Source Code
Overview
ETH Balance
0.001 ETH
Token Holdings
More Info
ContractCreator
Multi Chain
Multichain Addresses
0 address found via
Latest 8 from a total of 8 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Set Trusted Oper... | 4725540 | 10 days 14 hrs ago | IN | 0 ETH | 0.00009506 | ||||
Un Wrap | 4558291 | 35 days 22 hrs ago | IN | 0 ETH | 0.01368917 | ||||
Un Wrap | 4533633 | 39 days 15 hrs ago | IN | 0 ETH | 0.0002738 | ||||
Un Wrap | 4518681 | 41 days 20 hrs ago | IN | 0 ETH | 0.00037845 | ||||
Set WNFT Id | 4495155 | 45 days 15 hrs ago | IN | 0 ETH | 0.00014422 | ||||
Set Trusted Oper... | 4457088 | 51 days 14 hrs ago | IN | 0 ETH | 0.00084278 | ||||
Set White List | 4138244 | 99 days 15 hrs ago | IN | 0 ETH | 0.00080171 | ||||
0x60806040 | 4137033 | 99 days 19 hrs ago | IN | Create: TrustedWrapperV2 | 0 ETH | 0.19816876 |
Latest 1 internal transaction
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
4589976 | 31 days 7 hrs ago | 0.001 ETH |
Loading...
Loading
Contract Name:
TrustedWrapperV2
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) protocol V1 for NFT. import "WrapperBaseV1.sol"; pragma solidity 0.8.19; contract TrustedWrapperV2 is WrapperBaseV1 { mapping(address => bool) public trustedOperator; constructor (address _erc20, address _trusted) WrapperBaseV1(_erc20) { trustedOperator[_trusted] = true; } modifier onlyTrusted() { require (trustedOperator[msg.sender], "Only trusted address"); _; } function wrapUnsafe( ETypes.INData calldata _inData, ETypes.AssetItem[] calldata _collateral, address _wrappFor ) public virtual payable onlyTrusted nonReentrant returns (ETypes.AssetItem memory) { // 1. Take users inAsset ////////////////////////////////////////// // !!!! All transfer logic must // // be impemented in caller contract // // instead of here // ////////////////////////////////////////// // 2. Mint wNFT _mintNFT( _inData.outType, // what will be minted instead of wrapping asset lastWNFTId[_inData.outType].contractAddress, // wNFT contract address _wrappFor, // wNFT receiver (1st owner) lastWNFTId[_inData.outType].tokenId + 1, _inData.outBalance // wNFT tokenId ); lastWNFTId[_inData.outType].tokenId += 1; //Save just minted id // 4. Safe wNFT info _saveWNFTinfo( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, _inData ); ////////////////////////////////////////// // !!!! All add collateral logic must // // be impemented in caller contract // // instead of internal _addCollateral // ////////////////////////////////////////// for (uint256 i = 0; i <_collateral.length; i ++) { _updateCollateralInfo( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, _collateral[i] ); emit CollateralAdded( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, uint8(_collateral[i].asset.assetType), _collateral[i].asset.contractAddress, _collateral[i].tokenId, _collateral[i].amount ); } ////////////////////////////////////////// emit WrappedV1( _inData.inAsset.asset.contractAddress, // inAssetAddress lastWNFTId[_inData.outType].contractAddress, // outAssetAddress _inData.inAsset.tokenId, // inAssetTokenId lastWNFTId[_inData.outType].tokenId, // outTokenId _wrappFor, // wnftFirstOwner msg.value, // nativeCollateralAmount _inData.rules // rules ); return ETypes.AssetItem( ETypes.Asset(_inData.outType, lastWNFTId[_inData.outType].contractAddress), lastWNFTId[_inData.outType].tokenId, _inData.outBalance ); } function transferIn( ETypes.AssetItem memory _assetItem, address _from ) external onlyTrusted nonReentrant returns (uint256 _transferedValue) { return _transferSafe(_assetItem, _from, address(this)); } //////////////////////////////////////// // Admin functions /// //////////////////////////////////////// function setMaxCollateralSlots(uint256 _count) external onlyOwner { MAX_COLLATERAL_SLOTS = _count; } function setTrustedOperatorStatus(address _operator, bool _status) external onlyOwner { trustedOperator[_operator] = _status; } }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) protocol V1 for NFT. Wrapper - main protocol contract pragma solidity 0.8.19; import "Ownable.sol"; import "ERC721Holder.sol"; import "ERC1155Holder.sol"; import "ReentrancyGuard.sol"; import "IFeeRoyaltyModel.sol"; import "IWrapper.sol"; import "IAdvancedWhiteList.sol"; import "TokenService.sol"; // #### Envelop ProtocolV1 Rules // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 <= Bit number(dec) // ------------------------------------------------------------------------------------ // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 // | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | +-No_Unwrap // | | | | | | | | | | | | | | +-No_Wrap // | | | | | | | | | | | | | +-No_Transfer // | | | | | | | | | | | | +-No_Collateral // | | | | | | | | | | | +-reserved_core // | | | | | | | | | | +-reserved_core // | | | | | | | | | +-reserved_core // | | | | | | | | +-reserved_core // | | | | | | | | // | | | | | | | | // +----+----+----+----+----+---+---+ // for use in extendings /** * @title Non-Fungible Token Wrapper * @dev Make wraping for existing ERC721 & ERC1155 and empty */ contract WrapperBaseV1 is ReentrancyGuard, ERC721Holder, ERC1155Holder, IWrapper, TokenService, Ownable { uint256 public MAX_COLLATERAL_SLOTS = 25; address public protocolTechToken; address public protocolWhiteList; // Map from wrapping asset type to wnft contract address and last minted id mapping(ETypes.AssetType => ETypes.NFTItem) public lastWNFTId; // Map from wNFT address to it's type (721, 1155) mapping(address => ETypes.AssetType) public wnftTypes; // Map from wrapped token address and id => wNFT record mapping(address => mapping(uint256 => ETypes.WNFT)) internal wrappedTokens; constructor(address _erc20) { require(_erc20 != address(0), "ProtocolTechToken cant be zero value"); protocolTechToken = _erc20; // This because default trnaferFe moddel included in techToken code IFeeRoyaltyModel(protocolTechToken).registerModel(); } function wrap( ETypes.INData calldata _inData, ETypes.AssetItem[] calldata _collateral, address _wrappFor ) public virtual payable nonReentrant returns (ETypes.AssetItem memory) { // 0. Check assetIn asset require(_checkWrap(_inData,_wrappFor), "Wrap check fail" ); // 1. Take users inAsset if ( _inData.inAsset.asset.assetType != ETypes.AssetType.NATIVE && _inData.inAsset.asset.assetType != ETypes.AssetType.EMPTY ) { require( _mustTransfered(_inData.inAsset) == _transferSafe( _inData.inAsset, msg.sender, address(this) ), "Suspicious asset for wrap" ); } // 2. Mint wNFT lastWNFTId[_inData.outType].tokenId += 1; //Save just will minted id _mintNFT( _inData.outType, // what will be minted instead of wrapping asset lastWNFTId[_inData.outType].contractAddress, // wNFT contract address _wrappFor, // wNFT receiver (1st owner) lastWNFTId[_inData.outType].tokenId, _inData.outBalance // wNFT tokenId ); // 3. Safe wNFT info _saveWNFTinfo( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, _inData ); addCollateral( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, _collateral ); // Charge Fee Hook // There is No Any Fees in Protocol // So this hook can be used in b2b extensions of Envelop Protocol // 0x02 - feeType for WrapFee _chargeFees( lastWNFTId[_inData.outType].contractAddress, lastWNFTId[_inData.outType].tokenId, msg.sender, address(this), 0x02 ); emit WrappedV1( _inData.inAsset.asset.contractAddress, // inAssetAddress lastWNFTId[_inData.outType].contractAddress, // outAssetAddress _inData.inAsset.tokenId, // inAssetTokenId lastWNFTId[_inData.outType].tokenId, // outTokenId _wrappFor, // wnftFirstOwner msg.value, // nativeCollateralAmount _inData.rules // rules ); return ETypes.AssetItem( ETypes.Asset(_inData.outType, lastWNFTId[_inData.outType].contractAddress), lastWNFTId[_inData.outType].tokenId, _inData.outBalance ); } function addCollateral( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem[] calldata _collateral ) public payable virtual { if (_collateral.length > 0 || msg.value > 0) { require( _checkAddCollateral( _wNFTAddress, _wNFTTokenId, _collateral ), "Forbidden add collateral" ); _addCollateral( _wNFTAddress, _wNFTTokenId, _collateral ); } } function unWrap(address _wNFTAddress, uint256 _wNFTTokenId) external virtual { unWrap(wnftTypes[_wNFTAddress], _wNFTAddress, _wNFTTokenId, false); } function unWrap( ETypes.AssetType _wNFTType, address _wNFTAddress, uint256 _wNFTTokenId ) external virtual { unWrap(_wNFTType, _wNFTAddress, _wNFTTokenId, false); } function unWrap( ETypes.AssetType _wNFTType, address _wNFTAddress, uint256 _wNFTTokenId, bool _isEmergency ) public virtual { // 1. Check core protocol logic: // - who and what possible to unwrap (address burnFor, uint256 burnBalance) = _checkCoreUnwrap(_wNFTType, _wNFTAddress, _wNFTTokenId); // 2. Check locks = move to _checkUnwrap require( _checkLocks(_wNFTAddress, _wNFTTokenId) ); // 3. Charge Fee Hook // There is No Any Fees in Protocol // So this hook can be used in b2b extensions of Envelop Protocol // 0x03 - feeType for UnWrapFee // _chargeFees(_wNFTAddress, _wNFTTokenId, msg.sender, address(this), 0x03); (uint256 nativeCollateralAmount, ) = getCollateralBalanceAndIndex( _wNFTAddress, _wNFTTokenId, ETypes.AssetType.NATIVE, address(0), 0 ); /////////////////////////////////////////////// /// Place for hook //// /////////////////////////////////////////////// // 4. Safe return collateral to appropriate benificiary if (!_beforeUnWrapHook(_wNFTAddress, _wNFTTokenId, _isEmergency)) { return; } // 5. BurnWNFT _burnNFT( _wNFTType, _wNFTAddress, burnFor, // msg.sender, _wNFTTokenId, burnBalance ); emit UnWrappedV1( _wNFTAddress, wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset.asset.contractAddress, _wNFTTokenId, wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset.tokenId, wrappedTokens[_wNFTAddress][_wNFTTokenId].unWrapDestination, nativeCollateralAmount, // TODO Check GAS wrappedTokens[_wNFTAddress][_wNFTTokenId].rules ); } function chargeFees( address _wNFTAddress, uint256 _wNFTTokenId, address _from, address _to, bytes1 _feeType ) public virtual returns (bool charged) { //TODO only wNFT contract can execute this(=charge fee) require(msg.sender == _wNFTAddress || msg.sender == address(this), "Only for wNFT or wrapper" ); require(_chargeFees(_wNFTAddress, _wNFTTokenId, _from, _to, _feeType), "Fee charge fail" ); charged = true; } ///////////////////////////////////////////////////////////////////// // Admin functions // ///////////////////////////////////////////////////////////////////// function setWNFTId( ETypes.AssetType _assetOutType, address _wnftContract, uint256 _tokenId ) external onlyOwner { require(_wnftContract != address(0), "No zero address"); lastWNFTId[_assetOutType] = ETypes.NFTItem(_wnftContract, _tokenId); wnftTypes[_wnftContract] = _assetOutType; } function setWhiteList(address _wlAddress) external onlyOwner { protocolWhiteList = _wlAddress; } ///////////////////////////////////////////////////////////////////// function getWrappedToken(address _wNFTAddress, uint256 _wNFTTokenId) public view returns (ETypes.WNFT memory) { return wrappedTokens[_wNFTAddress][_wNFTTokenId]; } function getOriginalURI(address _wNFTAddress, uint256 _wNFTTokenId) public view returns(string memory uri_) { ETypes.AssetItem memory _wnftInAsset = getWrappedToken( _wNFTAddress, _wNFTTokenId ).inAsset; if (_wnftInAsset.asset.assetType == ETypes.AssetType.ERC721) { uri_ = IERC721Metadata(_wnftInAsset.asset.contractAddress).tokenURI(_wnftInAsset.tokenId); } else if (_wnftInAsset.asset.assetType == ETypes.AssetType.ERC1155) { uri_ = IERC1155MetadataURI(_wnftInAsset.asset.contractAddress).uri(_wnftInAsset.tokenId); } else { uri_ = ''; } } function getCollateralBalanceAndIndex( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetType _collateralType, address _erc, uint256 _tokenId ) public view returns (uint256, uint256) { for (uint256 i = 0; i < wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length; i ++) { if (wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].asset.contractAddress == _erc && wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].tokenId == _tokenId && wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].asset.assetType == _collateralType ) { return (wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].amount, i); } } } ///////////////////////////////////////////////////////////////////// // Internals // ///////////////////////////////////////////////////////////////////// function _saveWNFTinfo( address wNFTAddress, uint256 tokenId, ETypes.INData calldata _inData ) internal virtual { wrappedTokens[wNFTAddress][tokenId].inAsset = _inData.inAsset; // We will use _inData.unWrapDestination ONLY for RENT implementation // wrappedTokens[wNFTAddress][tokenId].unWrapDestination = _inData.unWrapDestination; wrappedTokens[wNFTAddress][tokenId].unWrapDestination = address(0); wrappedTokens[wNFTAddress][tokenId].rules = _inData.rules; // Copying of type struct ETypes.Fee memory[] // memory to storage not yet supported. for (uint256 i = 0; i < _inData.fees.length; i ++) { wrappedTokens[wNFTAddress][tokenId].fees.push(_inData.fees[i]); } for (uint256 i = 0; i < _inData.locks.length; i ++) { wrappedTokens[wNFTAddress][tokenId].locks.push(_inData.locks[i]); } for (uint256 i = 0; i < _inData.royalties.length; i ++) { wrappedTokens[wNFTAddress][tokenId].royalties.push(_inData.royalties[i]); } } function _addCollateral( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem[] calldata _collateral ) internal virtual { // Process Native Colleteral if (msg.value > 0) { _updateCollateralInfo( _wNFTAddress, _wNFTTokenId, ETypes.AssetItem( ETypes.Asset(ETypes.AssetType.NATIVE, address(0)), 0, msg.value ) ); emit CollateralAdded( _wNFTAddress, _wNFTTokenId, uint8(ETypes.AssetType.NATIVE), address(0), 0, msg.value ); } // Process Token Colleteral for (uint256 i = 0; i <_collateral.length; i ++) { if (_collateral[i].asset.assetType != ETypes.AssetType.NATIVE) { // Check WhiteList Logic if (protocolWhiteList != address(0)) { require( IAdvancedWhiteList(protocolWhiteList).enabledForCollateral( _collateral[i].asset.contractAddress), "WL:Some assets are not enabled for collateral" ); } require( _mustTransfered(_collateral[i]) == _transferSafe( _collateral[i], msg.sender, address(this) ), "Suspicious asset for wrap" ); _updateCollateralInfo( _wNFTAddress, _wNFTTokenId, _collateral[i] ); emit CollateralAdded( _wNFTAddress, _wNFTTokenId, uint8(_collateral[i].asset.assetType), _collateral[i].asset.contractAddress, _collateral[i].tokenId, _collateral[i].amount ); } } } function _updateCollateralInfo( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem memory collateralItem ) internal virtual { ///////////////////////////////////////// // ERC20 & NATIVE Collateral /// ///////////////////////////////////////// if (collateralItem.asset.assetType == ETypes.AssetType.ERC20 || collateralItem.asset.assetType == ETypes.AssetType.NATIVE) { require(collateralItem.tokenId == 0, "TokenId must be zero"); } ///////////////////////////////////////// // ERC1155 Collateral /// // ///////////////////////////////////////// // if (collateralItem.asset.assetType == ETypes.AssetType.ERC1155) { // No need special checks // } ///////////////////////////////////////// // ERC721 Collateral /// ///////////////////////////////////////// if (collateralItem.asset.assetType == ETypes.AssetType.ERC721 ) { require(collateralItem.amount == 0, "Amount must be zero"); } ///////////////////////////////////////// if (wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length == 0 || collateralItem.asset.assetType == ETypes.AssetType.ERC721 ) { // First record in collateral or 721 _newCollateralItem(_wNFTAddress,_wNFTTokenId,collateralItem); } else { // length > 0 (, uint256 _index) = getCollateralBalanceAndIndex( _wNFTAddress, _wNFTTokenId, collateralItem.asset.assetType, collateralItem.asset.contractAddress, collateralItem.tokenId ); if (_index > 0 || (_index == 0 && wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[0].asset.contractAddress == collateralItem.asset.contractAddress ) ) { // We dont need addition if for erc721 because for erc721 _amnt always be zero wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[_index].amount += collateralItem.amount; } else { // _index == 0 && and no this token record yet _newCollateralItem(_wNFTAddress,_wNFTTokenId,collateralItem); } } } function _newCollateralItem( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem memory collateralItem ) internal virtual { require( wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length < MAX_COLLATERAL_SLOTS, "Too much tokens in collateral" ); for (uint256 i = 0; i < wrappedTokens[_wNFTAddress][_wNFTTokenId].locks.length; i ++) { // Personal Collateral count Lock check if (wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].lockType == 0x02) { require( wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].param >= (wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length + 1), "Too much collateral slots for this wNFT" ); } } wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.push(collateralItem); } function _chargeFees( address _wNFTAddress, uint256 _wNFTTokenId, address _from, address _to, bytes1 _feeType ) internal virtual returns (bool _charged) { if (_feeType == 0x00) {// Transfer fee for (uint256 i = 0; i < wrappedTokens[_wNFTAddress][_wNFTTokenId].fees.length; i ++){ ///////////////////////////////////////// // For Transfer Fee -0x00 /// ///////////////////////////////////////// if (wrappedTokens[_wNFTAddress][_wNFTTokenId].fees[i].feeType == 0x00){ // - get modelAddress. Default feeModel adddress always live in // protocolTechToken. When white list used it is possible override that model. // default model always must be set as protocolTechToken address feeModel = protocolTechToken; if (protocolWhiteList != address(0)) { feeModel = IAdvancedWhiteList(protocolWhiteList).getWLItem( wrappedTokens[_wNFTAddress][_wNFTTokenId].fees[i].token).transferFeeModel; } // - get transfer list from external model by feetype(with royalties) (ETypes.AssetItem[] memory assetItems, address[] memory from, address[] memory to ) = IFeeRoyaltyModel(feeModel).getTransfersList( wrappedTokens[_wNFTAddress][_wNFTTokenId].fees[i], wrappedTokens[_wNFTAddress][_wNFTTokenId].royalties, _from, _to ); // - execute transfers uint256 actualTransfered; for (uint256 j = 0; j < to.length; j ++){ // if transfer receiver(to) = address(this) lets consider // wNFT as receiver. in this case received amount // will be added to collateral if (to[j]== address(this)){ _updateCollateralInfo( _wNFTAddress, _wNFTTokenId, assetItems[j] ); } actualTransfered = _transferSafe(assetItems[j], from[j], to[j]); emit EnvelopFee(to[j], _wNFTAddress, _wNFTTokenId, actualTransfered); } } ////////////////////////////////////////// } _charged = true; } } /** * @dev This hook may be overriden in inheritor contracts for extend * base functionality. * * @param _wNFTAddress -wrapped token address * @param _wNFTTokenId -wrapped token id * * must returns true for success unwrapping enable */ function _beforeUnWrapHook( address _wNFTAddress, uint256 _wNFTTokenId, bool _emergency ) internal virtual returns (bool) { uint256 transfered; address receiver = msg.sender; if (wrappedTokens[_wNFTAddress][_wNFTTokenId].unWrapDestination != address(0)) { receiver = wrappedTokens[_wNFTAddress][_wNFTTokenId].unWrapDestination; } for (uint256 i = 0; i < wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length; i ++) { if (wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].asset.assetType != ETypes.AssetType.EMPTY ) { if (_emergency) { // In case of something is wrong with any collateral (attack) // user can use this mode for skip malicious asset transfered = _transferEmergency( wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i], address(this), receiver ); } else { transfered = _transferSafe( wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i], address(this), receiver ); } // we collect info about contracts with not standard behavior if (transfered != wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].amount ) { emit SuspiciousFail( _wNFTAddress, _wNFTTokenId, wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].asset.contractAddress ); } // mark collateral record as returned wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral[i].asset.assetType = ETypes.AssetType.EMPTY; } // dont pop due in some case it c can be very costly // https://docs.soliditylang.org/en/v0.8.9/types.html#array-members // For safe exit in case of low gaslimit // this strange part of code can prevent only case // when when some collateral tokens spent unexpected gas limit if ( gasleft() <= 1_000 && i < wrappedTokens[_wNFTAddress][_wNFTTokenId].collateral.length - 1 ) { emit PartialUnWrapp(_wNFTAddress, _wNFTTokenId, i); //allReturned = false; return false; } } // 5. Return Original if (wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset.asset.assetType != ETypes.AssetType.NATIVE && wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset.asset.assetType != ETypes.AssetType.EMPTY ) { if (!_emergency){ _transferSafe( wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset, address(this), receiver ); } else { _transferEmergency ( wrappedTokens[_wNFTAddress][_wNFTTokenId].inAsset, address(this), receiver ); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////// function _mustTransfered(ETypes.AssetItem calldata _assetForTransfer) internal pure returns (uint256 mustTransfered) { // Available for wrap assets must be good transferable (stakable). // So for erc721 mustTransfered always be 1 if (_assetForTransfer.asset.assetType == ETypes.AssetType.ERC721) { mustTransfered = 1; } else { mustTransfered = _assetForTransfer.amount; } } function _checkRule(bytes2 _rule, bytes2 _wNFTrules) internal pure returns (bool) { return _rule == (_rule & _wNFTrules); } // 0x00 - TimeLock // 0x01 - TransferFeeLock // 0x02 - Personal Collateral count Lock check function _checkLocks(address _wNFTAddress, uint256 _wNFTTokenId) internal view returns (bool) { // Lets check that inAsset for (uint256 i = 0; i < wrappedTokens[_wNFTAddress][_wNFTTokenId].locks.length; i ++) { // Time Lock check if (wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].lockType == 0x00) { require( wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].param <= block.timestamp, "TimeLock error" ); } // Fee Lock check if (wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].lockType == 0x01) { // Lets check this lock rule against each fee record for (uint256 j = 0; j < wrappedTokens[_wNFTAddress][_wNFTTokenId].fees.length; j ++){ // Fee Lock depend only from Transfer Fee - 0x00 if ( wrappedTokens[_wNFTAddress][_wNFTTokenId].fees[j].feeType == 0x00) { (uint256 _bal,) = getCollateralBalanceAndIndex( _wNFTAddress, _wNFTTokenId, ETypes.AssetType.ERC20, wrappedTokens[_wNFTAddress][_wNFTTokenId].fees[j].token, 0 ); require( wrappedTokens[_wNFTAddress][_wNFTTokenId].locks[i].param <= _bal, "TransferFeeLock error" ); } } } } return true; } function _checkWrap(ETypes.INData calldata _inData, address _wrappFor) internal view returns (bool enabled) { // Lets check that inAsset // 0x0002 - this rule disable wrap already wrappednFT (NO matryoshka) enabled = !_checkRule(0x0002, getWrappedToken( _inData.inAsset.asset.contractAddress, _inData.inAsset.tokenId).rules ) && _wrappFor != address(this); // Check WhiteList Logic if (protocolWhiteList != address(0)) { require( !IAdvancedWhiteList(protocolWhiteList).getBLItem(_inData.inAsset.asset.contractAddress), "WL:Asset disabled for wrap" ); require( IAdvancedWhiteList(protocolWhiteList).rulesEnabled(_inData.inAsset.asset.contractAddress, _inData.rules), "WL:Some rules are disabled for this asset" ); for (uint256 i = 0; i < _inData.fees.length; i ++){ require( IAdvancedWhiteList(protocolWhiteList).enabledForFee( _inData.fees[i].token), "WL:Some assets are not enabled for fee" ); } } } function _checkAddCollateral( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem[] calldata _collateral ) internal view returns (bool enabled) { // Check that wNFT exist if (wnftTypes[_wNFTAddress] == ETypes.AssetType.ERC721) { require(IERC721Mintable(_wNFTAddress).exists(_wNFTTokenId), "wNFT not exists"); } else if(wnftTypes[_wNFTAddress] == ETypes.AssetType.ERC1155) { require(IERC1155Mintable(_wNFTAddress).exists(_wNFTTokenId), "wNFT not exists"); } else { revert UnSupportedAsset( ETypes.AssetItem(ETypes.Asset(wnftTypes[_wNFTAddress],_wNFTAddress),_wNFTTokenId, 0) ); } // Lets check wNFT rules // 0x0008 - this rule disable add collateral enabled = !_checkRule(0x0008, getWrappedToken(_wNFTAddress, _wNFTTokenId).rules); } function _checkCoreUnwrap( ETypes.AssetType _wNFTType, address _wNFTAddress, uint256 _wNFTTokenId ) internal view virtual returns (address burnFor, uint256 burnBalance) { // Lets wNFT rules // 0x0001 - this rule disable unwrap wrappednFT require(!_checkRule(0x0001, getWrappedToken(_wNFTAddress, _wNFTTokenId).rules), "UnWrapp forbidden by author" ); if (_wNFTType == ETypes.AssetType.ERC721) { // Only token owner can UnWrap burnFor = IERC721Mintable(_wNFTAddress).ownerOf(_wNFTTokenId); require(burnFor == msg.sender, 'Only owner can unwrap it' ); } else if (_wNFTType == ETypes.AssetType.ERC1155) { burnBalance = IERC1155Mintable(_wNFTAddress).totalSupply(_wNFTTokenId); burnFor = msg.sender; require( burnBalance == IERC1155Mintable(_wNFTAddress).balanceOf(burnFor, _wNFTTokenId) ,'ERC115 unwrap available only for all totalSupply' ); } else { revert UnSupportedAsset(ETypes.AssetItem(ETypes.Asset(_wNFTType,_wNFTAddress),_wNFTTokenId, 0)); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "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 (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 v4.4.1 (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.0; import "IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address, address, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC721Received.selector; } }
// 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 (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "IERC1155Receiver.sol"; import "ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// 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 (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.8.0) (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() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "LibEnvelopTypes.sol"; interface IFeeRoyaltyModel { function registerModel() external; function getTransfersList( ETypes.Fee calldata _fee, ETypes.Royalty[] calldata _royalties, address _from, address _to ) external view returns ( ETypes.AssetItem[] memory, address[] memory, address[] memory ); function wrapper() external returns (address); }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) protocol V1 for NFT. pragma solidity 0.8.19; /// @title Flibrary ETypes in Envelop PrtocolV1 /// @author Envelop Team /// @notice This contract implement main protocol's data types library ETypes { enum AssetType {EMPTY, NATIVE, ERC20, ERC721, ERC1155, FUTURE1, FUTURE2, FUTURE3} struct Asset { AssetType assetType; address contractAddress; } struct AssetItem { Asset asset; uint256 tokenId; uint256 amount; } struct NFTItem { address contractAddress; uint256 tokenId; } struct Fee { bytes1 feeType; uint256 param; address token; } struct Lock { bytes1 lockType; uint256 param; } struct Royalty { address beneficiary; uint16 percent; } struct WNFT { AssetItem inAsset; AssetItem[] collateral; address unWrapDestination; Fee[] fees; Lock[] locks; Royalty[] royalties; bytes2 rules; } struct INData { AssetItem inAsset; address unWrapDestination; Fee[] fees; Lock[] locks; Royalty[] royalties; AssetType outType; uint256 outBalance; //0- for 721 and any amount for 1155 bytes2 rules; } struct WhiteListItem { bool enabledForFee; bool enabledForCollateral; bool enabledRemoveFromCollateral; address transferFeeModel; } struct Rules { bytes2 onlythis; bytes2 disabled; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; //import "IERC721Enumerable.sol"; import "LibEnvelopTypes.sol"; interface IWrapper { event WrappedV1( address indexed inAssetAddress, address indexed outAssetAddress, uint256 indexed inAssetTokenId, uint256 outTokenId, address wnftFirstOwner, uint256 nativeCollateralAmount, bytes2 rules ); event UnWrappedV1( address indexed wrappedAddress, address indexed originalAddress, uint256 indexed wrappedId, uint256 originalTokenId, address beneficiary, uint256 nativeCollateralAmount, bytes2 rules ); event CollateralAdded( address indexed wrappedAddress, uint256 indexed wrappedId, uint8 assetType, address collateralAddress, uint256 collateralTokenId, uint256 collateralBalance ); event PartialUnWrapp( address indexed wrappedAddress, uint256 indexed wrappedId, uint256 lastCollateralIndex ); event SuspiciousFail( address indexed wrappedAddress, uint256 indexed wrappedId, address indexed failedContractAddress ); event EnvelopFee( address indexed receiver, address indexed wNFTConatract, uint256 indexed wNFTTokenId, uint256 amount ); function wrap( ETypes.INData calldata _inData, ETypes.AssetItem[] calldata _collateral, address _wrappFor ) external payable returns (ETypes.AssetItem memory); // function wrapUnsafe( // ETypes.INData calldata _inData, // ETypes.AssetItem[] calldata _collateral, // address _wrappFor // ) // external // payable // returns (ETypes.AssetItem memory); function addCollateral( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetItem[] calldata _collateral ) external payable; // function addCollateralUnsafe( // address _wNFTAddress, // uint256 _wNFTTokenId, // ETypes.AssetItem[] calldata _collateral // ) // external // payable; function unWrap( address _wNFTAddress, uint256 _wNFTTokenId ) external; function unWrap( ETypes.AssetType _wNFTType, address _wNFTAddress, uint256 _wNFTTokenId ) external; function unWrap( ETypes.AssetType _wNFTType, address _wNFTAddress, uint256 _wNFTTokenId, bool _isEmergency ) external; function chargeFees( address _wNFTAddress, uint256 _wNFTTokenId, address _from, address _to, bytes1 _feeType ) external returns (bool); ////////////////////////////////////////////////////////////////////// function MAX_COLLATERAL_SLOTS() external view returns (uint256); function protocolTechToken() external view returns (address); function protocolWhiteList() external view returns (address); //function trustedOperators(address _operator) external view returns (bool); //function lastWNFTId(ETypes.AssetType _assetType) external view returns (ETypes.NFTItem); function getWrappedToken(address _wNFTAddress, uint256 _wNFTTokenId) external view returns (ETypes.WNFT memory); function getOriginalURI(address _wNFTAddress, uint256 _wNFTTokenId) external view returns(string memory); function getCollateralBalanceAndIndex( address _wNFTAddress, uint256 _wNFTTokenId, ETypes.AssetType _collateralType, address _erc, uint256 _tokenId ) external view returns (uint256, uint256); }
// 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 pragma solidity 0.8.19; //import "IERC721Enumerable.sol"; import "LibEnvelopTypes.sol"; interface IAdvancedWhiteList { event WhiteListItemChanged( address indexed asset, bool enabledForFee, bool enabledForCollateral, bool enabledRemoveFromCollateral, address transferFeeModel ); event BlackListItemChanged( address indexed asset, bool isBlackListed ); function getWLItem(address _asset) external view returns (ETypes.WhiteListItem memory); function getWLItemCount() external view returns (uint256); function getBLItem(address _asset) external view returns (bool); function getBLItemCount() external view returns (uint256); function enabledForCollateral(address _asset) external view returns (bool); function enabledForFee(address _asset) external view returns (bool); function enabledRemoveFromCollateral(address _asset) external view returns (bool); function rulesEnabled(address _asset, bytes2 _rules) external view returns (bool); function validateRules(address _asset, bytes2 _rules) external view returns (bytes2); }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) protocol V1 for NFT. Wrapper - main protocol contract pragma solidity 0.8.19; import "SafeERC20.sol"; import "IERC20Extended.sol"; import "LibEnvelopTypes.sol"; import "IERC721Mintable.sol"; import "IERC1155Mintable.sol"; /// @title Envelop PrtocolV1 helper service for ERC(20, 721, 115) transfers /// @author Envelop Team /// @notice Just as dependence for main wrapper contract abstract contract TokenService { using SafeERC20 for IERC20Extended; error UnSupportedAsset(ETypes.AssetItem asset); function _mintNFT( ETypes.AssetType _mint_type, address _contract, address _mintFor, uint256 _tokenId, uint256 _outBalance ) internal virtual { if (_mint_type == ETypes.AssetType.ERC721) { IERC721Mintable(_contract).mint(_mintFor, _tokenId); } else if (_mint_type == ETypes.AssetType.ERC1155) { IERC1155Mintable(_contract).mint(_mintFor, _tokenId, _outBalance); }else { revert UnSupportedAsset( ETypes.AssetItem( ETypes.Asset(_mint_type, _contract), _tokenId, _outBalance ) ); } } function _burnNFT( ETypes.AssetType _burn_type, address _contract, address _burnFor, uint256 _tokenId, uint256 _balance ) internal virtual { if (_burn_type == ETypes.AssetType.ERC721) { IERC721Mintable(_contract).burn(_tokenId); } else if (_burn_type == ETypes.AssetType.ERC1155) { IERC1155Mintable(_contract).burn(_burnFor, _tokenId, _balance); } } function _transfer( ETypes.AssetItem memory _assetItem, address _from, address _to ) internal virtual returns (bool _transfered){ if (_assetItem.asset.assetType == ETypes.AssetType.NATIVE) { (bool success, ) = _to.call{ value: _assetItem.amount}(""); require(success, "transfer failed"); _transfered = true; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC20) { require(IERC20Extended(_assetItem.asset.contractAddress).balanceOf(_from) <= _assetItem.amount, "UPS!!!!"); IERC20Extended(_assetItem.asset.contractAddress).safeTransferFrom(_from, _to, _assetItem.amount); _transfered = true; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC721) { IERC721Mintable(_assetItem.asset.contractAddress).transferFrom(_from, _to, _assetItem.tokenId); _transfered = true; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC1155) { IERC1155Mintable(_assetItem.asset.contractAddress).safeTransferFrom(_from, _to, _assetItem.tokenId, _assetItem.amount, ""); _transfered = true; } else { revert UnSupportedAsset(_assetItem); } return _transfered; } function _transferSafe( ETypes.AssetItem memory _assetItem, address _from, address _to ) internal virtual returns (uint256 _transferedValue){ //TODO think about try catch in transfers uint256 balanceBefore; if (_assetItem.asset.assetType == ETypes.AssetType.NATIVE) { balanceBefore = _to.balance; (bool success, ) = _to.call{ value: _assetItem.amount}(""); require(success, "transfer failed"); _transferedValue = _to.balance - balanceBefore; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC20) { balanceBefore = IERC20Extended(_assetItem.asset.contractAddress).balanceOf(_to); if (_from == address(this)){ IERC20Extended(_assetItem.asset.contractAddress).safeTransfer(_to, _assetItem.amount); } else { IERC20Extended(_assetItem.asset.contractAddress).safeTransferFrom(_from, _to, _assetItem.amount); } _transferedValue = IERC20Extended(_assetItem.asset.contractAddress).balanceOf(_to) - balanceBefore; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC721 && IERC721Mintable(_assetItem.asset.contractAddress).ownerOf(_assetItem.tokenId) == _from) { balanceBefore = IERC721Mintable(_assetItem.asset.contractAddress).balanceOf(_to); IERC721Mintable(_assetItem.asset.contractAddress).transferFrom(_from, _to, _assetItem.tokenId); if (IERC721Mintable(_assetItem.asset.contractAddress).ownerOf(_assetItem.tokenId) == _to && IERC721Mintable(_assetItem.asset.contractAddress).balanceOf(_to) - balanceBefore == 1 ) { _transferedValue = 1; } } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC1155) { balanceBefore = IERC1155Mintable(_assetItem.asset.contractAddress).balanceOf(_to, _assetItem.tokenId); IERC1155Mintable(_assetItem.asset.contractAddress).safeTransferFrom(_from, _to, _assetItem.tokenId, _assetItem.amount, ""); _transferedValue = IERC1155Mintable(_assetItem.asset.contractAddress).balanceOf(_to, _assetItem.tokenId) - balanceBefore; } else { revert UnSupportedAsset(_assetItem); } return _transferedValue; } // This function must never revert. Use it for unwrap in case some // collateral transfers are revert function _transferEmergency( ETypes.AssetItem memory _assetItem, address _from, address _to ) internal virtual returns (uint256 _transferedValue){ //TODO think about try catch in transfers uint256 balanceBefore; if (_assetItem.asset.assetType == ETypes.AssetType.NATIVE) { balanceBefore = _to.balance; (bool success, ) = _to.call{ value: _assetItem.amount}(""); //require(success, "transfer failed"); _transferedValue = _to.balance - balanceBefore; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC20) { if (_from == address(this)){ (bool success, ) = _assetItem.asset.contractAddress.call( abi.encodeWithSignature("transfer(address,uint256)", _to, _assetItem.amount) ); } else { (bool success, ) = _assetItem.asset.contractAddress.call( abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _assetItem.amount) ); } _transferedValue = _assetItem.amount; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC721) { (bool success, ) = _assetItem.asset.contractAddress.call( abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _assetItem.tokenId) ); _transferedValue = 1; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC1155) { (bool success, ) = _assetItem.asset.contractAddress.call( abi.encodeWithSignature("safeTransferFrom(address,address,uint256,uint256,bytes)", _from, _to, _assetItem.tokenId, _assetItem.amount, "") ); _transferedValue = _assetItem.amount; } else { revert UnSupportedAsset(_assetItem); } return _transferedValue; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "IERC20.sol"; import "draft-IERC20Permit.sol"; import "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/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 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.8.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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 pragma solidity 0.8.19; import "IERC20.sol"; interface IERC20Extended is IERC20 { function mint(address _to, uint256 _value) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "IERC721Metadata.sol"; interface IERC721Mintable is IERC721Metadata { function mint(address _to, uint256 _tokenId) external; function burn(uint256 _tokenId) external; function exists(uint256 _tokenId) 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 pragma solidity 0.8.19; import "IERC1155MetadataURI.sol"; interface IERC1155Mintable is IERC1155MetadataURI { function mint(address _to, uint256 _tokenId, uint256 _amount) external; function burn(address _to, uint256 _tokenId, uint256 _amount) external; function totalSupply(uint256 _id) external view returns (uint256); function exists(uint256 _tokenId) external view returns(bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "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; }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "TrustedWrapperV2.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"address","name":"_erc20","type":"address"},{"internalType":"address","name":"_trusted","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"asset","type":"tuple"}],"name":"UnSupportedAsset","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wrappedAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"wrappedId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"assetType","type":"uint8"},{"indexed":false,"internalType":"address","name":"collateralAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralBalance","type":"uint256"}],"name":"CollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"wNFTConatract","type":"address"},{"indexed":true,"internalType":"uint256","name":"wNFTTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EnvelopFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wrappedAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"wrappedId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastCollateralIndex","type":"uint256"}],"name":"PartialUnWrapp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wrappedAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"wrappedId","type":"uint256"},{"indexed":true,"internalType":"address","name":"failedContractAddress","type":"address"}],"name":"SuspiciousFail","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wrappedAddress","type":"address"},{"indexed":true,"internalType":"address","name":"originalAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"wrappedId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"originalTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"nativeCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"bytes2","name":"rules","type":"bytes2"}],"name":"UnWrappedV1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"inAssetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"outAssetAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"inAssetTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outTokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"wnftFirstOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"nativeCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"bytes2","name":"rules","type":"bytes2"}],"name":"WrappedV1","type":"event"},{"inputs":[],"name":"MAX_COLLATERAL_SLOTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"},{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem[]","name":"_collateral","type":"tuple[]"}],"name":"addCollateral","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes1","name":"_feeType","type":"bytes1"}],"name":"chargeFees","outputs":[{"internalType":"bool","name":"charged","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"},{"internalType":"enum ETypes.AssetType","name":"_collateralType","type":"uint8"},{"internalType":"address","name":"_erc","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getCollateralBalanceAndIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"}],"name":"getOriginalURI","outputs":[{"internalType":"string","name":"uri_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"}],"name":"getWrappedToken","outputs":[{"components":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"inAsset","type":"tuple"},{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem[]","name":"collateral","type":"tuple[]"},{"internalType":"address","name":"unWrapDestination","type":"address"},{"components":[{"internalType":"bytes1","name":"feeType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct ETypes.Fee[]","name":"fees","type":"tuple[]"},{"components":[{"internalType":"bytes1","name":"lockType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"}],"internalType":"struct ETypes.Lock[]","name":"locks","type":"tuple[]"},{"components":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint16","name":"percent","type":"uint16"}],"internalType":"struct ETypes.Royalty[]","name":"royalties","type":"tuple[]"},{"internalType":"bytes2","name":"rules","type":"bytes2"}],"internalType":"struct ETypes.WNFT","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ETypes.AssetType","name":"","type":"uint8"}],"name":"lastWNFTId","outputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","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":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolTechToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolWhiteList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"setMaxCollateralSlots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setTrustedOperatorStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ETypes.AssetType","name":"_assetOutType","type":"uint8"},{"internalType":"address","name":"_wnftContract","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"setWNFTId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wlAddress","type":"address"}],"name":"setWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"_assetItem","type":"tuple"},{"internalType":"address","name":"_from","type":"address"}],"name":"transferIn","outputs":[{"internalType":"uint256","name":"_transferedValue","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"trustedOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ETypes.AssetType","name":"_wNFTType","type":"uint8"},{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"},{"internalType":"bool","name":"_isEmergency","type":"bool"}],"name":"unWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ETypes.AssetType","name":"_wNFTType","type":"uint8"},{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"}],"name":"unWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wNFTAddress","type":"address"},{"internalType":"uint256","name":"_wNFTTokenId","type":"uint256"}],"name":"unWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wnftTypes","outputs":[{"internalType":"enum ETypes.AssetType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"inAsset","type":"tuple"},{"internalType":"address","name":"unWrapDestination","type":"address"},{"components":[{"internalType":"bytes1","name":"feeType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct ETypes.Fee[]","name":"fees","type":"tuple[]"},{"components":[{"internalType":"bytes1","name":"lockType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"}],"internalType":"struct ETypes.Lock[]","name":"locks","type":"tuple[]"},{"components":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint16","name":"percent","type":"uint16"}],"internalType":"struct ETypes.Royalty[]","name":"royalties","type":"tuple[]"},{"internalType":"enum ETypes.AssetType","name":"outType","type":"uint8"},{"internalType":"uint256","name":"outBalance","type":"uint256"},{"internalType":"bytes2","name":"rules","type":"bytes2"}],"internalType":"struct ETypes.INData","name":"_inData","type":"tuple"},{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem[]","name":"_collateral","type":"tuple[]"},{"internalType":"address","name":"_wrappFor","type":"address"}],"name":"wrap","outputs":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"inAsset","type":"tuple"},{"internalType":"address","name":"unWrapDestination","type":"address"},{"components":[{"internalType":"bytes1","name":"feeType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"internalType":"struct ETypes.Fee[]","name":"fees","type":"tuple[]"},{"components":[{"internalType":"bytes1","name":"lockType","type":"bytes1"},{"internalType":"uint256","name":"param","type":"uint256"}],"internalType":"struct ETypes.Lock[]","name":"locks","type":"tuple[]"},{"components":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint16","name":"percent","type":"uint16"}],"internalType":"struct ETypes.Royalty[]","name":"royalties","type":"tuple[]"},{"internalType":"enum ETypes.AssetType","name":"outType","type":"uint8"},{"internalType":"uint256","name":"outBalance","type":"uint256"},{"internalType":"bytes2","name":"rules","type":"bytes2"}],"internalType":"struct ETypes.INData","name":"_inData","type":"tuple"},{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem[]","name":"_collateral","type":"tuple[]"},{"internalType":"address","name":"_wrappFor","type":"address"}],"name":"wrapUnsafe","outputs":[{"components":[{"components":[{"internalType":"enum ETypes.AssetType","name":"assetType","type":"uint8"},{"internalType":"address","name":"contractAddress","type":"address"}],"internalType":"struct ETypes.Asset","name":"asset","type":"tuple"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ETypes.AssetItem","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405260196002553480156200001657600080fd5b506040516200604b3803806200604b8339810160408190526200003991620001bc565b6001600055816200004a336200014d565b6001600160a01b038116620000b15760405162461bcd60e51b8152602060048201526024808201527f50726f746f636f6c54656368546f6b656e2063616e74206265207a65726f2076604482015263616c756560e01b606482015260840160405180910390fd5b600380546001600160a01b0319166001600160a01b03831690811790915560408051632dceecbb60e21b8152905163b73bb2ec9160048082019260009290919082900301818387803b1580156200010757600080fd5b505af11580156200011c573d6000803e3d6000fd5b5050506001600160a01b039092166000908152600860205260409020805460ff1916600117905550620001f4915050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b0381168114620001b757600080fd5b919050565b60008060408385031215620001d057600080fd5b620001db836200019f565b9150620001eb602084016200019f565b90509250929050565b615e4780620002046000396000f3fe6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063a50410401161008a578063f1551a9c11610064578063f1551a9c14610567578063f23a6e611461059c578063f2fde38b146105c8578063faf7d720146105e857600080fd5b8063a5041040146104fa578063bc197c811461051a578063c424d4f71461053a57600080fd5b8063980550ca116100c6578063980550ca146104845780639a251c291461049a5780639a7b0509146104ad578063a0c889f6146104da57600080fd5b80638da5cb5b1461042557806391ddb1461461044357806397da0ceb1461045657600080fd5b806339e899ee1161015957806351b5deec1161013357806351b5deec1461038357806366967cbb146103b3578063715018a6146103f05780637f6d4c931461040557600080fd5b806339e899ee1461032357806342fb01a8146103435780634d36d0851461036357600080fd5b80631fe438a2116101955780631fe438a214610262578063320a18dc14610284578063331758e6146102a45780633360aa3c146102c457600080fd5b806301ffc9a7146101bc57806310118ebb146101f1578063150b7a0214610229575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004614cdb565b610608565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b50600454610211906001600160a01b031681565b6040516001600160a01b0390911681526020016101e8565b34801561023557600080fd5b50610249610244366004614e27565b61063f565b6040516001600160e01b031990911681526020016101e8565b34801561026e57600080fd5b5061028261027d366004614ea0565b610650565b005b34801561029057600080fd5b5061028261029f366004614ee6565b610683565b3480156102b057600080fd5b50600354610211906001600160a01b031681565b3480156102d057600080fd5b506103046102df366004614f27565b600560205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b0390931683526020830191909152016101e8565b34801561032f57600080fd5b5061028261033e366004614f44565b61078b565b34801561034f57600080fd5b5061028261035e366004614f61565b6107b5565b610376610371366004614fff565b6108af565b6040516101e891906150e6565b34801561038f57600080fd5b506101dc61039e366004614f44565b60086020526000908152604090205460ff1681565b3480156103bf57600080fd5b506103e36103ce366004614f44565b60066020526000908152604090205460ff1681565b6040516101e891906150f4565b3480156103fc57600080fd5b50610282610f07565b34801561041157600080fd5b506101dc610420366004615118565b610f1b565b34801561043157600080fd5b506001546001600160a01b0316610211565b610282610451366004615180565b610fd6565b34801561046257600080fd5b5061047661047136600461524f565b61104d565b6040519081526020016101e8565b34801561049057600080fd5b5061047660025481565b6103766104a8366004614fff565b6110c2565b3480156104b957600080fd5b506104cd6104c836600461527c565b6114e9565b6040516101e891906152cc565b3480156104e657600080fd5b506102826104f53660046152ff565b61160c565b34801561050657600080fd5b50610282610515366004614ee6565b611619565b34801561052657600080fd5b506102496105353660046153a1565b61162b565b34801561054657600080fd5b5061055a61055536600461527c565b61163d565b6040516101e89190615579565b34801561057357600080fd5b50610587610582366004615646565b6119ae565b604080519283526020830191909152016101e8565b3480156105a857600080fd5b506102496105b73660046156a1565b63f23a6e6160e01b95945050505050565b3480156105d457600080fd5b506102826105e3366004614f44565b611b85565b3480156105f457600080fd5b5061028261060336600461527c565b611bfe565b60006001600160e01b03198216630271189760e51b148061063957506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610658611c2e565b6001600160a01b03919091166000908152600860205260409020805460ff1916911515919091179055565b61068b611c2e565b6001600160a01b0382166106d85760405162461bcd60e51b815260206004820152600f60248201526e4e6f207a65726f206164647265737360881b60448201526064015b60405180910390fd5b6040518060400160405280836001600160a01b03168152602001828152506005600085600781111561070c5761070c615078565b600781111561071d5761071d615078565b815260208082019290925260409081016000908120845181546001600160a01b0319166001600160a01b03918216178255948401516001918201559386168152600690925290208054859260ff199091169083600781111561078157610781615078565b0217905550505050565b610793611c2e565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000806107c3868686611c88565b915091506107d18585611fa7565b6107da57600080fd5b6107eb85853330600360f81b6122db565b5060006107fd868660016000806119ae565b50905061080b8686866126c9565b610817575050506108a9565b6108248787858886612d0d565b6001600160a01b0386811660008181526007602090815260408083208a84529091529081902080546001820154600483015460089093015493518b96610100909304831695947fabb50c1815800da62a4637d3272d1584df1ee8cbd963d90fb44eb55b63acfcb59461089d941691899160f01b90615709565b60405180910390a45050505b50505050565b6040805160a08101825260006060820181815260808301829052825260208201819052918101919091526108e1612e10565b6108eb8583612e69565b6109295760405162461bcd60e51b815260206004820152600f60248201526e15dc985c0818da1958dac819985a5b608a1b60448201526064016106cf565b60016109386020870187614f27565b600781111561094957610949615078565b14158015610975575060006109616020870187614f27565b600781111561097257610972615078565b14155b156109e55761099361098c36879003870187615737565b33306131cc565b61099c86613829565b146109e55760405162461bcd60e51b81526020600482015260196024820152780537573706963696f757320617373657420666f72207772617603c1b60448201526064016106cf565b6001600560006109fd61012089016101008a01614f27565b6007811115610a0e57610a0e615078565b6007811115610a1f57610a1f615078565b81526020019081526020016000206001016000828254610a3f9190615769565b90915550610b059050610a5a61012087016101008801614f27565b60056000610a706101208a016101008b01614f27565b6007811115610a8157610a81615078565b6007811115610a9257610a92615078565b815260208101919091526040016000908120546001600160a01b0316908590600590610ac66101208c016101008d01614f27565b6007811115610ad757610ad7615078565b6007811115610ae857610ae8615078565b815260200190815260200160002060010154896101200135613860565b610bac60056000610b1e61012089016101008a01614f27565b6007811115610b2f57610b2f615078565b6007811115610b4057610b40615078565b815260208101919091526040016000908120546001600160a01b031690600590610b726101208a016101008b01614f27565b6007811115610b8357610b83615078565b6007811115610b9457610b94615078565b81526020019081526020016000206001015487613961565b610c5460056000610bc561012089016101008a01614f27565b6007811115610bd657610bd6615078565b6007811115610be757610be7615078565b815260208101919091526040016000908120546001600160a01b031690600590610c196101208a016101008b01614f27565b6007811115610c2a57610c2a615078565b6007811115610c3b57610c3b615078565b8152602001908152602001600020600101548686610fd6565b610d0160056000610c6d61012089016101008a01614f27565b6007811115610c7e57610c7e615078565b6007811115610c8f57610c8f615078565b815260208101919091526040016000908120546001600160a01b031690600590610cc16101208a016101008b01614f27565b6007811115610cd257610cd2615078565b6007811115610ce357610ce3615078565b8152602001908152602001600020600101543330600260f81b6122db565b50604085013560056000610d1d61012089016101008a01614f27565b6007811115610d2e57610d2e615078565b6007811115610d3f57610d3f615078565b81526020808201929092526040908101600020546001600160a01b031691610d6b918901908901614f44565b6001600160a01b03167fa90a3b8dae41ae10a708d32fec7bf12da5c90879c98b9c4cca3c8fba91ddf49360056000610dab6101208c016101008d01614f27565b6007811115610dbc57610dbc615078565b6007811115610dcd57610dcd615078565b81526020810191909152604001600020600101548634610df56101608d016101408e0161577c565b604051610e059493929190615709565b60405180910390a46040805160a08101909152806060810180610e306101208a016101008b01614f27565b6007811115610e4157610e41615078565b815260200160056000610e5c6101208c016101008d01614f27565b6007811115610e6d57610e6d615078565b6007811115610e7e57610e7e615078565b81526020808201929092526040016000908120546001600160a01b0316909252918352910190600590610eb96101208a016101008b01614f27565b6007811115610eca57610eca615078565b6007811115610edb57610edb615078565b815260200190815260200160002060010154815260200186610120013581525090506106486001600055565b610f0f611c2e565b610f196000613bec565b565b6000336001600160a01b0387161480610f3357503330145b610f7f5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920666f7220774e4654206f722077726170706572000000000000000060448201526064016106cf565b610f8c86868686866122db565b610fca5760405162461bcd60e51b815260206004820152600f60248201526e1199594818da185c99d94819985a5b608a1b60448201526064016106cf565b50600195945050505050565b80151580610fe45750600034115b156108a957610ff584848484613c3e565b6110415760405162461bcd60e51b815260206004820152601860248201527f466f7262696464656e2061646420636f6c6c61746572616c000000000000000060448201526064016106cf565b6108a984848484613e1a565b3360009081526008602052604081205460ff166110a35760405162461bcd60e51b81526020600482015260146024820152734f6e6c792074727573746564206164647265737360601b60448201526064016106cf565b6110ab612e10565b6110b68383306131cc565b90506106396001600055565b6040805160a081018252600060608201818152608083018290528252602080830182905282840182905233825260089052919091205460ff1661113e5760405162461bcd60e51b81526020600482015260146024820152734f6e6c792074727573746564206164647265737360601b60448201526064016106cf565b611146612e10565b61121261115b61012087016101008801614f27565b600560006111716101208a016101008b01614f27565b600781111561118257611182615078565b600781111561119357611193615078565b815260208101919091526040016000908120546001600160a01b03169085906005906111c76101208c016101008d01614f27565b60078111156111d8576111d8615078565b60078111156111e9576111e9615078565b81526020019081526020016000206001015460016112079190615769565b896101200135613860565b60016005600061122a61012089016101008a01614f27565b600781111561123b5761123b615078565b600781111561124c5761124c615078565b8152602001908152602001600020600101600082825461126c9190615769565b9091555061128b905060056000610b1e61012089016101008a01614f27565b60005b83811015610d0157611364600560006112af6101208a016101008b01614f27565b60078111156112c0576112c0615078565b60078111156112d1576112d1615078565b815260208101919091526040016000908120546001600160a01b0316906005906113036101208b016101008c01614f27565b600781111561131457611314615078565b600781111561132557611325615078565b815260200190815260200160002060010154878785818110611349576113496157a6565b90506080020180360381019061135f9190615737565b6141a4565b6005600061137a61012089016101008a01614f27565b600781111561138b5761138b615078565b600781111561139c5761139c615078565b81526020019081526020016000206001015460056000886101000160208101906113c69190614f27565b60078111156113d7576113d7615078565b60078111156113e8576113e8615078565b81526020810191909152604001600020546001600160a01b03167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa878785818110611435576114356157a6565b61144b9260206080909202019081019150614f27565b600781111561145c5761145c615078565b88888681811061146e5761146e6157a6565b6114879260406080909202019081019150602001614f44565b898987818110611499576114996157a6565b905060800201604001358a8a888181106114b5576114b56157a6565b905060800201606001356040516114cf94939291906157bc565b60405180910390a3806114e1816157e5565b91505061128e565b606060006114f7848461163d565b5190506003815151600781111561151057611510615078565b0361159c5780516020908101519082015160405163c87b56dd60e01b81526001600160a01b039092169163c87b56dd916115509160040190815260200190565b600060405180830381865afa15801561156d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261159591908101906157fe565b9150611605565b600481515160078111156115b2576115b2615078565b036115f2578051602090810151908201516040516303a24d0760e21b81526001600160a01b0390921691630e89341c916115509160040190815260200190565b6040518060200160405280600081525091505b5092915050565b611614611c2e565b600255565b61162683838360006107b5565b505050565b63bc197c8160e01b5b95945050505050565b604080516101808101825260006101408201818152610160830182905260e083019081526101008301829052610120830182905282526060602083018190529282018190528282018390526080820183905260a082019290925260c08101919091526001600160a01b0383166000908152600760208181526040808420868552909152918290208251610180810190935280549091839160e0830191849183916101408601918491839160ff16908111156116fa576116fa615078565b600781111561170b5761170b615078565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260038401805483518184028101840190945280845293820193909160009084015b828210156117f6576000848152602090206040805160a08101909152600384029091018054829060608201908390829060ff1660078111156117a3576117a3615078565b60078111156117b4576117b4615078565b8152905461010090046001600160a01b03166020918201529082526001838101548383015260029093015460409092019190915291835292909201910161175f565b5050509082525060048201546001600160a01b0316602080830191909152600583018054604080518285028101850182528281529401939260009084015b828210156118965760008481526020908190206040805160608101825260038602909201805460f81b6001600160f81b0319168352600180820154848601526002909101546001600160a01b0316918301919091529083529092019101611834565b50505050815260200160068201805480602002602001604051908101604052809291908181526020016000905b8282101561190f5760008481526020908190206040805180820190915260028502909101805460f81b6001600160f81b03191682526001908101548284015290835290920191016118c3565b50505050815260200160078201805480602002602001604051908101604052809291908181526020016000905b8282101561198657600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff168183015282526001909201910161193c565b505050908252506008919091015460f01b6001600160f01b0319166020909101529392505050565b60008060005b6001600160a01b03881660009081526007602090815260408083208a8452909152902060030154811015611b79576001600160a01b0388811660009081526007602090815260408083208b8452909152902060030180549187169183908110611a1f57611a1f6157a6565b600091825260209091206003909102015461010090046001600160a01b0316148015611a9557506001600160a01b03881660009081526007602090815260408083208a84529091529020600301805485919083908110611a8157611a816157a6565b906000526020600020906003020160010154145b8015611b0d5750856007811115611aae57611aae615078565b6001600160a01b03891660009081526007602090815260408083208b84529091529020600301805483908110611ae657611ae66157a6565b600091825260209091206003909102015460ff166007811115611b0b57611b0b615078565b145b15611b67576001600160a01b03881660009081526007602090815260408083208a84529091529020600301805482908110611b4a57611b4a6157a6565b906000526020600020906003020160020154819250925050611b7b565b80611b71816157e5565b9150506119b4565b505b9550959350505050565b611b8d611c2e565b6001600160a01b038116611bf25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106cf565b611bfb81613bec565b50565b6001600160a01b038216600090815260066020526040812054611c2a9160ff90911690849084906107b5565b5050565b6001546001600160a01b03163314610f195760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cf565b600080611cb5600160f01b611c9d868661163d565b60c0015181166001600160f01b031990811691161490565b15611d025760405162461bcd60e51b815260206004820152601b60248201527f556e577261707020666f7262696464656e20627920617574686f72000000000060448201526064016106cf565b6003856007811115611d1657611d16615078565b03611de3576040516331a9108f60e11b8152600481018490526001600160a01b03851690636352211e90602401602060405180830381865afa158015611d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d84919061586b565b91506001600160a01b0382163314611dde5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79206f776e65722063616e20756e77726170206974000000000000000060448201526064016106cf565b611f9f565b6004856007811115611df757611df7615078565b03611f405760405163bd85b03960e01b8152600481018490526001600160a01b0385169063bd85b03990602401602060405180830381865afa158015611e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e659190615888565b604051627eeac760e11b815233600482018190526024820186905293509091506001600160a01b0385169062fdd58e90604401602060405180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed99190615888565b8114611dde5760405162461bcd60e51b815260206004820152603060248201527f45524331313520756e7772617020617661696c61626c65206f6e6c7920666f7260448201526f20616c6c20746f74616c537570706c7960801b60648201526084016106cf565b6040805160a08101909152806060810180886007811115611f6357611f63615078565b8152602001876001600160a01b03168152508152602001848152602001600081525060405163391102fb60e01b81526004016106cf91906150e6565b935093915050565b6000805b6001600160a01b03841660009081526007602090815260408083208684529091529020600601548110156122d1576001600160a01b03841660009081526007602090815260408083208684529091529020600601805482908110612011576120116157a6565b600091825260208220600291909102015460f81b6001600160f81b03191690036120c1576001600160a01b03841660009081526007602090815260408083208684529091529020600601805442919083908110612070576120706157a6565b90600052602060002090600202016001015411156120c15760405162461bcd60e51b815260206004820152600e60248201526d2a34b6b2a637b1b59032b93937b960911b60448201526064016106cf565b6001600160a01b038416600090815260076020908152604080832086845290915290206006018054829081106120f9576120f96157a6565b600091825260209091206002909102015460f81b6001600160f81b031916600160f81b036122bf5760005b6001600160a01b03851660009081526007602090815260408083208784529091529020600501548110156122bd576001600160a01b0385166000908152600760209081526040808320878452909152902060050180548290811061218a5761218a6157a6565b600091825260208220600391909102015460f81b6001600160f81b03191690036122ab576001600160a01b0385166000908152600760209081526040808320878452909152812060050180546122139188918891600291879081106121f1576121f16157a6565b600091825260208220600260039092020101546001600160a01b0316906119ae565b506001600160a01b038716600090815260076020908152604080832089845290915290206006018054919250829185908110612251576122516157a6565b90600052602060002090600202016001015411156122a95760405162461bcd60e51b81526020600482015260156024820152742a3930b739b332b92332b2a637b1b59032b93937b960591b60448201526064016106cf565b505b806122b5816157e5565b915050612124565b505b806122c9816157e5565b915050611fab565b5060019392505050565b60006001600160f81b0319821681036116345760005b6001600160a01b03871660009081526007602090815260408083208984529091529020600501548110156126bc576001600160a01b03871660009081526007602090815260408083208984529091529020600501805482908110612357576123576157a6565b600091825260208220600391909102015460f81b6001600160f81b03191690036126aa576003546004546001600160a01b0391821691161561245d576004546001600160a01b0389811660009081526007602090815260408083208c84529091529020600501805491909216916373cf00f691859081106123da576123da6157a6565b600091825260209091206003909102016002015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401608060405180830381865afa158015612432573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245691906158a1565b6060015190505b6000806000836001600160a01b031663ce244ce1600760008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060050187815481106124bb576124bb6157a6565b9060005260206000209060030201600760008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000206007018c8c6040518563ffffffff1660e01b81526004016125239493929190615925565b600060405180830381865afa158015612540573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125689190810190615a3d565b919450925090506000805b82518110156126a357306001600160a01b0316838281518110612598576125986157a6565b60200260200101516001600160a01b0316036125d2576125d28d8d8784815181106125c5576125c56157a6565b60200260200101516141a4565b6126288582815181106125e7576125e76157a6565b6020026020010151858381518110612601576126016157a6565b602002602001015185848151811061261b5761261b6157a6565b60200260200101516131cc565b91508b8d6001600160a01b0316848381518110612647576126476157a6565b60200260200101516001600160a01b03167f2e7d475f6480b44a6b26e0a71fd4bf4fbf7842b803ad204a4d23042a02bd73358560405161268991815260200190565b60405180910390a48061269b816157e5565b915050612573565b5050505050505b806126b4816157e5565b9150506122f1565b5060019695505050505050565b6001600160a01b038381166000908152600760209081526040808320868452909152812060040154909182913391161561272857506001600160a01b038086166000908152600760209081526040808320888452909152902060040154165b60005b6001600160a01b0387166000908152600760209081526040808320898452909152902060030154811015612b35576001600160a01b03871660009081526007602090815260408083208984529091528120600301805483908110612791576127916157a6565b600091825260209091206003909102015460ff1660078111156127b6576127b6615078565b14612a8b578415612889576001600160a01b0387166000908152600760209081526040808320898452909152902060030180546128829190839081106127fe576127fe6157a6565b600091825260209091206040805160a081019091526003909202018054829060608201908390829060ff16600781111561283a5761283a615078565b600781111561284b5761284b615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230846143f3565b925061294d565b6001600160a01b03871660009081526007602090815260408083208984529091529020600301805461294a9190839081106128c6576128c66157a6565b600091825260209091206040805160a081019091526003909202018054829060608201908390829060ff16600781111561290257612902615078565b600781111561291357612913615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230846131cc565b92505b6001600160a01b03871660009081526007602090815260408083208984529091529020600301805482908110612985576129856157a6565b9060005260206000209060030201600201548314612a23576001600160a01b038716600090815260076020908152604080832089845290915290206003018054829081106129d5576129d56157a6565b600091825260208220600390910201546040516001600160a01b0361010090920482169289928b16917ffca203c3f6987c2a1dae80f773c277d67920e7bce0cea9c07cd0eb8142e985ca9190a45b6001600160a01b03871660009081526007602090815260408083208984529091528120600301805483908110612a5b57612a5b6157a6565b60009182526020909120600390910201805460ff19166001836007811115612a8557612a85615078565b02179055505b6103e85a11158015612ace57506001600160a01b0387166000908152600760209081526040808320898452909152902060030154612acb90600190615b86565b81105b15612b235785876001600160a01b03167fd66d44264f9d44e254da71183ff08098f38da4675285592ee80cdbd3b6f5153e83604051612b0f91815260200190565b60405180910390a360009350505050612d06565b80612b2d816157e5565b91505061272b565b5060016001600160a01b03871660009081526007602081815260408084208a85529091529091205460ff1690811115612b7057612b70615078565b14158015612bb357506001600160a01b038616600090815260076020818152604080842089855290915282205460ff1690811115612bb057612bb0615078565b14155b15612cff5783612c60576001600160a01b038616600090815260076020818152604080842089855290915291829020825160a081019093528054612c5a9392839160608301918491839160ff90911690811115612c1257612c12615078565b6007811115612c2357612c23615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230836131cc565b50612cff565b6001600160a01b038616600090815260076020818152604080842089855290915291829020825160a081019093528054612cfd9392839160608301918491839160ff90911690811115612cb557612cb5615078565b6007811115612cc657612cc6615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230836143f3565b505b6001925050505b9392505050565b6003856007811115612d2157612d21615078565b03612d8657604051630852cd8d60e31b8152600481018390526001600160a01b038516906342966c68906024015b600060405180830381600087803b158015612d6957600080fd5b505af1158015612d7d573d6000803e3d6000fd5b50505050612e09565b6004856007811115612d9a57612d9a615078565b03612e0957604051637a94c56560e11b81526001600160a01b038481166004830152602482018490526044820183905285169063f5298aca90606401600060405180830381600087803b158015612df057600080fd5b505af1158015612e04573d6000803e3d6000fd5b505050505b5050505050565b600260005403612e625760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106cf565b6002600055565b6000612e90600160f11b611c9d612e866040870160208801614f44565b604087013561163d565b158015612ea657506001600160a01b0382163014155b6004549091506001600160a01b031615610639576004546001600160a01b0316638f8b138e612edb6040860160208701614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f439190615b99565b15612f905760405162461bcd60e51b815260206004820152601a60248201527f574c3a41737365742064697361626c656420666f72207772617000000000000060448201526064016106cf565b6004546001600160a01b03166352cdc6a6612fb16040860160208701614f44565b612fc36101608701610140880161577c565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160f01b0319166024820152604401602060405180830381865afa158015613016573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303a9190615b99565b6130985760405162461bcd60e51b815260206004820152602960248201527f574c3a536f6d652072756c6573206172652064697361626c656420666f7220746044820152681a1a5cc8185cdcd95d60ba1b60648201526084016106cf565b60005b6130a860a0850185615bb6565b9050811015611605576004546001600160a01b031663b6e306ac6130cf60a0870187615bb6565b848181106130df576130df6157a6565b90506060020160400160208101906130f79190614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561313b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315f9190615b99565b6131ba5760405162461bcd60e51b815260206004820152602660248201527f574c3a536f6d652061737365747320617265206e6f7420656e61626c656420666044820152656f722066656560d01b60648201526084016106cf565b806131c4816157e5565b91505061309b565b600080600185515160078111156131e5576131e5615078565b0361329f575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d806000811461323b576040519150601f19603f3d011682016040523d82523d6000602084013e613240565b606091505b50509050806132835760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016106cf565b613297826001600160a01b03861631615b86565b925050613821565b600285515160078111156132b5576132b5615078565b0361340b578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa158015613307573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332b9190615888565b9050306001600160a01b0385160361336457604085015185516020015161335f916001600160a01b039091169085906147c4565b613388565b6040850151855160200151613388916001600160a01b039091169086908690614827565b8451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a08231906024015b602060405180830381865afa1580156133d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fa9190615888565b6134049190615b86565b9150613821565b6003855151600781111561342157613421615078565b1480156134ad57508451602090810151908601516040516331a9108f60e11b815260048101919091526001600160a01b03868116921690636352211e90602401602060405180830381865afa15801561347e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134a2919061586b565b6001600160a01b0316145b156136b7578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156134ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135239190615888565b90508460000151602001516001600160a01b03166323b872dd858588602001516040518463ffffffff1660e01b815260040161356193929190615bfe565b600060405180830381600087803b15801561357b57600080fd5b505af115801561358f573d6000803e3d6000fd5b50505050826001600160a01b03168560000151602001516001600160a01b0316636352211e87602001516040518263ffffffff1660e01b81526004016135d791815260200190565b602060405180830381865afa1580156135f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613618919061586b565b6001600160a01b03161480156136a857508451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a0823190602401602060405180830381865afa158015613676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369a9190615888565b6136a49190615b86565b6001145b156136b257600191505b613821565b600485515160078111156136cd576136cd615078565b0361380657845160209081015190860151604051627eeac760e11b81526001600160a01b038681166004830152602482019290925291169062fdd58e90604401602060405180830381865afa15801561372a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374e9190615888565b90508460000151602001516001600160a01b031663f242432a8585886020015189604001516040518563ffffffff1660e01b81526004016137929493929190615c22565b600060405180830381600087803b1580156137ac57600080fd5b505af11580156137c0573d6000803e3d6000fd5b5050865160209081015190880151604051627eeac760e11b81526001600160a01b03888116600483015260248201929092528594509116915062fdd58e906044016133b9565b8460405163391102fb60e01b81526004016106cf91906150e6565b509392505050565b6000600361383a6020840184614f27565b600781111561384b5761384b615078565b0361385857506001919050565b506060013590565b600385600781111561387457613874615078565b036138ae576040516340c10f1960e01b81526001600160a01b038481166004830152602482018490528516906340c10f1990604401612d4f565b60048560078111156138c2576138c2615078565b0361390357604051630ab714fb60e11b81526001600160a01b038481166004830152602482018490526044820183905285169063156e29f690606401612d4f565b6040805160a0810190915280606081018088600781111561392657613926615078565b8152602001876001600160a01b031681525081526020018381526020018281525060405163391102fb60e01b81526004016106cf91906150e6565b6001600160a01b0383166000908152600760209081526040808320858452909152902081906139908282615c5a565b50506001600160a01b0383166000908152600760209081526040808320858452909152902060040180546001600160a01b03191690556139d86101608201610140830161577c565b6001600160a01b03841660009081526007602090815260408083208684529091528120600801805461ffff191660f09390931c929092179091555b613a2060a0830183615bb6565b9050811015613aaf576001600160a01b03841660009081526007602090815260408083208684529091529020600501613a5c60a0840184615bb6565b83818110613a6c57613a6c6157a6565b835460018101855560009485526020909420606090910292909201926003029091019050613a9a8282615cfd565b50508080613aa7906157e5565b915050613a13565b5060005b613ac060c0830183615d3c565b9050811015613b4f576001600160a01b03841660009081526007602090815260408083208684529091529020600601613afc60c0840184615d3c565b83818110613b0c57613b0c6157a6565b835460018101855560009485526020909420604090910292909201926002029091019050613b3a8282615d85565b50508080613b47906157e5565b915050613ab3565b5060005b613b6060e0830183615d3c565b90508110156108a9576001600160a01b038416600090815260076020818152604080842087855290915290912001613b9b60e0840184615d3c565b83818110613bab57613bab6157a6565b83546001810185556000948552602090942060409091029290920192919091019050613bd78282615dad565b50508080613be4906157e5565b915050613b53565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060036001600160a01b03861660009081526006602052604090205460ff166007811115613c6f57613c6f615078565b03613d2157604051634f558e7960e01b8152600481018590526001600160a01b03861690634f558e79906024015b602060405180830381865afa158015613cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cde9190615b99565b613d1c5760405162461bcd60e51b815260206004820152600f60248201526e774e4654206e6f742065786973747360881b60448201526064016106cf565b613dfe565b60046001600160a01b03861660009081526006602052604090205460ff166007811115613d5057613d50615078565b03613d8257604051634f558e7960e01b8152600481018590526001600160a01b03861690634f558e7990602401613c9d565b6040805160a0810182526001600160a01b03871660009081526006602052919091205481906060820190819060ff166007811115613dc257613dc2615078565b8152602001886001600160a01b03168152508152602001858152602001600081525060405163391102fb60e01b81526004016106cf91906150e6565b613e10600160f31b611c9d878761163d565b1595945050505050565b3415613ea4576040805160a08101909152613e5990859085908060608101806001815260006020918201819052918352820152346040909101526141a4565b826001600160a01b0385167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa600160008034604051613e9b94939291906157bc565b60405180910390a35b60005b81811015612e09576001838383818110613ec357613ec36157a6565b613ed99260206080909202019081019150614f27565b6007811115613eea57613eea615078565b14614192576004546001600160a01b031615614006576004546001600160a01b031663eb9ae17c848484818110613f2357613f236157a6565b613f3c9260406080909202019081019150602001614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613f80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa49190615b99565b6140065760405162461bcd60e51b815260206004820152602d60248201527f574c3a536f6d652061737365747320617265206e6f7420656e61626c6564206660448201526c1bdc8818dbdb1b185d195c985b609a1b60648201526084016106cf565b61403183838381811061401b5761401b6157a6565b90506080020180360381019061098c9190615737565b614051848484818110614046576140466157a6565b905060800201613829565b1461409a5760405162461bcd60e51b81526020600482015260196024820152780537573706963696f757320617373657420666f72207772617603c1b60448201526064016106cf565b6140b18585858585818110611349576113496157a6565b83856001600160a01b03167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa8585858181106140ef576140ef6157a6565b6141059260206080909202019081019150614f27565b600781111561411657614116615078565b868686818110614128576141286157a6565b6141419260406080909202019081019150602001614f44565b878787818110614153576141536157a6565b9050608002016040013588888881811061416f5761416f6157a6565b9050608002016060013560405161418994939291906157bc565b60405180910390a35b8061419c816157e5565b915050613ea7565b600281515160078111156141ba576141ba615078565b14806141d95750600181515160078111156141d7576141d7615078565b145b15614227576020810151156142275760405162461bcd60e51b8152602060048201526014602482015273546f6b656e4964206d757374206265207a65726f60601b60448201526064016106cf565b6003815151600781111561423d5761423d615078565b0361428a5760408101511561428a5760405162461bcd60e51b8152602060048201526013602482015272416d6f756e74206d757374206265207a65726f60681b60448201526064016106cf565b6001600160a01b038316600090815260076020908152604080832085845290915290206003015415806142d05750600381515160078111156142ce576142ce615078565b145b156142e057611626838383614848565b6000614303848484600001516000015185600001516020015186602001516119ae565b915050600081118061437b57508015801561437b575081516020908101516001600160a01b038681166000908152600784526040808220888352909452928320600301805491909216929061435a5761435a6157a6565b600091825260209091206003909102015461010090046001600160a01b0316145b156143e8576040808301516001600160a01b0386166000908152600760209081528382208783529052919091206003018054839081106143bd576143bd6157a6565b906000526020600020906003020160020160008282546143dd9190615769565b909155506108a99050565b6108a9848484614848565b6000806001855151600781111561440c5761440c615078565b03614481575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d8060008114614462576040519150601f19603f3d011682016040523d82523d6000602084013e614467565b606091505b5050905081846001600160a01b0316316132979190615b86565b6002855151600781111561449757614497615078565b0361462157306001600160a01b0385160361456c5760008560000151602001516001600160a01b03168487604001516040516024016144eb9291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516145209190615df5565b6000604051808303816000865af19150503d806000811461455d576040519150601f19603f3d011682016040523d82523d6000602084013e614562565b606091505b5050905050614615565b60008560000151602001516001600160a01b03168585886040015160405160240161459993929190615bfe565b60408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b179052516145ce9190615df5565b6000604051808303816000865af19150503d806000811461460b576040519150601f19603f3d011682016040523d82523d6000602084013e614610565b606091505b505050505b84604001519150613821565b6003855151600781111561463757614637615078565b036146ee5760008560000151602001516001600160a01b03168585886020015160405160240161466993929190615bfe565b60408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b1790525161469e9190615df5565b6000604051808303816000865af19150503d80600081146146db576040519150601f19603f3d011682016040523d82523d6000602084013e6146e0565b606091505b505090506001925050613821565b6004855151600781111561470457614704615078565b036138065760008560000151602001516001600160a01b031685858860200151896040015160405160240161473c9493929190615c22565b60408051601f198184030181529181526020820180516001600160e01b0316637921219560e11b179052516147719190615df5565b6000604051808303816000865af19150503d80600081146147ae576040519150601f19603f3d011682016040523d82523d6000602084013e6147b3565b606091505b505090508560400151925050613821565b6040516001600160a01b03831660248201526044810182905261162690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614ae6565b6108a9846323b872dd60e01b8585856040516024016147f093929190615bfe565b6002546001600160a01b0384166000908152600760209081526040808320868452909152902060030154106148bf5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206d75636820746f6b656e7320696e20636f6c6c61746572616c00000060448201526064016106cf565b60005b6001600160a01b0384166000908152600760209081526040808320868452909152902060060154811015614a3c576001600160a01b03841660009081526007602090815260408083208684529091529020600601805482908110614928576149286157a6565b600091825260209091206002909102015460f81b6001600160f81b031916600160f91b03614a2a576001600160a01b0384166000908152600760209081526040808320868452909152902060030154614982906001615769565b6001600160a01b038516600090815260076020908152604080832087845290915290206006018054839081106149ba576149ba6157a6565b9060005260206000209060020201600101541015614a2a5760405162461bcd60e51b815260206004820152602760248201527f546f6f206d75636820636f6c6c61746572616c20736c6f747320666f722074686044820152661a5cc81dd3919560ca1b60648201526084016106cf565b80614a34816157e5565b9150506148c2565b506001600160a01b038316600090815260076020818152604080842086855282528320600390810180546001818101835591865292909420855180519390920201805486959194929385939092849260ff1916918490811115614aa157614aa1615078565b021790555060209182015181546001600160a01b0390911661010002610100600160a81b03199091161790558201516001820155604090910151600290910155505050565b6000614b3b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614bb89092919063ffffffff16565b8051909150156116265780806020019051810190614b599190615b99565b6116265760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106cf565b6060610648848460008585600080866001600160a01b03168587604051614bdf9190615df5565b60006040518083038185875af1925050503d8060008114614c1c576040519150601f19603f3d011682016040523d82523d6000602084013e614c21565b606091505b5091509150614c3287838387614c3d565b979650505050505050565b60608315614cac578251600003614ca5576001600160a01b0385163b614ca55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106cf565b5081610648565b6106488383815115614cc15781518083602001fd5b8060405162461bcd60e51b81526004016106cf91906152cc565b600060208284031215614ced57600080fd5b81356001600160e01b031981168114612d0657600080fd5b6001600160a01b0381168114611bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715614d5257614d52614d1a565b60405290565b604080519081016001600160401b0381118282101715614d5257614d52614d1a565b604051601f8201601f191681016001600160401b0381118282101715614da257614da2614d1a565b604052919050565b60006001600160401b03821115614dc357614dc3614d1a565b50601f01601f191660200190565b600082601f830112614de257600080fd5b8135614df5614df082614daa565b614d7a565b818152846020838601011115614e0a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215614e3d57600080fd5b8435614e4881614d05565b93506020850135614e5881614d05565b92506040850135915060608501356001600160401b03811115614e7a57600080fd5b614e8687828801614dd1565b91505092959194509250565b8015158114611bfb57600080fd5b60008060408385031215614eb357600080fd5b8235614ebe81614d05565b91506020830135614ece81614e92565b809150509250929050565b60088110611bfb57600080fd5b600080600060608486031215614efb57600080fd5b8335614f0681614ed9565b92506020840135614f1681614d05565b929592945050506040919091013590565b600060208284031215614f3957600080fd5b8135612d0681614ed9565b600060208284031215614f5657600080fd5b8135612d0681614d05565b60008060008060808587031215614f7757600080fd5b8435614f8281614ed9565b93506020850135614f9281614d05565b9250604085013591506060850135614fa981614e92565b939692955090935050565b60008083601f840112614fc657600080fd5b5081356001600160401b03811115614fdd57600080fd5b6020830191508360208260071b8501011115614ff857600080fd5b9250929050565b6000806000806060858703121561501557600080fd5b84356001600160401b038082111561502c57600080fd5b90860190610160828903121561504157600080fd5b9094506020860135908082111561505757600080fd5b5061506487828801614fb4565b9094509250506040850135614fa981614d05565b634e487b7160e01b600052602160045260246000fd5b600881106150ac57634e487b7160e01b600052602160045260246000fd5b9052565b80516150bd83825161508e565b6020908101516001600160a01b0316838201528101516040808401919091520151606090910152565b6080810161063982846150b0565b60208101610639828461508e565b6001600160f81b031981168114611bfb57600080fd5b600080600080600060a0868803121561513057600080fd5b853561513b81614d05565b945060208601359350604086013561515281614d05565b9250606086013561516281614d05565b9150608086013561517281615102565b809150509295509295909350565b6000806000806060858703121561519657600080fd5b84356151a181614d05565b93506020850135925060408501356001600160401b038111156151c357600080fd5b6151cf87828801614fb4565b95989497509550505050565b600081830360808112156151ee57600080fd5b6151f6614d30565b9150604081121561520657600080fd5b5061520f614d58565b823561521a81614ed9565b8152602083013561522a81614d05565b8060208301525080825250604082013560208201526060820135604082015292915050565b60008060a0838503121561526257600080fd5b61526c84846151db565b91506080830135614ece81614d05565b6000806040838503121561528f57600080fd5b823561529a81614d05565b946020939093013593505050565b60005b838110156152c35781810151838201526020016152ab565b50506000910152565b60208152600082518060208401526152eb8160408501602087016152a8565b601f01601f19169190910160400192915050565b60006020828403121561531157600080fd5b5035919050565b60006001600160401b0382111561533157615331614d1a565b5060051b60200190565b600082601f83011261534c57600080fd5b8135602061535c614df083615318565b82815260059290921b8401810191818101908684111561537b57600080fd5b8286015b84811015615396578035835291830191830161537f565b509695505050505050565b600080600080600060a086880312156153b957600080fd5b85356153c481614d05565b945060208601356153d481614d05565b935060408601356001600160401b03808211156153f057600080fd5b6153fc89838a0161533b565b9450606088013591508082111561541257600080fd5b61541e89838a0161533b565b9350608088013591508082111561543457600080fd5b5061544188828901614dd1565b9150509295509295909350565b600081518084526020808501945080840160005b83811015615488576154758783516150b0565b6080969096019590820190600101615462565b509495945050505050565b600081518084526020808501945080840160005b8381101561548857815180516001600160f81b031916885283810151848901526040908101516001600160a01b031690880152606090960195908201906001016154a7565b600081518084526020808501945080840160005b8381101561548857815180516001600160f81b03191688528301518388015260409096019590820190600101615500565b600081518084526020808501945080840160005b8381101561548857815180516001600160a01b0316885283015161ffff168388015260409096019590820190600101615545565b6020815261558b6020820183516150b0565b600060208301516101408060a08501526155a961016085018361544e565b915060408501516155c560c08601826001600160a01b03169052565b506060850151601f19808685030160e08701526155e28483615493565b935060808701519150808685030161010087015261560084836154ec565b935060a0870151915080868503016101208701525061561f8382615531565b92505060c085015161563c828601826001600160f01b0319169052565b5090949350505050565b600080600080600060a0868803121561565e57600080fd5b853561566981614d05565b945060208601359350604086013561568081614ed9565b9250606086013561569081614d05565b949793965091946080013592915050565b600080600080600060a086880312156156b957600080fd5b85356156c481614d05565b945060208601356156d481614d05565b9350604086013592506060860135915060808601356001600160401b038111156156fd57600080fd5b61544188828901614dd1565b9384526001600160a01b0392909216602084015260408301526001600160f01b031916606082015260800190565b60006080828403121561574957600080fd5b612d0683836151db565b634e487b7160e01b600052601160045260246000fd5b8082018082111561063957610639615753565b60006020828403121561578e57600080fd5b81356001600160f01b031981168114612d0657600080fd5b634e487b7160e01b600052603260045260246000fd5b60ff9490941684526001600160a01b039290921660208401526040830152606082015260800190565b6000600182016157f7576157f7615753565b5060010190565b60006020828403121561581057600080fd5b81516001600160401b0381111561582657600080fd5b8201601f8101841361583757600080fd5b8051615845614df082614daa565b81815285602083850101111561585a57600080fd5b6116348260208301602086016152a8565b60006020828403121561587d57600080fd5b8151612d0681614d05565b60006020828403121561589a57600080fd5b5051919050565b6000608082840312156158b357600080fd5b604051608081018181106001600160401b03821117156158d5576158d5614d1a565b60405282516158e381614e92565b815260208301516158f381614e92565b6020820152604083015161590681614e92565b6040820152606083015161591981614d05565b60608201529392505050565b600060c0820160ff60f81b875460f81b1683526001808801546020818187015260018060a01b0391508160028b0154166040818189015260c060608901528591508a5480875260e0890192508b60005283600020965060005b818110156159a7578754868116855260a01c61ffff16858501529686019692820192860161597e565b5050506001600160a01b038916608088015294506159c59350505050565b6001600160a01b03831660a0830152611634565b600082601f8301126159ea57600080fd5b815160206159fa614df083615318565b82815260059290921b84018101918181019086841115615a1957600080fd5b8286015b84811015615396578051615a3081614d05565b8352918301918301615a1d565b60008060006060808587031215615a5357600080fd5b84516001600160401b0380821115615a6a57600080fd5b818701915087601f830112615a7e57600080fd5b81516020615a8e614df083615318565b82815260079290921b8401810191818101908b841115615aad57600080fd5b948201945b83861015615b3357858c036080811215615acc5760008081fd5b615ad4614d30565b604080831215615ae45760008081fd5b615aec614d58565b92508851615af981614ed9565b835288860151615b0881614d05565b8387015291815287820151818601528888015191810191909152825260809095019490820190615ab2565b918a0151919850909450505080831115615b4c57600080fd5b615b58888489016159d9565b94506040870151925080831115615b6e57600080fd5b5050615b7c868287016159d9565b9150509250925092565b8181038181111561063957610639615753565b600060208284031215615bab57600080fd5b8151612d0681614e92565b6000808335601e19843603018112615bcd57600080fd5b8301803591506001600160401b03821115615be757600080fd5b6020019150606081023603821315614ff857600080fd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b8135615c6581614ed9565b60088110615c8357634e487b7160e01b600052602160045260246000fd5b815460ff821691508160ff1982161783556020840135615ca281614d05565b6001600160a81b03199190911690911760089190911b610100600160a81b031617815560408201356001820155606090910135600290910155565b80546001600160a01b0319166001600160a01b0392909216919091179055565b8135615d0881615102565b815460ff191660f882901c17825550602082013560018201556040820135615d2f81614d05565b6116268160028401615cdd565b6000808335601e19843603018112615d5357600080fd5b8301803591506001600160401b03821115615d6d57600080fd5b6020019150600681901b3603821315614ff857600080fd5b8135615d9081615102565b815460ff191660f882901c17825550602082013560018201555050565b8135615db881614d05565b615dc28183615cdd565b50602082013561ffff81168114615dd857600080fd5b815461ffff60a01b191660a09190911b61ffff60a01b1617905550565b60008251615e078184602087016152a8565b919091019291505056fea264697066735822122082b07310c189bc0bf9fb1021491d58510e40f252c15525846ad059d86448479b64736f6c634300081300330000000000000000000000002d60618bbc79e6d653083793b3e11b0e8aa03966000000000000000000000000f315b9006c20913d6d8498bdf657e778d4ddf2c4
Deployed Bytecode
0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063a50410401161008a578063f1551a9c11610064578063f1551a9c14610567578063f23a6e611461059c578063f2fde38b146105c8578063faf7d720146105e857600080fd5b8063a5041040146104fa578063bc197c811461051a578063c424d4f71461053a57600080fd5b8063980550ca116100c6578063980550ca146104845780639a251c291461049a5780639a7b0509146104ad578063a0c889f6146104da57600080fd5b80638da5cb5b1461042557806391ddb1461461044357806397da0ceb1461045657600080fd5b806339e899ee1161015957806351b5deec1161013357806351b5deec1461038357806366967cbb146103b3578063715018a6146103f05780637f6d4c931461040557600080fd5b806339e899ee1461032357806342fb01a8146103435780634d36d0851461036357600080fd5b80631fe438a2116101955780631fe438a214610262578063320a18dc14610284578063331758e6146102a45780633360aa3c146102c457600080fd5b806301ffc9a7146101bc57806310118ebb146101f1578063150b7a0214610229575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004614cdb565b610608565b60405190151581526020015b60405180910390f35b3480156101fd57600080fd5b50600454610211906001600160a01b031681565b6040516001600160a01b0390911681526020016101e8565b34801561023557600080fd5b50610249610244366004614e27565b61063f565b6040516001600160e01b031990911681526020016101e8565b34801561026e57600080fd5b5061028261027d366004614ea0565b610650565b005b34801561029057600080fd5b5061028261029f366004614ee6565b610683565b3480156102b057600080fd5b50600354610211906001600160a01b031681565b3480156102d057600080fd5b506103046102df366004614f27565b600560205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b0390931683526020830191909152016101e8565b34801561032f57600080fd5b5061028261033e366004614f44565b61078b565b34801561034f57600080fd5b5061028261035e366004614f61565b6107b5565b610376610371366004614fff565b6108af565b6040516101e891906150e6565b34801561038f57600080fd5b506101dc61039e366004614f44565b60086020526000908152604090205460ff1681565b3480156103bf57600080fd5b506103e36103ce366004614f44565b60066020526000908152604090205460ff1681565b6040516101e891906150f4565b3480156103fc57600080fd5b50610282610f07565b34801561041157600080fd5b506101dc610420366004615118565b610f1b565b34801561043157600080fd5b506001546001600160a01b0316610211565b610282610451366004615180565b610fd6565b34801561046257600080fd5b5061047661047136600461524f565b61104d565b6040519081526020016101e8565b34801561049057600080fd5b5061047660025481565b6103766104a8366004614fff565b6110c2565b3480156104b957600080fd5b506104cd6104c836600461527c565b6114e9565b6040516101e891906152cc565b3480156104e657600080fd5b506102826104f53660046152ff565b61160c565b34801561050657600080fd5b50610282610515366004614ee6565b611619565b34801561052657600080fd5b506102496105353660046153a1565b61162b565b34801561054657600080fd5b5061055a61055536600461527c565b61163d565b6040516101e89190615579565b34801561057357600080fd5b50610587610582366004615646565b6119ae565b604080519283526020830191909152016101e8565b3480156105a857600080fd5b506102496105b73660046156a1565b63f23a6e6160e01b95945050505050565b3480156105d457600080fd5b506102826105e3366004614f44565b611b85565b3480156105f457600080fd5b5061028261060336600461527c565b611bfe565b60006001600160e01b03198216630271189760e51b148061063957506301ffc9a760e01b6001600160e01b03198316145b92915050565b630a85bd0160e11b5b949350505050565b610658611c2e565b6001600160a01b03919091166000908152600860205260409020805460ff1916911515919091179055565b61068b611c2e565b6001600160a01b0382166106d85760405162461bcd60e51b815260206004820152600f60248201526e4e6f207a65726f206164647265737360881b60448201526064015b60405180910390fd5b6040518060400160405280836001600160a01b03168152602001828152506005600085600781111561070c5761070c615078565b600781111561071d5761071d615078565b815260208082019290925260409081016000908120845181546001600160a01b0319166001600160a01b03918216178255948401516001918201559386168152600690925290208054859260ff199091169083600781111561078157610781615078565b0217905550505050565b610793611c2e565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6000806107c3868686611c88565b915091506107d18585611fa7565b6107da57600080fd5b6107eb85853330600360f81b6122db565b5060006107fd868660016000806119ae565b50905061080b8686866126c9565b610817575050506108a9565b6108248787858886612d0d565b6001600160a01b0386811660008181526007602090815260408083208a84529091529081902080546001820154600483015460089093015493518b96610100909304831695947fabb50c1815800da62a4637d3272d1584df1ee8cbd963d90fb44eb55b63acfcb59461089d941691899160f01b90615709565b60405180910390a45050505b50505050565b6040805160a08101825260006060820181815260808301829052825260208201819052918101919091526108e1612e10565b6108eb8583612e69565b6109295760405162461bcd60e51b815260206004820152600f60248201526e15dc985c0818da1958dac819985a5b608a1b60448201526064016106cf565b60016109386020870187614f27565b600781111561094957610949615078565b14158015610975575060006109616020870187614f27565b600781111561097257610972615078565b14155b156109e55761099361098c36879003870187615737565b33306131cc565b61099c86613829565b146109e55760405162461bcd60e51b81526020600482015260196024820152780537573706963696f757320617373657420666f72207772617603c1b60448201526064016106cf565b6001600560006109fd61012089016101008a01614f27565b6007811115610a0e57610a0e615078565b6007811115610a1f57610a1f615078565b81526020019081526020016000206001016000828254610a3f9190615769565b90915550610b059050610a5a61012087016101008801614f27565b60056000610a706101208a016101008b01614f27565b6007811115610a8157610a81615078565b6007811115610a9257610a92615078565b815260208101919091526040016000908120546001600160a01b0316908590600590610ac66101208c016101008d01614f27565b6007811115610ad757610ad7615078565b6007811115610ae857610ae8615078565b815260200190815260200160002060010154896101200135613860565b610bac60056000610b1e61012089016101008a01614f27565b6007811115610b2f57610b2f615078565b6007811115610b4057610b40615078565b815260208101919091526040016000908120546001600160a01b031690600590610b726101208a016101008b01614f27565b6007811115610b8357610b83615078565b6007811115610b9457610b94615078565b81526020019081526020016000206001015487613961565b610c5460056000610bc561012089016101008a01614f27565b6007811115610bd657610bd6615078565b6007811115610be757610be7615078565b815260208101919091526040016000908120546001600160a01b031690600590610c196101208a016101008b01614f27565b6007811115610c2a57610c2a615078565b6007811115610c3b57610c3b615078565b8152602001908152602001600020600101548686610fd6565b610d0160056000610c6d61012089016101008a01614f27565b6007811115610c7e57610c7e615078565b6007811115610c8f57610c8f615078565b815260208101919091526040016000908120546001600160a01b031690600590610cc16101208a016101008b01614f27565b6007811115610cd257610cd2615078565b6007811115610ce357610ce3615078565b8152602001908152602001600020600101543330600260f81b6122db565b50604085013560056000610d1d61012089016101008a01614f27565b6007811115610d2e57610d2e615078565b6007811115610d3f57610d3f615078565b81526020808201929092526040908101600020546001600160a01b031691610d6b918901908901614f44565b6001600160a01b03167fa90a3b8dae41ae10a708d32fec7bf12da5c90879c98b9c4cca3c8fba91ddf49360056000610dab6101208c016101008d01614f27565b6007811115610dbc57610dbc615078565b6007811115610dcd57610dcd615078565b81526020810191909152604001600020600101548634610df56101608d016101408e0161577c565b604051610e059493929190615709565b60405180910390a46040805160a08101909152806060810180610e306101208a016101008b01614f27565b6007811115610e4157610e41615078565b815260200160056000610e5c6101208c016101008d01614f27565b6007811115610e6d57610e6d615078565b6007811115610e7e57610e7e615078565b81526020808201929092526040016000908120546001600160a01b0316909252918352910190600590610eb96101208a016101008b01614f27565b6007811115610eca57610eca615078565b6007811115610edb57610edb615078565b815260200190815260200160002060010154815260200186610120013581525090506106486001600055565b610f0f611c2e565b610f196000613bec565b565b6000336001600160a01b0387161480610f3357503330145b610f7f5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c7920666f7220774e4654206f722077726170706572000000000000000060448201526064016106cf565b610f8c86868686866122db565b610fca5760405162461bcd60e51b815260206004820152600f60248201526e1199594818da185c99d94819985a5b608a1b60448201526064016106cf565b50600195945050505050565b80151580610fe45750600034115b156108a957610ff584848484613c3e565b6110415760405162461bcd60e51b815260206004820152601860248201527f466f7262696464656e2061646420636f6c6c61746572616c000000000000000060448201526064016106cf565b6108a984848484613e1a565b3360009081526008602052604081205460ff166110a35760405162461bcd60e51b81526020600482015260146024820152734f6e6c792074727573746564206164647265737360601b60448201526064016106cf565b6110ab612e10565b6110b68383306131cc565b90506106396001600055565b6040805160a081018252600060608201818152608083018290528252602080830182905282840182905233825260089052919091205460ff1661113e5760405162461bcd60e51b81526020600482015260146024820152734f6e6c792074727573746564206164647265737360601b60448201526064016106cf565b611146612e10565b61121261115b61012087016101008801614f27565b600560006111716101208a016101008b01614f27565b600781111561118257611182615078565b600781111561119357611193615078565b815260208101919091526040016000908120546001600160a01b03169085906005906111c76101208c016101008d01614f27565b60078111156111d8576111d8615078565b60078111156111e9576111e9615078565b81526020019081526020016000206001015460016112079190615769565b896101200135613860565b60016005600061122a61012089016101008a01614f27565b600781111561123b5761123b615078565b600781111561124c5761124c615078565b8152602001908152602001600020600101600082825461126c9190615769565b9091555061128b905060056000610b1e61012089016101008a01614f27565b60005b83811015610d0157611364600560006112af6101208a016101008b01614f27565b60078111156112c0576112c0615078565b60078111156112d1576112d1615078565b815260208101919091526040016000908120546001600160a01b0316906005906113036101208b016101008c01614f27565b600781111561131457611314615078565b600781111561132557611325615078565b815260200190815260200160002060010154878785818110611349576113496157a6565b90506080020180360381019061135f9190615737565b6141a4565b6005600061137a61012089016101008a01614f27565b600781111561138b5761138b615078565b600781111561139c5761139c615078565b81526020019081526020016000206001015460056000886101000160208101906113c69190614f27565b60078111156113d7576113d7615078565b60078111156113e8576113e8615078565b81526020810191909152604001600020546001600160a01b03167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa878785818110611435576114356157a6565b61144b9260206080909202019081019150614f27565b600781111561145c5761145c615078565b88888681811061146e5761146e6157a6565b6114879260406080909202019081019150602001614f44565b898987818110611499576114996157a6565b905060800201604001358a8a888181106114b5576114b56157a6565b905060800201606001356040516114cf94939291906157bc565b60405180910390a3806114e1816157e5565b91505061128e565b606060006114f7848461163d565b5190506003815151600781111561151057611510615078565b0361159c5780516020908101519082015160405163c87b56dd60e01b81526001600160a01b039092169163c87b56dd916115509160040190815260200190565b600060405180830381865afa15801561156d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261159591908101906157fe565b9150611605565b600481515160078111156115b2576115b2615078565b036115f2578051602090810151908201516040516303a24d0760e21b81526001600160a01b0390921691630e89341c916115509160040190815260200190565b6040518060200160405280600081525091505b5092915050565b611614611c2e565b600255565b61162683838360006107b5565b505050565b63bc197c8160e01b5b95945050505050565b604080516101808101825260006101408201818152610160830182905260e083019081526101008301829052610120830182905282526060602083018190529282018190528282018390526080820183905260a082019290925260c08101919091526001600160a01b0383166000908152600760208181526040808420868552909152918290208251610180810190935280549091839160e0830191849183916101408601918491839160ff16908111156116fa576116fa615078565b600781111561170b5761170b615078565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260038401805483518184028101840190945280845293820193909160009084015b828210156117f6576000848152602090206040805160a08101909152600384029091018054829060608201908390829060ff1660078111156117a3576117a3615078565b60078111156117b4576117b4615078565b8152905461010090046001600160a01b03166020918201529082526001838101548383015260029093015460409092019190915291835292909201910161175f565b5050509082525060048201546001600160a01b0316602080830191909152600583018054604080518285028101850182528281529401939260009084015b828210156118965760008481526020908190206040805160608101825260038602909201805460f81b6001600160f81b0319168352600180820154848601526002909101546001600160a01b0316918301919091529083529092019101611834565b50505050815260200160068201805480602002602001604051908101604052809291908181526020016000905b8282101561190f5760008481526020908190206040805180820190915260028502909101805460f81b6001600160f81b03191682526001908101548284015290835290920191016118c3565b50505050815260200160078201805480602002602001604051908101604052809291908181526020016000905b8282101561198657600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900461ffff168183015282526001909201910161193c565b505050908252506008919091015460f01b6001600160f01b0319166020909101529392505050565b60008060005b6001600160a01b03881660009081526007602090815260408083208a8452909152902060030154811015611b79576001600160a01b0388811660009081526007602090815260408083208b8452909152902060030180549187169183908110611a1f57611a1f6157a6565b600091825260209091206003909102015461010090046001600160a01b0316148015611a9557506001600160a01b03881660009081526007602090815260408083208a84529091529020600301805485919083908110611a8157611a816157a6565b906000526020600020906003020160010154145b8015611b0d5750856007811115611aae57611aae615078565b6001600160a01b03891660009081526007602090815260408083208b84529091529020600301805483908110611ae657611ae66157a6565b600091825260209091206003909102015460ff166007811115611b0b57611b0b615078565b145b15611b67576001600160a01b03881660009081526007602090815260408083208a84529091529020600301805482908110611b4a57611b4a6157a6565b906000526020600020906003020160020154819250925050611b7b565b80611b71816157e5565b9150506119b4565b505b9550959350505050565b611b8d611c2e565b6001600160a01b038116611bf25760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106cf565b611bfb81613bec565b50565b6001600160a01b038216600090815260066020526040812054611c2a9160ff90911690849084906107b5565b5050565b6001546001600160a01b03163314610f195760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106cf565b600080611cb5600160f01b611c9d868661163d565b60c0015181166001600160f01b031990811691161490565b15611d025760405162461bcd60e51b815260206004820152601b60248201527f556e577261707020666f7262696464656e20627920617574686f72000000000060448201526064016106cf565b6003856007811115611d1657611d16615078565b03611de3576040516331a9108f60e11b8152600481018490526001600160a01b03851690636352211e90602401602060405180830381865afa158015611d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d84919061586b565b91506001600160a01b0382163314611dde5760405162461bcd60e51b815260206004820152601860248201527f4f6e6c79206f776e65722063616e20756e77726170206974000000000000000060448201526064016106cf565b611f9f565b6004856007811115611df757611df7615078565b03611f405760405163bd85b03960e01b8152600481018490526001600160a01b0385169063bd85b03990602401602060405180830381865afa158015611e41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e659190615888565b604051627eeac760e11b815233600482018190526024820186905293509091506001600160a01b0385169062fdd58e90604401602060405180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed99190615888565b8114611dde5760405162461bcd60e51b815260206004820152603060248201527f45524331313520756e7772617020617661696c61626c65206f6e6c7920666f7260448201526f20616c6c20746f74616c537570706c7960801b60648201526084016106cf565b6040805160a08101909152806060810180886007811115611f6357611f63615078565b8152602001876001600160a01b03168152508152602001848152602001600081525060405163391102fb60e01b81526004016106cf91906150e6565b935093915050565b6000805b6001600160a01b03841660009081526007602090815260408083208684529091529020600601548110156122d1576001600160a01b03841660009081526007602090815260408083208684529091529020600601805482908110612011576120116157a6565b600091825260208220600291909102015460f81b6001600160f81b03191690036120c1576001600160a01b03841660009081526007602090815260408083208684529091529020600601805442919083908110612070576120706157a6565b90600052602060002090600202016001015411156120c15760405162461bcd60e51b815260206004820152600e60248201526d2a34b6b2a637b1b59032b93937b960911b60448201526064016106cf565b6001600160a01b038416600090815260076020908152604080832086845290915290206006018054829081106120f9576120f96157a6565b600091825260209091206002909102015460f81b6001600160f81b031916600160f81b036122bf5760005b6001600160a01b03851660009081526007602090815260408083208784529091529020600501548110156122bd576001600160a01b0385166000908152600760209081526040808320878452909152902060050180548290811061218a5761218a6157a6565b600091825260208220600391909102015460f81b6001600160f81b03191690036122ab576001600160a01b0385166000908152600760209081526040808320878452909152812060050180546122139188918891600291879081106121f1576121f16157a6565b600091825260208220600260039092020101546001600160a01b0316906119ae565b506001600160a01b038716600090815260076020908152604080832089845290915290206006018054919250829185908110612251576122516157a6565b90600052602060002090600202016001015411156122a95760405162461bcd60e51b81526020600482015260156024820152742a3930b739b332b92332b2a637b1b59032b93937b960591b60448201526064016106cf565b505b806122b5816157e5565b915050612124565b505b806122c9816157e5565b915050611fab565b5060019392505050565b60006001600160f81b0319821681036116345760005b6001600160a01b03871660009081526007602090815260408083208984529091529020600501548110156126bc576001600160a01b03871660009081526007602090815260408083208984529091529020600501805482908110612357576123576157a6565b600091825260208220600391909102015460f81b6001600160f81b03191690036126aa576003546004546001600160a01b0391821691161561245d576004546001600160a01b0389811660009081526007602090815260408083208c84529091529020600501805491909216916373cf00f691859081106123da576123da6157a6565b600091825260209091206003909102016002015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602401608060405180830381865afa158015612432573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061245691906158a1565b6060015190505b6000806000836001600160a01b031663ce244ce1600760008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d815260200190815260200160002060050187815481106124bb576124bb6157a6565b9060005260206000209060030201600760008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000206007018c8c6040518563ffffffff1660e01b81526004016125239493929190615925565b600060405180830381865afa158015612540573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125689190810190615a3d565b919450925090506000805b82518110156126a357306001600160a01b0316838281518110612598576125986157a6565b60200260200101516001600160a01b0316036125d2576125d28d8d8784815181106125c5576125c56157a6565b60200260200101516141a4565b6126288582815181106125e7576125e76157a6565b6020026020010151858381518110612601576126016157a6565b602002602001015185848151811061261b5761261b6157a6565b60200260200101516131cc565b91508b8d6001600160a01b0316848381518110612647576126476157a6565b60200260200101516001600160a01b03167f2e7d475f6480b44a6b26e0a71fd4bf4fbf7842b803ad204a4d23042a02bd73358560405161268991815260200190565b60405180910390a48061269b816157e5565b915050612573565b5050505050505b806126b4816157e5565b9150506122f1565b5060019695505050505050565b6001600160a01b038381166000908152600760209081526040808320868452909152812060040154909182913391161561272857506001600160a01b038086166000908152600760209081526040808320888452909152902060040154165b60005b6001600160a01b0387166000908152600760209081526040808320898452909152902060030154811015612b35576001600160a01b03871660009081526007602090815260408083208984529091528120600301805483908110612791576127916157a6565b600091825260209091206003909102015460ff1660078111156127b6576127b6615078565b14612a8b578415612889576001600160a01b0387166000908152600760209081526040808320898452909152902060030180546128829190839081106127fe576127fe6157a6565b600091825260209091206040805160a081019091526003909202018054829060608201908390829060ff16600781111561283a5761283a615078565b600781111561284b5761284b615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230846143f3565b925061294d565b6001600160a01b03871660009081526007602090815260408083208984529091529020600301805461294a9190839081106128c6576128c66157a6565b600091825260209091206040805160a081019091526003909202018054829060608201908390829060ff16600781111561290257612902615078565b600781111561291357612913615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230846131cc565b92505b6001600160a01b03871660009081526007602090815260408083208984529091529020600301805482908110612985576129856157a6565b9060005260206000209060030201600201548314612a23576001600160a01b038716600090815260076020908152604080832089845290915290206003018054829081106129d5576129d56157a6565b600091825260208220600390910201546040516001600160a01b0361010090920482169289928b16917ffca203c3f6987c2a1dae80f773c277d67920e7bce0cea9c07cd0eb8142e985ca9190a45b6001600160a01b03871660009081526007602090815260408083208984529091528120600301805483908110612a5b57612a5b6157a6565b60009182526020909120600390910201805460ff19166001836007811115612a8557612a85615078565b02179055505b6103e85a11158015612ace57506001600160a01b0387166000908152600760209081526040808320898452909152902060030154612acb90600190615b86565b81105b15612b235785876001600160a01b03167fd66d44264f9d44e254da71183ff08098f38da4675285592ee80cdbd3b6f5153e83604051612b0f91815260200190565b60405180910390a360009350505050612d06565b80612b2d816157e5565b91505061272b565b5060016001600160a01b03871660009081526007602081815260408084208a85529091529091205460ff1690811115612b7057612b70615078565b14158015612bb357506001600160a01b038616600090815260076020818152604080842089855290915282205460ff1690811115612bb057612bb0615078565b14155b15612cff5783612c60576001600160a01b038616600090815260076020818152604080842089855290915291829020825160a081019093528054612c5a9392839160608301918491839160ff90911690811115612c1257612c12615078565b6007811115612c2357612c23615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230836131cc565b50612cff565b6001600160a01b038616600090815260076020818152604080842089855290915291829020825160a081019093528054612cfd9392839160608301918491839160ff90911690811115612cb557612cb5615078565b6007811115612cc657612cc6615078565b8152905461010090046001600160a01b031660209182015290825260018301549082015260029091015460409091015230836143f3565b505b6001925050505b9392505050565b6003856007811115612d2157612d21615078565b03612d8657604051630852cd8d60e31b8152600481018390526001600160a01b038516906342966c68906024015b600060405180830381600087803b158015612d6957600080fd5b505af1158015612d7d573d6000803e3d6000fd5b50505050612e09565b6004856007811115612d9a57612d9a615078565b03612e0957604051637a94c56560e11b81526001600160a01b038481166004830152602482018490526044820183905285169063f5298aca90606401600060405180830381600087803b158015612df057600080fd5b505af1158015612e04573d6000803e3d6000fd5b505050505b5050505050565b600260005403612e625760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106cf565b6002600055565b6000612e90600160f11b611c9d612e866040870160208801614f44565b604087013561163d565b158015612ea657506001600160a01b0382163014155b6004549091506001600160a01b031615610639576004546001600160a01b0316638f8b138e612edb6040860160208701614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f439190615b99565b15612f905760405162461bcd60e51b815260206004820152601a60248201527f574c3a41737365742064697361626c656420666f72207772617000000000000060448201526064016106cf565b6004546001600160a01b03166352cdc6a6612fb16040860160208701614f44565b612fc36101608701610140880161577c565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160f01b0319166024820152604401602060405180830381865afa158015613016573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061303a9190615b99565b6130985760405162461bcd60e51b815260206004820152602960248201527f574c3a536f6d652072756c6573206172652064697361626c656420666f7220746044820152681a1a5cc8185cdcd95d60ba1b60648201526084016106cf565b60005b6130a860a0850185615bb6565b9050811015611605576004546001600160a01b031663b6e306ac6130cf60a0870187615bb6565b848181106130df576130df6157a6565b90506060020160400160208101906130f79190614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561313b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315f9190615b99565b6131ba5760405162461bcd60e51b815260206004820152602660248201527f574c3a536f6d652061737365747320617265206e6f7420656e61626c656420666044820152656f722066656560d01b60648201526084016106cf565b806131c4816157e5565b91505061309b565b600080600185515160078111156131e5576131e5615078565b0361329f575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d806000811461323b576040519150601f19603f3d011682016040523d82523d6000602084013e613240565b606091505b50509050806132835760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016106cf565b613297826001600160a01b03861631615b86565b925050613821565b600285515160078111156132b5576132b5615078565b0361340b578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa158015613307573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332b9190615888565b9050306001600160a01b0385160361336457604085015185516020015161335f916001600160a01b039091169085906147c4565b613388565b6040850151855160200151613388916001600160a01b039091169086908690614827565b8451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a08231906024015b602060405180830381865afa1580156133d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fa9190615888565b6134049190615b86565b9150613821565b6003855151600781111561342157613421615078565b1480156134ad57508451602090810151908601516040516331a9108f60e11b815260048101919091526001600160a01b03868116921690636352211e90602401602060405180830381865afa15801561347e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134a2919061586b565b6001600160a01b0316145b156136b7578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156134ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135239190615888565b90508460000151602001516001600160a01b03166323b872dd858588602001516040518463ffffffff1660e01b815260040161356193929190615bfe565b600060405180830381600087803b15801561357b57600080fd5b505af115801561358f573d6000803e3d6000fd5b50505050826001600160a01b03168560000151602001516001600160a01b0316636352211e87602001516040518263ffffffff1660e01b81526004016135d791815260200190565b602060405180830381865afa1580156135f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613618919061586b565b6001600160a01b03161480156136a857508451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a0823190602401602060405180830381865afa158015613676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369a9190615888565b6136a49190615b86565b6001145b156136b257600191505b613821565b600485515160078111156136cd576136cd615078565b0361380657845160209081015190860151604051627eeac760e11b81526001600160a01b038681166004830152602482019290925291169062fdd58e90604401602060405180830381865afa15801561372a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374e9190615888565b90508460000151602001516001600160a01b031663f242432a8585886020015189604001516040518563ffffffff1660e01b81526004016137929493929190615c22565b600060405180830381600087803b1580156137ac57600080fd5b505af11580156137c0573d6000803e3d6000fd5b5050865160209081015190880151604051627eeac760e11b81526001600160a01b03888116600483015260248201929092528594509116915062fdd58e906044016133b9565b8460405163391102fb60e01b81526004016106cf91906150e6565b509392505050565b6000600361383a6020840184614f27565b600781111561384b5761384b615078565b0361385857506001919050565b506060013590565b600385600781111561387457613874615078565b036138ae576040516340c10f1960e01b81526001600160a01b038481166004830152602482018490528516906340c10f1990604401612d4f565b60048560078111156138c2576138c2615078565b0361390357604051630ab714fb60e11b81526001600160a01b038481166004830152602482018490526044820183905285169063156e29f690606401612d4f565b6040805160a0810190915280606081018088600781111561392657613926615078565b8152602001876001600160a01b031681525081526020018381526020018281525060405163391102fb60e01b81526004016106cf91906150e6565b6001600160a01b0383166000908152600760209081526040808320858452909152902081906139908282615c5a565b50506001600160a01b0383166000908152600760209081526040808320858452909152902060040180546001600160a01b03191690556139d86101608201610140830161577c565b6001600160a01b03841660009081526007602090815260408083208684529091528120600801805461ffff191660f09390931c929092179091555b613a2060a0830183615bb6565b9050811015613aaf576001600160a01b03841660009081526007602090815260408083208684529091529020600501613a5c60a0840184615bb6565b83818110613a6c57613a6c6157a6565b835460018101855560009485526020909420606090910292909201926003029091019050613a9a8282615cfd565b50508080613aa7906157e5565b915050613a13565b5060005b613ac060c0830183615d3c565b9050811015613b4f576001600160a01b03841660009081526007602090815260408083208684529091529020600601613afc60c0840184615d3c565b83818110613b0c57613b0c6157a6565b835460018101855560009485526020909420604090910292909201926002029091019050613b3a8282615d85565b50508080613b47906157e5565b915050613ab3565b5060005b613b6060e0830183615d3c565b90508110156108a9576001600160a01b038416600090815260076020818152604080842087855290915290912001613b9b60e0840184615d3c565b83818110613bab57613bab6157a6565b83546001810185556000948552602090942060409091029290920192919091019050613bd78282615dad565b50508080613be4906157e5565b915050613b53565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060036001600160a01b03861660009081526006602052604090205460ff166007811115613c6f57613c6f615078565b03613d2157604051634f558e7960e01b8152600481018590526001600160a01b03861690634f558e79906024015b602060405180830381865afa158015613cba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cde9190615b99565b613d1c5760405162461bcd60e51b815260206004820152600f60248201526e774e4654206e6f742065786973747360881b60448201526064016106cf565b613dfe565b60046001600160a01b03861660009081526006602052604090205460ff166007811115613d5057613d50615078565b03613d8257604051634f558e7960e01b8152600481018590526001600160a01b03861690634f558e7990602401613c9d565b6040805160a0810182526001600160a01b03871660009081526006602052919091205481906060820190819060ff166007811115613dc257613dc2615078565b8152602001886001600160a01b03168152508152602001858152602001600081525060405163391102fb60e01b81526004016106cf91906150e6565b613e10600160f31b611c9d878761163d565b1595945050505050565b3415613ea4576040805160a08101909152613e5990859085908060608101806001815260006020918201819052918352820152346040909101526141a4565b826001600160a01b0385167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa600160008034604051613e9b94939291906157bc565b60405180910390a35b60005b81811015612e09576001838383818110613ec357613ec36157a6565b613ed99260206080909202019081019150614f27565b6007811115613eea57613eea615078565b14614192576004546001600160a01b031615614006576004546001600160a01b031663eb9ae17c848484818110613f2357613f236157a6565b613f3c9260406080909202019081019150602001614f44565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613f80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fa49190615b99565b6140065760405162461bcd60e51b815260206004820152602d60248201527f574c3a536f6d652061737365747320617265206e6f7420656e61626c6564206660448201526c1bdc8818dbdb1b185d195c985b609a1b60648201526084016106cf565b61403183838381811061401b5761401b6157a6565b90506080020180360381019061098c9190615737565b614051848484818110614046576140466157a6565b905060800201613829565b1461409a5760405162461bcd60e51b81526020600482015260196024820152780537573706963696f757320617373657420666f72207772617603c1b60448201526064016106cf565b6140b18585858585818110611349576113496157a6565b83856001600160a01b03167ff3d1350815c4f9db2be36c35f840bfb002835a83ff1c3d8f3a217b1e6227d5aa8585858181106140ef576140ef6157a6565b6141059260206080909202019081019150614f27565b600781111561411657614116615078565b868686818110614128576141286157a6565b6141419260406080909202019081019150602001614f44565b878787818110614153576141536157a6565b9050608002016040013588888881811061416f5761416f6157a6565b9050608002016060013560405161418994939291906157bc565b60405180910390a35b8061419c816157e5565b915050613ea7565b600281515160078111156141ba576141ba615078565b14806141d95750600181515160078111156141d7576141d7615078565b145b15614227576020810151156142275760405162461bcd60e51b8152602060048201526014602482015273546f6b656e4964206d757374206265207a65726f60601b60448201526064016106cf565b6003815151600781111561423d5761423d615078565b0361428a5760408101511561428a5760405162461bcd60e51b8152602060048201526013602482015272416d6f756e74206d757374206265207a65726f60681b60448201526064016106cf565b6001600160a01b038316600090815260076020908152604080832085845290915290206003015415806142d05750600381515160078111156142ce576142ce615078565b145b156142e057611626838383614848565b6000614303848484600001516000015185600001516020015186602001516119ae565b915050600081118061437b57508015801561437b575081516020908101516001600160a01b038681166000908152600784526040808220888352909452928320600301805491909216929061435a5761435a6157a6565b600091825260209091206003909102015461010090046001600160a01b0316145b156143e8576040808301516001600160a01b0386166000908152600760209081528382208783529052919091206003018054839081106143bd576143bd6157a6565b906000526020600020906003020160020160008282546143dd9190615769565b909155506108a99050565b6108a9848484614848565b6000806001855151600781111561440c5761440c615078565b03614481575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d8060008114614462576040519150601f19603f3d011682016040523d82523d6000602084013e614467565b606091505b5050905081846001600160a01b0316316132979190615b86565b6002855151600781111561449757614497615078565b0361462157306001600160a01b0385160361456c5760008560000151602001516001600160a01b03168487604001516040516024016144eb9291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b179052516145209190615df5565b6000604051808303816000865af19150503d806000811461455d576040519150601f19603f3d011682016040523d82523d6000602084013e614562565b606091505b5050905050614615565b60008560000151602001516001600160a01b03168585886040015160405160240161459993929190615bfe565b60408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b179052516145ce9190615df5565b6000604051808303816000865af19150503d806000811461460b576040519150601f19603f3d011682016040523d82523d6000602084013e614610565b606091505b505050505b84604001519150613821565b6003855151600781111561463757614637615078565b036146ee5760008560000151602001516001600160a01b03168585886020015160405160240161466993929190615bfe565b60408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b1790525161469e9190615df5565b6000604051808303816000865af19150503d80600081146146db576040519150601f19603f3d011682016040523d82523d6000602084013e6146e0565b606091505b505090506001925050613821565b6004855151600781111561470457614704615078565b036138065760008560000151602001516001600160a01b031685858860200151896040015160405160240161473c9493929190615c22565b60408051601f198184030181529181526020820180516001600160e01b0316637921219560e11b179052516147719190615df5565b6000604051808303816000865af19150503d80600081146147ae576040519150601f19603f3d011682016040523d82523d6000602084013e6147b3565b606091505b505090508560400151925050613821565b6040516001600160a01b03831660248201526044810182905261162690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614ae6565b6108a9846323b872dd60e01b8585856040516024016147f093929190615bfe565b6002546001600160a01b0384166000908152600760209081526040808320868452909152902060030154106148bf5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206d75636820746f6b656e7320696e20636f6c6c61746572616c00000060448201526064016106cf565b60005b6001600160a01b0384166000908152600760209081526040808320868452909152902060060154811015614a3c576001600160a01b03841660009081526007602090815260408083208684529091529020600601805482908110614928576149286157a6565b600091825260209091206002909102015460f81b6001600160f81b031916600160f91b03614a2a576001600160a01b0384166000908152600760209081526040808320868452909152902060030154614982906001615769565b6001600160a01b038516600090815260076020908152604080832087845290915290206006018054839081106149ba576149ba6157a6565b9060005260206000209060020201600101541015614a2a5760405162461bcd60e51b815260206004820152602760248201527f546f6f206d75636820636f6c6c61746572616c20736c6f747320666f722074686044820152661a5cc81dd3919560ca1b60648201526084016106cf565b80614a34816157e5565b9150506148c2565b506001600160a01b038316600090815260076020818152604080842086855282528320600390810180546001818101835591865292909420855180519390920201805486959194929385939092849260ff1916918490811115614aa157614aa1615078565b021790555060209182015181546001600160a01b0390911661010002610100600160a81b03199091161790558201516001820155604090910151600290910155505050565b6000614b3b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614bb89092919063ffffffff16565b8051909150156116265780806020019051810190614b599190615b99565b6116265760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106cf565b6060610648848460008585600080866001600160a01b03168587604051614bdf9190615df5565b60006040518083038185875af1925050503d8060008114614c1c576040519150601f19603f3d011682016040523d82523d6000602084013e614c21565b606091505b5091509150614c3287838387614c3d565b979650505050505050565b60608315614cac578251600003614ca5576001600160a01b0385163b614ca55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106cf565b5081610648565b6106488383815115614cc15781518083602001fd5b8060405162461bcd60e51b81526004016106cf91906152cc565b600060208284031215614ced57600080fd5b81356001600160e01b031981168114612d0657600080fd5b6001600160a01b0381168114611bfb57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715614d5257614d52614d1a565b60405290565b604080519081016001600160401b0381118282101715614d5257614d52614d1a565b604051601f8201601f191681016001600160401b0381118282101715614da257614da2614d1a565b604052919050565b60006001600160401b03821115614dc357614dc3614d1a565b50601f01601f191660200190565b600082601f830112614de257600080fd5b8135614df5614df082614daa565b614d7a565b818152846020838601011115614e0a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215614e3d57600080fd5b8435614e4881614d05565b93506020850135614e5881614d05565b92506040850135915060608501356001600160401b03811115614e7a57600080fd5b614e8687828801614dd1565b91505092959194509250565b8015158114611bfb57600080fd5b60008060408385031215614eb357600080fd5b8235614ebe81614d05565b91506020830135614ece81614e92565b809150509250929050565b60088110611bfb57600080fd5b600080600060608486031215614efb57600080fd5b8335614f0681614ed9565b92506020840135614f1681614d05565b929592945050506040919091013590565b600060208284031215614f3957600080fd5b8135612d0681614ed9565b600060208284031215614f5657600080fd5b8135612d0681614d05565b60008060008060808587031215614f7757600080fd5b8435614f8281614ed9565b93506020850135614f9281614d05565b9250604085013591506060850135614fa981614e92565b939692955090935050565b60008083601f840112614fc657600080fd5b5081356001600160401b03811115614fdd57600080fd5b6020830191508360208260071b8501011115614ff857600080fd5b9250929050565b6000806000806060858703121561501557600080fd5b84356001600160401b038082111561502c57600080fd5b90860190610160828903121561504157600080fd5b9094506020860135908082111561505757600080fd5b5061506487828801614fb4565b9094509250506040850135614fa981614d05565b634e487b7160e01b600052602160045260246000fd5b600881106150ac57634e487b7160e01b600052602160045260246000fd5b9052565b80516150bd83825161508e565b6020908101516001600160a01b0316838201528101516040808401919091520151606090910152565b6080810161063982846150b0565b60208101610639828461508e565b6001600160f81b031981168114611bfb57600080fd5b600080600080600060a0868803121561513057600080fd5b853561513b81614d05565b945060208601359350604086013561515281614d05565b9250606086013561516281614d05565b9150608086013561517281615102565b809150509295509295909350565b6000806000806060858703121561519657600080fd5b84356151a181614d05565b93506020850135925060408501356001600160401b038111156151c357600080fd5b6151cf87828801614fb4565b95989497509550505050565b600081830360808112156151ee57600080fd5b6151f6614d30565b9150604081121561520657600080fd5b5061520f614d58565b823561521a81614ed9565b8152602083013561522a81614d05565b8060208301525080825250604082013560208201526060820135604082015292915050565b60008060a0838503121561526257600080fd5b61526c84846151db565b91506080830135614ece81614d05565b6000806040838503121561528f57600080fd5b823561529a81614d05565b946020939093013593505050565b60005b838110156152c35781810151838201526020016152ab565b50506000910152565b60208152600082518060208401526152eb8160408501602087016152a8565b601f01601f19169190910160400192915050565b60006020828403121561531157600080fd5b5035919050565b60006001600160401b0382111561533157615331614d1a565b5060051b60200190565b600082601f83011261534c57600080fd5b8135602061535c614df083615318565b82815260059290921b8401810191818101908684111561537b57600080fd5b8286015b84811015615396578035835291830191830161537f565b509695505050505050565b600080600080600060a086880312156153b957600080fd5b85356153c481614d05565b945060208601356153d481614d05565b935060408601356001600160401b03808211156153f057600080fd5b6153fc89838a0161533b565b9450606088013591508082111561541257600080fd5b61541e89838a0161533b565b9350608088013591508082111561543457600080fd5b5061544188828901614dd1565b9150509295509295909350565b600081518084526020808501945080840160005b83811015615488576154758783516150b0565b6080969096019590820190600101615462565b509495945050505050565b600081518084526020808501945080840160005b8381101561548857815180516001600160f81b031916885283810151848901526040908101516001600160a01b031690880152606090960195908201906001016154a7565b600081518084526020808501945080840160005b8381101561548857815180516001600160f81b03191688528301518388015260409096019590820190600101615500565b600081518084526020808501945080840160005b8381101561548857815180516001600160a01b0316885283015161ffff168388015260409096019590820190600101615545565b6020815261558b6020820183516150b0565b600060208301516101408060a08501526155a961016085018361544e565b915060408501516155c560c08601826001600160a01b03169052565b506060850151601f19808685030160e08701526155e28483615493565b935060808701519150808685030161010087015261560084836154ec565b935060a0870151915080868503016101208701525061561f8382615531565b92505060c085015161563c828601826001600160f01b0319169052565b5090949350505050565b600080600080600060a0868803121561565e57600080fd5b853561566981614d05565b945060208601359350604086013561568081614ed9565b9250606086013561569081614d05565b949793965091946080013592915050565b600080600080600060a086880312156156b957600080fd5b85356156c481614d05565b945060208601356156d481614d05565b9350604086013592506060860135915060808601356001600160401b038111156156fd57600080fd5b61544188828901614dd1565b9384526001600160a01b0392909216602084015260408301526001600160f01b031916606082015260800190565b60006080828403121561574957600080fd5b612d0683836151db565b634e487b7160e01b600052601160045260246000fd5b8082018082111561063957610639615753565b60006020828403121561578e57600080fd5b81356001600160f01b031981168114612d0657600080fd5b634e487b7160e01b600052603260045260246000fd5b60ff9490941684526001600160a01b039290921660208401526040830152606082015260800190565b6000600182016157f7576157f7615753565b5060010190565b60006020828403121561581057600080fd5b81516001600160401b0381111561582657600080fd5b8201601f8101841361583757600080fd5b8051615845614df082614daa565b81815285602083850101111561585a57600080fd5b6116348260208301602086016152a8565b60006020828403121561587d57600080fd5b8151612d0681614d05565b60006020828403121561589a57600080fd5b5051919050565b6000608082840312156158b357600080fd5b604051608081018181106001600160401b03821117156158d5576158d5614d1a565b60405282516158e381614e92565b815260208301516158f381614e92565b6020820152604083015161590681614e92565b6040820152606083015161591981614d05565b60608201529392505050565b600060c0820160ff60f81b875460f81b1683526001808801546020818187015260018060a01b0391508160028b0154166040818189015260c060608901528591508a5480875260e0890192508b60005283600020965060005b818110156159a7578754868116855260a01c61ffff16858501529686019692820192860161597e565b5050506001600160a01b038916608088015294506159c59350505050565b6001600160a01b03831660a0830152611634565b600082601f8301126159ea57600080fd5b815160206159fa614df083615318565b82815260059290921b84018101918181019086841115615a1957600080fd5b8286015b84811015615396578051615a3081614d05565b8352918301918301615a1d565b60008060006060808587031215615a5357600080fd5b84516001600160401b0380821115615a6a57600080fd5b818701915087601f830112615a7e57600080fd5b81516020615a8e614df083615318565b82815260079290921b8401810191818101908b841115615aad57600080fd5b948201945b83861015615b3357858c036080811215615acc5760008081fd5b615ad4614d30565b604080831215615ae45760008081fd5b615aec614d58565b92508851615af981614ed9565b835288860151615b0881614d05565b8387015291815287820151818601528888015191810191909152825260809095019490820190615ab2565b918a0151919850909450505080831115615b4c57600080fd5b615b58888489016159d9565b94506040870151925080831115615b6e57600080fd5b5050615b7c868287016159d9565b9150509250925092565b8181038181111561063957610639615753565b600060208284031215615bab57600080fd5b8151612d0681614e92565b6000808335601e19843603018112615bcd57600080fd5b8301803591506001600160401b03821115615be757600080fd5b6020019150606081023603821315614ff857600080fd5b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b8135615c6581614ed9565b60088110615c8357634e487b7160e01b600052602160045260246000fd5b815460ff821691508160ff1982161783556020840135615ca281614d05565b6001600160a81b03199190911690911760089190911b610100600160a81b031617815560408201356001820155606090910135600290910155565b80546001600160a01b0319166001600160a01b0392909216919091179055565b8135615d0881615102565b815460ff191660f882901c17825550602082013560018201556040820135615d2f81614d05565b6116268160028401615cdd565b6000808335601e19843603018112615d5357600080fd5b8301803591506001600160401b03821115615d6d57600080fd5b6020019150600681901b3603821315614ff857600080fd5b8135615d9081615102565b815460ff191660f882901c17825550602082013560018201555050565b8135615db881614d05565b615dc28183615cdd565b50602082013561ffff81168114615dd857600080fd5b815461ffff60a01b191660a09190911b61ffff60a01b1617905550565b60008251615e078184602087016152a8565b919091019291505056fea264697066735822122082b07310c189bc0bf9fb1021491d58510e40f252c15525846ad059d86448479b64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002d60618bbc79e6d653083793b3e11b0e8aa03966000000000000000000000000f315b9006c20913d6d8498bdf657e778d4ddf2c4
-----Decoded View---------------
Arg [0] : _erc20 (address): 0x2D60618BBC79e6d653083793B3E11b0E8Aa03966
Arg [1] : _trusted (address): 0xf315B9006C20913D6D8498BDf657E778d4Ddf2c4
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002d60618bbc79e6d653083793b3e11b0e8aa03966
Arg [1] : 000000000000000000000000f315b9006c20913d6d8498bdf657e778d4ddf2c4
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.