Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multi Chain
Multichain Addresses
0 address found via
Latest 4 from a total of 4 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Set Display Para... | 4241344 | 83 days 16 hrs ago | IN | 0 ETH | 0.0004944 | ||||
Set Subscription... | 4235296 | 84 days 17 hrs ago | IN | 0 ETH | 0.00002184 | ||||
Set White List | 4235293 | 84 days 17 hrs ago | IN | 0 ETH | 0.00004394 | ||||
0x60e06040 | 4235096 | 84 days 18 hrs ago | IN | Create: EnvelopNFTKioskService | 0 ETH | 0.00460305 |
Loading...
Loading
Contract Name:
EnvelopNFTKioskService
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) NFT(wNFT) Kiosk. pragma solidity 0.8.19; import "ServiceProviderOwnable.sol"; import "NFTKiosk.sol"; import "IModelWhiteList.sol"; contract EnvelopNFTKioskService is NFTKiosk, ServiceProviderOwnable { address public modelWhiteListAddress; constructor (address _subscrRegistry) ServiceProviderOwnable(_subscrRegistry) { } function setDisplayParams( string calldata _name, address _beneficiary, // who will receive assets from sale uint256 _enableAfter, uint256 _disableAfter, address _priceModel ) public override(NFTKiosk) { require( IModelWhiteList(modelWhiteListAddress).isModelEnabled(_priceModel), "Unexpected price model address" ); if (displays[hlpHashString(_name)].owner == address(0)) { // Fix subscriptionfor NEW display only _checkAndFixSubscription(msg.sender); } super.setDisplayParams( _name, _beneficiary, _enableAfter, _disableAfter, _priceModel ); } //////////////////////////////////////// // Admin functions /// //////////////////////////////////////// function setWhiteList(address _modelWhiteList) external onlyOwner { modelWhiteListAddress = _modelWhiteList; } ///////////////////////////////////////////////////////////////////// function checkUser(address _user) external view returns (bool ok, bool needFix) { return _checkUserSubscription(_user); } }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) Subscription Registry Contract V2 /// The subscription platform operates with the following role model /// (it is assumed that the actor with the role is implemented as a contract). /// `Service Provider` is a contract whose services are sold by subscription. /// `Agent` - a contract that sells a subscription on behalf ofservice provider. /// May receive sales commission /// `Platform` - SubscriptionRegistry contract that performs processingsubscriptions, /// fares, tickets pragma solidity 0.8.19; import "Ownable.sol"; import "ServiceProvider.sol"; /// @title ServiceProviderOwnable contract /// @author Envelop project Team /// @notice Contract implements Ownable pattern for service providers. /// @dev Inherit this code in service provider contract that /// want use subscription. contract ServiceProviderOwnable is ServiceProvider, Ownable { constructor(address _subscrRegistry) ServiceProvider(_subscrRegistry) { } /////////////////////////////////////// // Admin functions /// //////////////////////////////////////// function newTariff(Tariff memory _newTariff) external onlyOwner returns(uint256 tariffIndex) { tariffIndex = _registerServiceTariff(_newTariff); } function registerServiceTariff(Tariff memory _newTariff) external onlyOwner returns(uint256) { return _registerServiceTariff(_newTariff); } function editServiceTariff( uint256 _tariffIndex, uint256 _timelockPeriod, uint256 _ticketValidPeriod, uint256 _counter, bool _isAvailable, address _beneficiary ) external onlyOwner { _editServiceTariff( _tariffIndex, _timelockPeriod, _ticketValidPeriod, _counter, _isAvailable, _beneficiary ); } function addPayOption( uint256 _tariffIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external onlyOwner returns(uint256 index) { index = _addTariffPayOption( _tariffIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } function editPayOption( uint256 _tariffIndex, uint256 _payWithIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external onlyOwner { _editTariffPayOption( _tariffIndex, _payWithIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } function authorizeAgentForService( address _agent, uint256[] memory _serviceTariffIndexes ) external onlyOwner returns (uint256[] memory actualTariffs) { actualTariffs = _authorizeAgentForService( _agent, _serviceTariffIndexes ); } function setSubscriptionRegistry(address _subscrRegistry) external onlyOwner { subscriptionRegistry = ISubscriptionRegistry(_subscrRegistry); } function setSubscriptionOnOff(bool _isEnable) external onlyOwner { isEnabled = _isEnable; } }
// 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 // ENVELOP(NIFTSY) Subscription Registry Contract V2 /// The subscription platform operates with the following role model /// (it is assumed that the actor with the role is implemented as a contract). /// `Service Provider` is a contract whose services are sold by subscription. /// `Agent` - a contract that sells a subscription on behalf ofservice provider. /// May receive sales commission /// `Platform` - SubscriptionRegistry contract that performs processingsubscriptions, /// fares, tickets pragma solidity 0.8.19; import "ISubscriptionRegistry.sol"; /// @title ServiceProvider abstract contract /// @author Envelop project Team /// @notice Abstract contract implements subscribing features. /// For use with SubscriptionRegestry /// @dev Use this code in service provider contract that /// want use subscription. One contract = one servie /// Please see example folder abstract contract ServiceProvider { address public serviceProvider; ISubscriptionRegistry public subscriptionRegistry; bool public isEnabled = true; constructor(address _subscrRegistry) { require(_subscrRegistry != address(0), 'Non zero only'); serviceProvider = address(this); subscriptionRegistry = ISubscriptionRegistry(_subscrRegistry); } function _registerServiceTariff(Tariff memory _newTariff) internal virtual returns(uint256) { return subscriptionRegistry.registerServiceTariff(_newTariff); } function _editServiceTariff( uint256 _tariffIndex, uint256 _timelockPeriod, uint256 _ticketValidPeriod, uint256 _counter, bool _isAvailable, address _beneficiary ) internal virtual { subscriptionRegistry.editServiceTariff( _tariffIndex, _timelockPeriod, _ticketValidPeriod, _counter, _isAvailable, _beneficiary ); } function _addTariffPayOption( uint256 _tariffIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) internal virtual returns(uint256) { return subscriptionRegistry.addTariffPayOption( _tariffIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } function _editTariffPayOption( uint256 _tariffIndex, uint256 _payWithIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) internal virtual { subscriptionRegistry.editTariffPayOption( _tariffIndex, _payWithIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } function _authorizeAgentForService( address _agent, uint256[] memory _serviceTariffIndexes ) internal virtual returns (uint256[] memory) { // TODO Check agent return subscriptionRegistry.authorizeAgentForService( _agent, _serviceTariffIndexes ); } //////////////////////////// // Main USAGE // //////////////////////////// function _checkAndFixSubscription(address _user) internal returns (bool ok) { if (isEnabled) { ok = subscriptionRegistry.checkAndFixUserSubscription( _user ); } else { ok = true; } } function _checkUserSubscription(address _user) internal view returns (bool ok, bool needFix) { if (isEnabled) { (ok, needFix) = subscriptionRegistry.checkUserSubscription( _user, address(this) ); } else { ok = true; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {SubscriptionType, PayOption, Tariff, Ticket} from "SubscriptionRegistry.sol"; interface ISubscriptionRegistry { /** * @notice Add new tariff for caller * @dev Call this method from ServiceProvider * for setup new tariff * using `Tariff` data type(please see above) * * @param _newTariff full encded Tariff object * @return last added tariff index in Tariff[] array * for current Service Provider (msg.sender) */ function registerServiceTariff(Tariff calldata _newTariff) external returns(uint256); /** * @notice Authorize agent for caller service provider * @dev Call this method from ServiceProvider * * @param _agent - address of contract that implement Agent role * @param _serviceTariffIndexes - array of index in `availableTariffs` array * that available for given `_agent` * @return full array of actual tarifs for this agent */ function authorizeAgentForService( address _agent, uint256[] calldata _serviceTariffIndexes ) external returns (uint256[] memory); /** * @notice By Ticket for subscription * @dev Call this method from Agent * * @param _service - Service Provider address * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @param _buyFor - address for whome this ticket would be bought * @param _payer - address of payer for this ticket * @return ticket structure that would be use for validate service process */ function buySubscription( address _service, uint256 _tariffIndex, uint256 _payWithIndex, address _buyFor, address _payer ) external payable returns(Ticket memory ticket); /** * @notice Edit tariff for caller * @dev Call this method from ServiceProvider * for setup new tariff * using `Tariff` data type(please see above) * * @param _tariffIndex - index in `availableTariffs` array * @param _timelockPeriod - see SubscriptionType notice above * @param _ticketValidPeriod - see SubscriptionType notice above * @param _counter - see SubscriptionType notice above * @param _isAvailable - see SubscriptionType notice above * @param _beneficiary - see SubscriptionType notice above */ function editServiceTariff( uint256 _tariffIndex, uint256 _timelockPeriod, uint256 _ticketValidPeriod, uint256 _counter, bool _isAvailable, address _beneficiary ) external; /** * @notice Add tariff PayOption for exact service * @dev Call this method from ServiceProvider * for add tariff PayOption * * @param _tariffIndex - index in `availableTariffs` array * @param _paymentToken - see PayOption notice above * @param _paymentAmount - see PayOption notice above * @param _agentFeePercent - see PayOption notice above * @return last added PaymentOption index in array * for _tariffIndex Tariff of caller Service Provider (msg.sender) */ function addTariffPayOption( uint256 _tariffIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external returns(uint256); /** * @notice Edit tariff PayOption for exact service * @dev Call this method from ServiceProvider * for edit tariff PayOption * * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @param _paymentToken - see PayOption notice above * @param _paymentAmount - see PayOption notice above * @param _agentFeePercent - see PayOption notice above * for _tariffIndex Tariff of caller Service Provider (msg.sender) */ function editTariffPayOption( uint256 _tariffIndex, uint256 _payWithIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external; /** * @notice Check that `_user` have still valid ticket for this service. * @dev Call this method from any context * * @param _user - address of user who has an ticket and who trying get service * @param _service - address of Service Provider * @return ok True in case ticket is valid * @return needFix True in case ticket has counter > 0 */ function checkUserSubscription( address _user, address _service ) external view returns (bool ok, bool needFix); /** * @notice Check that `_user` have still valid ticket for this service. * Decrement ticket counter in case it > 0 * @dev Call this method from ServiceProvider * * @param _user - address of user who has an ticket and who trying get service * @return ok True in case ticket is valid */ function checkAndFixUserSubscription(address _user) external returns (bool ok); /** * @notice Decrement ticket counter in case it > 0 * @dev Call this method from new SubscriptionRegistry in case of upgrade * * @param _user - address of user who has an ticket and who trying get service * @param _serviceFromProxy - address of service from more new SubscriptionRegistry contract */ function fixUserSubscription(address _user, address _serviceFromProxy) external; /** * @notice Returns `_user` ticket for this service. * @dev Call this method from any context * * @param _user - address of user who has an ticket and who trying get service * @param _service - address of Service Provider * @return ticket */ function getUserTicketForService( address _service, address _user ) external view returns(Ticket memory); /** * @notice Returns array of Tariff for `_service` * @dev Call this method from any context * * @param _service - address of Service Provider * @return Tariff array */ function getTariffsForService(address _service) external view returns (Tariff[] memory); /** * @notice Returns ticket price include any fees * @dev Call this method from any context * * @param _service - address of Service Provider * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @return tulpe with payment token an ticket price */ function getTicketPrice( address _service, uint256 _tariffIndex, uint256 _payWithIndex ) external view returns (address, uint256); /** * @notice Returns array of Tariff for `_service` assigned to `_agent` * @dev Call this method from any context * * @param _agent - address of Agent * @param _service - address of Service Provider * @return Tariff array */ function getAvailableAgentsTariffForService( address _agent, address _service ) external view returns(Tariff[] memory); }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) Team. Subscription Registry Contract V2 pragma solidity 0.8.19; import "Ownable.sol"; import "SafeERC20.sol"; import "ITrustedWrapper.sol"; import "LibEnvelopTypes.sol"; import "ISubscriptionRegistry.sol"; /// The subscription platform operates with the following role model /// (it is assumed that the actor with the role is implemented as a contract). /// `Service Provider` is a contract whose services are sold by subscription. /// `Agent` - a contract that sells a subscription on behalf ofservice provider. /// May receive sales commission /// `Platform` - SubscriptionRegistry contract that performs processingsubscriptions, /// fares, tickets struct SubscriptionType { uint256 timelockPeriod; // in seconds e.g. 3600*24*30*12 = 31104000 = 1 year uint256 ticketValidPeriod; // in seconds e.g. 3600*24*30 = 2592000 = 1 month uint256 counter; // For case when ticket valid for N usage, e.g. for Min N NFTs bool isAvailable; // USe for stop using tariff because we can`t remove tariff from array address beneficiary; // Who will receive payment for tickets } struct PayOption { address paymentToken; // token contract address or zero address for native token(ETC etc) uint256 paymentAmount; // ticket price exclude any fees uint16 agentFeePercent; // 100%-10000, 20%-2000, 3%-300 } struct Tariff { SubscriptionType subscription; // link to subscriptionType PayOption[] payWith; // payment option array. Use it for price in defferent tokens } // native subscribtionManager tickets format struct Ticket { uint256 validUntil; // Unixdate, tickets not valid after uint256 countsLeft; // for tarif with fixed use counter } /// @title Base contract in Envelop Subscription Platform /// @author Envelop Team /// @notice You can use this contract for make and operate any on-chain subscriptions /// @dev Contract that performs processing subscriptions, fares(tariffs), tickets /// @custom:please see example folder. contract SubscriptionRegistry is Ownable { using SafeERC20 for IERC20; uint256 constant public PERCENT_DENOMINATOR = 10000; /// @notice Envelop Multisig contract address public platformOwner; /// @notice Platform owner can receive fee from each payments uint16 public platformFeePercent = 50; // 100%-10000, 20%-2000, 3%-300 /// @notice address used for wrapp & lock incoming assets address public mainWrapper; /// @notice Used in case upgrade this contract address public previousRegistry; /// @notice Used in case upgrade this contract address public proxyRegistry; /// @notice Only white listed assets can be used on platform mapping(address => bool) public whiteListedForPayments; /// @notice from service(=smart contract address) to tarifs mapping(address => Tariff[]) public availableTariffs; /// @notice from service to agent to available tarifs(tarif index); mapping(address => mapping(address => uint256[])) public agentServiceRegistry; /// @notice mapping from user addres to service contract address to ticket mapping(address => mapping(address => Ticket)) public userTickets; event PlatfromFeeChanged(uint16 indexed newPercent); event WhitelistPaymentTokenChanged(address indexed asset, bool indexed state); event TariffChanged(address indexed service, uint256 indexed tariffIndex); event TicketIssued( address indexed service, address indexed agent, address indexed forUser, uint256 tariffIndex ); constructor(address _platformOwner) { require(_platformOwner != address(0),'Zero platform fee receiver'); platformOwner = _platformOwner; } /** * @notice Add new tariff for caller * @dev Call this method from ServiceProvider * for setup new tariff * using `Tariff` data type(please see above) * * @param _newTariff full encded Tariff object * @return last added tariff index in Tariff[] array * for current Service Provider (msg.sender) */ function registerServiceTariff(Tariff calldata _newTariff) external returns(uint256) { // TODO // Tarif structure check // PayWith array whiteList check return _addTariff(msg.sender, _newTariff); } /** * @notice Edit tariff for caller * @dev Call this method from ServiceProvider * for setup new tariff * using `Tariff` data type(please see above) * * @param _tariffIndex - index in `availableTariffs` array * @param _timelockPeriod - see SubscriptionType notice above * @param _ticketValidPeriod - see SubscriptionType notice above * @param _counter - see SubscriptionType notice above * @param _isAvailable - see SubscriptionType notice above * @param _beneficiary - see SubscriptionType notice above */ function editServiceTariff( uint256 _tariffIndex, uint256 _timelockPeriod, uint256 _ticketValidPeriod, uint256 _counter, bool _isAvailable, address _beneficiary ) external { // TODO // Tariff structure check // PayWith array whiteList check _editTariff( msg.sender, _tariffIndex, _timelockPeriod, _ticketValidPeriod, _counter, _isAvailable, _beneficiary ); } /** * @notice Add tariff PayOption for exact service * @dev Call this method from ServiceProvider * for add tariff PayOption * * @param _tariffIndex - index in `availableTariffs` array * @param _paymentToken - see PayOption notice above * @param _paymentAmount - see PayOption notice above * @param _agentFeePercent - see PayOption notice above * @return last added PaymentOption index in array * for _tariffIndex Tariff of caller Service Provider (msg.sender) */ function addTariffPayOption( uint256 _tariffIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external returns(uint256) { return _addTariffPayOption( msg.sender, _tariffIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } /** * @notice Edit tariff PayOption for exact service * @dev Call this method from ServiceProvider * for edit tariff PayOption * * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @param _paymentToken - see PayOption notice above * @param _paymentAmount - see PayOption notice above * @param _agentFeePercent - see PayOption notice above * for _tariffIndex Tariff of caller Service Provider (msg.sender) */ function editTariffPayOption( uint256 _tariffIndex, uint256 _payWithIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) external { _editTariffPayOption( msg.sender, _tariffIndex, _payWithIndex, _paymentToken, _paymentAmount, _agentFeePercent ); } /** * @notice Authorize agent for caller service provider * @dev Call this method from ServiceProvider * * @param _agent - address of contract that implement Agent role * @param _serviceTariffIndexes - array of index in `availableTariffs` array * that available for given `_agent` * @return full array of actual tarifs for this agent */ function authorizeAgentForService( address _agent, uint256[] calldata _serviceTariffIndexes ) external virtual returns (uint256[] memory) { // remove previouse tariffs delete agentServiceRegistry[msg.sender][_agent]; uint256[] storage currentServiceTariffsOfAgent = agentServiceRegistry[msg.sender][_agent]; // check that adding tariffs still available for(uint256 i; i < _serviceTariffIndexes.length; ++ i) { if (availableTariffs[msg.sender][_serviceTariffIndexes[i]].subscription.isAvailable){ currentServiceTariffsOfAgent.push(_serviceTariffIndexes[i]); } } return currentServiceTariffsOfAgent; } /** * @notice By Ticket for subscription * @dev Call this method from Agent * * @param _service - Service Provider address * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @param _buyFor - address for whome this ticket would be bought * @param _payer - address of payer for this ticket * @return ticket structure that would be use for validate service process */ function buySubscription( address _service, uint256 _tariffIndex, uint256 _payWithIndex, address _buyFor, address _payer ) external payable returns(Ticket memory ticket) { // Cant buy ticket for nobody require(_buyFor != address(0),'Cant buy ticket for nobody'); require( availableTariffs[_service][_tariffIndex].subscription.isAvailable, 'This subscription not available' ); // Not used in this implementation // require( // availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount > 0, // 'This Payment option not available' // ); // Check that agent is authorized for purchace of this service require( _isAgentAuthorized(msg.sender, _service, _tariffIndex), 'Agent not authorized for this service tariff' ); (bool isValid, bool needFix) = _isTicketValid(_buyFor, _service); require(!isValid, 'Only one valid ticket at time'); //lets safe user ticket (only one ticket available in this version) ticket = Ticket( availableTariffs[_service][_tariffIndex].subscription.ticketValidPeriod + block.timestamp, availableTariffs[_service][_tariffIndex].subscription.counter ); userTickets[_buyFor][_service] = ticket; // Lets receive payment tokens FROM sender if (availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount > 0){ _processPayment(_service, _tariffIndex, _payWithIndex, _payer); } emit TicketIssued(_service, msg.sender, _buyFor, _tariffIndex); } /** * @notice Check that `_user` have still valid ticket for this service. * Decrement ticket counter in case it > 0 * @dev Call this method from ServiceProvider * * @param _user - address of user who has an ticket and who trying get service * @return ok True in case ticket is valid */ function checkAndFixUserSubscription( address _user ) external returns (bool ok){ address _service = msg.sender; // Check user ticket (bool isValid, bool needFix) = _isTicketValid(_user, msg.sender); // Proxy to previos if (!isValid && previousRegistry != address(0)) { (isValid, needFix) = ISubscriptionRegistry(previousRegistry).checkUserSubscription( _user, _service ); // Case when valid ticket stored in previousManager if (isValid ) { if (needFix){ ISubscriptionRegistry(previousRegistry).fixUserSubscription( _user, _service ); } ok = true; return ok; } } require(isValid,'Valid ticket not found'); // Fix action (for subscription with counter) if (needFix){ _fixUserSubscription(_user, msg.sender); } ok = true; } /** * @notice Decrement ticket counter in case it > 0 * @dev Call this method from new SubscriptionRegistry in case of upgrade * * @param _user - address of user who has an ticket and who trying get service * @param _serviceFromProxy - address of service from more new SubscriptionRegistry contract */ function fixUserSubscription( address _user, address _serviceFromProxy ) public { require(proxyRegistry !=address(0) && msg.sender == proxyRegistry, 'Only for future registry' ); _fixUserSubscription(_user, _serviceFromProxy); } //////////////////////////////////////////////////////////////// /** * @notice Check that `_user` have still valid ticket for this service. * @dev Call this method from any context * * @param _user - address of user who has an ticket and who trying get service * @param _service - address of Service Provider * @return ok True in case ticket is valid * @return needFix True in case ticket has counter > 0 */ function checkUserSubscription( address _user, address _service ) external view returns (bool ok, bool needFix) { (ok, needFix) = _isTicketValid(_user, _service); if (!ok && previousRegistry != address(0)) { (ok, needFix) = ISubscriptionRegistry(previousRegistry).checkUserSubscription( _user, _service ); } } /** * @notice Returns `_user` ticket for this service. * @dev Call this method from any context * * @param _user - address of user who has an ticket and who trying get service * @param _service - address of Service Provider * @return ticket */ function getUserTicketForService( address _service, address _user ) public view returns(Ticket memory) { return userTickets[_user][_service]; } /** * @notice Returns array of Tariff for `_service` * @dev Call this method from any context * * @param _service - address of Service Provider * @return Tariff array */ function getTariffsForService(address _service) external view returns (Tariff[] memory) { return availableTariffs[_service]; } /** * @notice Returns ticket price include any fees * @dev Call this method from any context * * @param _service - address of Service Provider * @param _tariffIndex - index in `availableTariffs` array * @param _payWithIndex - index in `tariff.payWith` array * @return tulpe with payment token an ticket price */ function getTicketPrice( address _service, uint256 _tariffIndex, uint256 _payWithIndex ) public view virtual returns (address, uint256) { if (availableTariffs[_service][_tariffIndex].subscription.timelockPeriod != 0) { return( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); } else { return( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount + availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].agentFeePercent /PERCENT_DENOMINATOR + availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *_platformFeePercent(_service, _tariffIndex, _payWithIndex) /PERCENT_DENOMINATOR ); } } /** * @notice Returns array of Tariff for `_service` assigned to `_agent` * @dev Call this method from any context * * @param _agent - address of Agent * @param _service - address of Service Provider * @return tuple with two arrays: indexes and Tariffs */ function getAvailableAgentsTariffForService( address _agent, address _service ) external view virtual returns(uint256[] memory, Tariff[] memory) { //First need get count of tarifs that still available uint256 availableCount; for (uint256 i; i < agentServiceRegistry[_service][_agent].length; ++i){ if (availableTariffs[_service][ agentServiceRegistry[_service][_agent][i] ].subscription.isAvailable ) {++availableCount;} } Tariff[] memory tariffs = new Tariff[](availableCount); uint256[] memory indexes = new uint256[](availableCount); for (uint256 i; i < agentServiceRegistry[_service][_agent].length; ++i){ if (availableTariffs[_service][ agentServiceRegistry[_service][_agent][i] ].subscription.isAvailable ) { tariffs[availableCount - 1] = availableTariffs[_service][ agentServiceRegistry[_service][_agent][i] ]; indexes[availableCount - 1] = agentServiceRegistry[_service][_agent][i]; --availableCount; } } return (indexes, tariffs); } //////////////////////////////////////////////////////////////// ////////// Admins ////// //////////////////////////////////////////////////////////////// function setAssetForPaymentState(address _asset, bool _isEnable) external onlyOwner { whiteListedForPayments[_asset] = _isEnable; emit WhitelistPaymentTokenChanged(_asset, _isEnable); } function setMainWrapper(address _wrapper) external onlyOwner { mainWrapper = _wrapper; } function setPlatformOwner(address _newOwner) external { require(msg.sender == platformOwner, 'Only platform owner'); require(_newOwner != address(0),'Zero platform fee receiver'); platformOwner = _newOwner; } function setPlatformFeePercent(uint16 _newPercent) external { require(msg.sender == platformOwner, 'Only platform owner'); platformFeePercent = _newPercent; emit PlatfromFeeChanged(platformFeePercent); } function setPreviousRegistry(address _registry) external onlyOwner { previousRegistry = _registry; } function setProxyRegistry(address _registry) external onlyOwner { proxyRegistry = _registry; } ///////////////////////////////////////////////////////////////////// function _processPayment( address _service, uint256 _tariffIndex, uint256 _payWithIndex, address _payer ) internal virtual returns(bool) { // there are two payment method for this implementation. // 1. with wrap and lock in asset (no fees) // 2. simple payment (agent & platform fee enabled) if (availableTariffs[_service][_tariffIndex].subscription.timelockPeriod != 0){ require(msg.value == 0, 'Ether Not accepted in this method'); // 1. with wrap and lock in asset IERC20( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ).safeTransferFrom( _payer, address(this), availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); // Lets approve received for wrap IERC20( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ).safeApprove( mainWrapper, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); // Lets wrap with timelock and appropriate params ETypes.INData memory _inData; ETypes.AssetItem[] memory _collateralERC20 = new ETypes.AssetItem[](1); ETypes.Lock[] memory timeLock = new ETypes.Lock[](1); // Only need set timelock for this wNFT timeLock[0] = ETypes.Lock( 0x00, // timelock availableTariffs[_service][_tariffIndex].subscription.timelockPeriod + block.timestamp ); _inData = ETypes.INData( ETypes.AssetItem( ETypes.Asset(ETypes.AssetType.EMPTY, address(0)), 0,0 ), // INAsset address(0), // Unwrap destinition new ETypes.Fee[](0), // Fees //new ETypes.Lock[](0), // Locks timeLock, new ETypes.Royalty[](0), // Royalties ETypes.AssetType.ERC721, // Out type 0, // Out Balance 0x0000 // Rules ); _collateralERC20[0] = ETypes.AssetItem( ETypes.Asset( ETypes.AssetType.ERC20, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ), 0, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); ITrustedWrapper(mainWrapper).wrap( _inData, _collateralERC20, _payer ); } else { // 2. simple payment if (availableTariffs[_service][_tariffIndex] .payWith[_payWithIndex] .paymentToken != address(0) ) { // pay with erc20 require(msg.value == 0, 'Ether Not accepted in this method'); // 2.1. Body payment IERC20( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ).safeTransferFrom( _payer, availableTariffs[_service][_tariffIndex].subscription.beneficiary, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); // 2.2. Agent fee payment IERC20( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ).safeTransferFrom( _payer, msg.sender, availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].agentFeePercent /PERCENT_DENOMINATOR ); // 2.3. Platform fee uint256 _pFee = _platformFeePercent(_service, _tariffIndex, _payWithIndex); if (_pFee > 0) { IERC20( availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentToken ).safeTransferFrom( _payer, platformOwner, // availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *_pFee /PERCENT_DENOMINATOR ); } } else { // pay with native token(eth, bnb, etc) (, uint256 needPay) = getTicketPrice(_service, _tariffIndex,_payWithIndex); require(msg.value >= needPay, 'Not enough ether'); // 2.4. Body ether payment sendValue( payable(availableTariffs[_service][_tariffIndex].subscription.beneficiary), availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount ); // 2.5. Agent fee payment sendValue( payable(msg.sender), availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].agentFeePercent /PERCENT_DENOMINATOR ); // 2.3. Platform fee uint256 _pFee = _platformFeePercent(_service, _tariffIndex, _payWithIndex); if (_pFee > 0) { sendValue( payable(platformOwner), availableTariffs[_service][_tariffIndex].payWith[_payWithIndex].paymentAmount *_pFee /PERCENT_DENOMINATOR ); } // return change if ((msg.value - needPay) > 0) { address payable s = payable(_payer); s.transfer(msg.value - needPay); } } } } // In this impementation params not used. // Can be ovveriden in other cases function _platformFeePercent( address _service, uint256 _tariffIndex, uint256 _payWithIndex ) internal view virtual returns(uint256) { return platformFeePercent; } function _addTariff(address _service, Tariff calldata _newTariff) internal returns(uint256) { require (_newTariff.payWith.length > 0, 'No payment method'); for (uint256 i; i < _newTariff.payWith.length; ++i){ require( whiteListedForPayments[_newTariff.payWith[i].paymentToken], 'Not whitelisted for payments' ); } require( _newTariff.subscription.ticketValidPeriod > 0 || _newTariff.subscription.counter > 0, 'Tariff has no valid ticket option' ); availableTariffs[_service].push(_newTariff); emit TariffChanged(_service, availableTariffs[_service].length - 1); return availableTariffs[_service].length - 1; } function _editTariff( address _service, uint256 _tariffIndex, uint256 _timelockPeriod, uint256 _ticketValidPeriod, uint256 _counter, bool _isAvailable, address _beneficiary ) internal { availableTariffs[_service][_tariffIndex].subscription.timelockPeriod = _timelockPeriod; availableTariffs[_service][_tariffIndex].subscription.ticketValidPeriod = _ticketValidPeriod; availableTariffs[_service][_tariffIndex].subscription.counter = _counter; availableTariffs[_service][_tariffIndex].subscription.isAvailable = _isAvailable; availableTariffs[_service][_tariffIndex].subscription.beneficiary = _beneficiary; emit TariffChanged(_service, _tariffIndex); } function _addTariffPayOption( address _service, uint256 _tariffIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) internal returns(uint256) { require(whiteListedForPayments[_paymentToken], 'Not whitelisted for payments'); availableTariffs[_service][_tariffIndex].payWith.push( PayOption(_paymentToken, _paymentAmount, _agentFeePercent) ); emit TariffChanged(_service, _tariffIndex); return availableTariffs[_service][_tariffIndex].payWith.length - 1; } function _editTariffPayOption( address _service, uint256 _tariffIndex, uint256 _payWithIndex, address _paymentToken, uint256 _paymentAmount, uint16 _agentFeePercent ) internal { require(whiteListedForPayments[_paymentToken], 'Not whitelisted for payments'); availableTariffs[_service][_tariffIndex].payWith[_payWithIndex] = PayOption(_paymentToken, _paymentAmount, _agentFeePercent); emit TariffChanged(_service, _tariffIndex); } function _fixUserSubscription( address _user, address _service ) internal { // Fix action (for subscription with counter) if (userTickets[_user][_service].countsLeft > 0) { -- userTickets[_user][_service].countsLeft; } } function _isTicketValid(address _user, address _service) internal view returns (bool isValid, bool needFix ) { isValid = userTickets[_user][_service].validUntil > block.timestamp || userTickets[_user][_service].countsLeft > 0; needFix = userTickets[_user][_service].countsLeft > 0; } function _isAgentAuthorized( address _agent, address _service, uint256 _tariffIndex ) internal view returns(bool authorized) { for (uint256 i; i < agentServiceRegistry[_service][_agent].length; ++ i){ if (agentServiceRegistry[_service][_agent][i] == _tariffIndex){ authorized = true; return authorized; } } } 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"); } }
// 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 "IWrapper.sol"; interface ITrustedWrapper is IWrapper { function trustedOperator() external view returns(address); function wrapUnsafe( ETypes.INData calldata _inData, ETypes.AssetItem[] calldata _collateral, address _wrappFor ) external payable returns (ETypes.AssetItem memory); function transferIn( ETypes.AssetItem memory _assetItem, address _from ) external payable returns (uint256 _transferedValue); }
// 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 // 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 // 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 // ENVELOP(NIFTSY) NFT(wNFT) Kiosk. pragma solidity 0.8.19; import "TokenServiceExtended.sol"; import "ERC721Holder.sol"; import "ERC1155Holder.sol"; import "ReentrancyGuard.sol"; //import "KTypes.sol"; import "IDisplayPriceModel.sol"; //import "DefaultPriceModel.sol"; contract NFTKiosk is TokenServiceExtended, ReentrancyGuard { uint256 constant public DEFAULT_INDEX = 0; uint256 constant public PERCENT_DENOMINATOR = 10000; bytes32 immutable public DEFAULT_DISPLAY = hlpHashString('NFTKiosk'); mapping(bytes32 => KTypes.Display) public displays; // mapping from contract address & tokenId to Place(displayHash and index) mapping(address => mapping(uint256 => KTypes.Place)) public assetAtDisplay; event DisplayChanged( bytes32 indexed display, address indexed owner, address indexed beneficiary, // who will receive assets from sale uint256 enableAfter, uint256 disableAfter, address priceModel, string name ); event DisplayTransfer( bytes32 indexed display, address indexed from, address indexed newOwner ); event ItemAddedToDisplay( bytes32 indexed display, address indexed assetContract, uint256 indexed assetTokenId, uint256 placeIndex ); event ItemPriceChanged( bytes32 indexed display, address indexed assetContract, uint256 indexed assetTokenId ); event EnvelopPurchase( bytes32 indexed display, address indexed assetContract, uint256 indexed assetTokenId ); event EnvelopReferrer( address indexed referrer, address indexed customer, address indexed payWithToken, uint256 payWithAmount, uint16 percentDiscount ); function setDisplayParams( string calldata _name, address _beneficiary, // who will receive assets from sale uint256 _enableAfter, uint256 _disableAfter, address _priceModel ) public virtual { // require( // displays[DEFAULT_DISPLAY].owner != address(0), // "DEFAULT DISPLAY must be created first" // ); // TODO Check that model is whitelisted.. ??Ask Alex bytes32 _displayNameHash = hlpHashString(_name); require( (displays[_displayNameHash].owner == msg.sender // edit existing ||displays[_displayNameHash].owner == address(0)), // create new "Only for Display Owner" ); _setDisplayParams( _displayNameHash, msg.sender, _beneficiary, // who will receive assets from sale _enableAfter, _disableAfter, _priceModel ); emit DisplayChanged( _displayNameHash, msg.sender, _beneficiary, // who will receive assets from sale _enableAfter, _disableAfter, _priceModel, _name ); } function transferDisplay(address _to, bytes32 _displayNameHash) external { require(displays[_displayNameHash].owner == msg.sender, "Only for Display Owner"); displays[_displayNameHash].owner = _to; emit DisplayTransfer(_displayNameHash, msg.sender, _to); } // TODO Check that display exists function addItemToDisplay( bytes32 _displayNameHash, ETypes.AssetItem memory _assetItem, KTypes.Price[] calldata _prices ) public returns (KTypes.Place memory place) { // We need two checks. // 1. Only item with zero place (display and index) can be added // to exact display KTypes.Place memory p = assetAtDisplay[_assetItem.asset.contractAddress][_assetItem.tokenId]; require( p.display == bytes32(0) && p.index == 0, "Already at display" ); // 2. Item has been transfered to this contract // Next check is For 721 only. Because 1155 standard // has no `ownerOf` method. Hence we can't use simple (implicit) // erc1155 transfer for put item at display. // In this implementation you cant`t 'edit' display after // simple (implicit) adding item to display // if (_ownerOf(_assetItem) != address(this)) { // Do transfer to this contract require(_assetItem.amount <=_transferSafe(_assetItem, msg.sender, address(this)), "Insufficient balance after NFT transfer" ); // } // DEFAULT_DISPLAY accept items from any addresses if (msg.sender != displays[_displayNameHash].owner) { require( _displayNameHash == DEFAULT_DISPLAY, "Only Default Display allow for any" ); } place = _addItemRecordAtDisplay( _displayNameHash, msg.sender, // Item Owner _assetItem, _prices ); emit ItemAddedToDisplay( place.display, _assetItem.asset.contractAddress, _assetItem.tokenId, place.index ); } function addBatchItemsToDisplayWithSamePrice( bytes32 _displayNameHash, ETypes.AssetItem[] memory _assetItems, KTypes.Price[] calldata _prices ) external returns (KTypes.Place[] memory) { // Lets calc and create array var for result KTypes.Place[] memory pls = new KTypes.Place[](_assetItems.length); for (uint256 i = 0; i < _assetItems.length; ++i){ pls[i] = addItemToDisplay(_displayNameHash,_assetItems[i],_prices); } return pls; } function addAssetItemPriceAtIndex( ETypes.AssetItem calldata _assetItem, KTypes.Price[] calldata _prices ) external { KTypes.Place memory p = getAssetItemPlace(_assetItem); // check that sender is item owner or display owner(if item owner not set) if (displays[p.display].items[p.index].owner != msg.sender) { require( displays[p.display].owner == msg.sender, "Only display owner can edit price" ); } _addItemPriceAtIndex(p.display, p.index, _prices); emit ItemPriceChanged( p.display, _assetItem.asset.contractAddress, _assetItem.tokenId ); } function editAssetItemPriceAtIndex( ETypes.AssetItem calldata _assetItem, uint256 _priceIndex, KTypes.Price calldata _price ) external { KTypes.Place memory p = getAssetItemPlace(_assetItem); // check that sender is item owner or display owner(if item owner not set) if (displays[p.display].items[p.index].owner != msg.sender) { require(displays[p.display].owner == msg.sender, "Only for display owner"); } _editItemPriceAtIndex(p.display, p.index, _priceIndex ,_price); emit ItemPriceChanged( p.display, _assetItem.asset.contractAddress, _assetItem.tokenId ); } function removeLastPersonalPriceForAssetItem( ETypes.AssetItem calldata _assetItem ) external { KTypes.Place memory p = getAssetItemPlace(_assetItem); // check that sender is item owner or display owner(if item owner not set) if (displays[p.display].items[p.index].owner != msg.sender) { require(displays[p.display].owner == msg.sender, "Only for display owner"); } KTypes.Price[] storage priceArray = displays[p.display].items[p.index].prices; priceArray.pop(); emit ItemPriceChanged( p.display, _assetItem.asset.contractAddress, _assetItem.tokenId ); } function buyAssetItem( ETypes.AssetItem calldata _assetItem, uint256 _priceIndex, address _buyer, address _referrer, string calldata _promo ) external payable nonReentrant { // 1.Define exact asset price with discounts ETypes.AssetItem memory payWithItem; { // Against stack too deep (KTypes.Price[] memory pArray, KTypes.Discount[] memory dArray) = _getAssetItemPricesAndDiscounts( _assetItem, _buyer, _referrer, hlpHashString(_promo) ); uint256 totalDiscountPercent; for (uint256 i = 0; i < dArray.length; ++ i){ totalDiscountPercent += dArray[i].dsctPercent; if (dArray[i].dsctType ==KTypes.DiscountType.REFERRAL){ emit EnvelopReferrer( _referrer, msg.sender, pArray[_priceIndex].payWith, pArray[_priceIndex].amount, uint16(dArray[i].dsctPercent) ); } } payWithItem = ETypes.AssetItem( ETypes.Asset( pArray[_priceIndex].payWith == address(0) ?ETypes.AssetType.NATIVE :ETypes.AssetType.ERC20, pArray[_priceIndex].payWith ), 0, pArray[_priceIndex].amount * (PERCENT_DENOMINATOR - totalDiscountPercent) / PERCENT_DENOMINATOR ); } // 2. Manage display records for different cases address beneficiary; KTypes.Place memory p = getAssetItemPlace(_assetItem); // Case when NFT just transfered to kiosk contract if (p.display == bytes32(0)) { //isImplicitAdded = true; beneficiary = displays[DEFAULT_DISPLAY].beneficiary; p.display = DEFAULT_DISPLAY; p.index = DEFAULT_INDEX; } else { beneficiary = displays[p.display].items[p.index].owner; // 2.1 remove item from display if (p.index != displays[p.display].items.length - 1) { // if asset item is not last array element // then replace it with last element displays[p.display].items[p.index] = displays[p.display].items[ displays[p.display].items.length - 1 ]; // and change last element that was moved in above string assetAtDisplay[ displays[p.display].items[p.index].nft.asset.contractAddress // address of just moved nft ][ displays[p.display].items[p.index].nft.tokenId ] = KTypes.Place( p.display, p.index ); } // remove last element from array displays[p.display].items.pop(); // delete mapping element delete assetAtDisplay[_assetItem.asset.contractAddress][_assetItem.tokenId]; } require( displays[p.display].enableAfter < block.timestamp && displays[p.display].disableAfter >= block.timestamp, "Only in time" ); // 3.Receive payment // There are two different cases: native token and erc20 if (payWithItem.asset.assetType ==ETypes.AssetType.NATIVE ) //if (pArray[_priceIndex].payWith == address(0)) { // Native token payment require(payWithItem.amount <= _transferSafe(payWithItem, address(this), beneficiary), "Insufficient balance after payment transfer" ); // Return change if ((msg.value - payWithItem.amount) > 0) { address payable s = payable(msg.sender); s.transfer(msg.value - payWithItem.amount); } } else { // ERC20 token payment require(msg.value == 0, "Only ERC20 tokens"); require(payWithItem.amount <=_transferSafe(payWithItem, msg.sender, beneficiary), "Insufficient balance after payment transfer" ); } // 4. Send asset to buyer _transferSafe(_assetItem, address(this), _buyer); emit EnvelopPurchase(p.display, _assetItem.asset.contractAddress, _assetItem.tokenId); } ////////////////////////////////////////////////////////////// function getDisplayOwner(bytes32 _displayNameHash) public view returns (address) { return displays[_displayNameHash].owner; } function getDisplay(bytes32 _displayNameHash) public view returns (KTypes.Display memory) { return displays[_displayNameHash]; } function getAssetItemPlace(ETypes.AssetItem memory _assetItem) public view returns (KTypes.Place memory) { if (_assetItem.asset.assetType == ETypes.AssetType.ERC721) { // ERC721 require( _ownerOf(_assetItem) == address(this), "Asset not transfered to kiosk" ); } else { //ERC1155 or other** require( _balanceOf(_assetItem, address(this)) >= _assetItem.amount, "Asset not transfered to kiosk" ); } return assetAtDisplay[_assetItem.asset.contractAddress][_assetItem.tokenId]; } function getAssetItemPricesAndDiscounts( ETypes.AssetItem memory _assetItem, address _buyer, address _referrer, string calldata _promo ) external view returns (KTypes.Price[] memory, KTypes.Discount[] memory) { return _getAssetItemPricesAndDiscounts( _assetItem, _buyer, _referrer, hlpHashString(_promo) ); } /// @notice Returns ONLY items that was added with `addItemToDisplay`. /// @dev For obtain all items please use envelop oracle function getDisplayAssetItems(bytes32 _displayNameHash) public view virtual returns (KTypes.ItemForSale[] memory) { return displays[_displayNameHash].items; } function getAssetItem(ETypes.AssetItem memory _assetItem) public view returns (KTypes.ItemForSale memory) { KTypes.Place memory p = getAssetItemPlace(_assetItem); return displays[p.display].items[p.index]; } function hlpHashString(string memory _name) public pure returns (bytes32) { return keccak256(abi.encode(_name)); } ///////////////////////////// /// Internals // ///////////////////////////// function _setDisplayParams( bytes32 _displayNameHash, address _owner, address _beneficiary, // who will receive assets from sale uint256 _enableAfter, uint256 _disableAfter, address _priceModel ) internal { KTypes.Display storage d = displays[_displayNameHash]; d.owner = _owner; d.beneficiary = _beneficiary; d.enableAfter = _enableAfter; d.disableAfter = _disableAfter; d.priceModel = _priceModel; } function _addItemRecordAtDisplay( bytes32 _displayNameHash, address _itemOwner, ETypes.AssetItem memory _nft, KTypes.Price[] calldata _prices ) internal returns (KTypes.Place memory) { KTypes.ItemForSale storage it = displays[_displayNameHash].items.push(); it.owner = _itemOwner; it.nft = _nft; if (_prices.length > 0){ for (uint256 i = 0; i < _prices.length; ++ i) { it.prices.push(_prices[i]); } } // add to mapping assetAtDisplay assetAtDisplay[_nft.asset.contractAddress][_nft.tokenId] = KTypes.Place( _displayNameHash, displays[_displayNameHash].items.length - 1 ); return assetAtDisplay[_nft.asset.contractAddress][_nft.tokenId]; } function _addItemPriceAtIndex( bytes32 _displayNameHash, uint256 _itemIndex, KTypes.Price[] calldata _prices ) internal { KTypes.ItemForSale storage it = displays[_displayNameHash].items[_itemIndex]; for (uint256 i = 0; i < _prices.length; ++ i) { it.prices.push(_prices[i]); } } function _editItemPriceAtIndex( bytes32 _displayNameHash, uint256 _itemIndex, uint256 _priceIndex, KTypes.Price calldata _price ) internal { displays[_displayNameHash].items[_itemIndex].prices[_priceIndex] = _price; } function _getAssetItemPricesAndDiscounts( ETypes.AssetItem memory _assetItem, address _buyer, address _referrer, bytes32 _promoHash ) internal view virtual returns(KTypes.Price[] memory, KTypes.Discount[] memory) { // Define current asset Place KTypes.Place memory pl = getAssetItemPlace(_assetItem); if (pl.display == bytes32(0) && pl.index == 0){ return ( IDisplayPriceModel(displays[DEFAULT_DISPLAY].priceModel).getItemPrices(_assetItem), IDisplayPriceModel(displays[DEFAULT_DISPLAY].priceModel).getItemDiscounts( _assetItem, _buyer, _referrer, _promoHash ) ); } if (displays[pl.display].items[pl.index].prices.length > 0) { return ( displays[pl.display].items[pl.index].prices, IDisplayPriceModel(displays[pl.display].priceModel).getItemDiscounts( _assetItem, _buyer, _referrer, _promoHash ) ); } // If there is no individual prices then need ask priceModel contract of display return ( IDisplayPriceModel(displays[pl.display].priceModel).getItemPrices(_assetItem), IDisplayPriceModel(displays[pl.display].priceModel).getItemDiscounts( _assetItem, _buyer, _referrer, _promoHash ) ); } }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) protocol V1 for NFT. Wrapper - main protocol contract pragma solidity 0.8.19; import "TokenService.sol"; /// @title Envelop PrtocolV1 helper service for manage ERC(20, 721, 115) getters /// @author Envelop Team /// @notice Just as dependence for main wrapper contract abstract contract TokenServiceExtended is TokenService { function _balanceOf( ETypes.AssetItem memory _assetItem, address _holder ) internal view virtual returns (uint256 _balance){ if (_assetItem.asset.assetType == ETypes.AssetType.NATIVE) { _balance = _holder.balance; } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC20) { _balance = IERC20Extended(_assetItem.asset.contractAddress).balanceOf(_holder); } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC721) { _balance = IERC721Mintable(_assetItem.asset.contractAddress).balanceOf(_holder); } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC1155) { _balance = IERC1155Mintable(_assetItem.asset.contractAddress).balanceOf(_holder, _assetItem.tokenId); } else { revert UnSupportedAsset(_assetItem); } } function _ownerOf( ETypes.AssetItem memory _assetItem ) internal view virtual returns (address _owner){ if (_assetItem.asset.assetType == ETypes.AssetType.NATIVE) { _owner = address(0); } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC20) { _owner = address(0); } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC721) { _owner = IERC721Mintable(_assetItem.asset.contractAddress).ownerOf(_assetItem.tokenId); } else if (_assetItem.asset.assetType == ETypes.AssetType.ERC1155) { _owner = address(0); } else { revert UnSupportedAsset(_assetItem); } } }
// 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 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; }
// 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/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 // ENVELOP(NIFTSY) protocol V1 for NFT. import "LibEnvelopTypes.sol"; pragma solidity 0.8.19; library KTypes { enum DiscountType {PROMO, REFERRAL, BATCH, TIME, WHITELIST, CUSTOM1, CUSTOM2, CUSTOM3} struct Price { address payWith; uint256 amount; } struct DenominatedPrice { address payWith; uint256 amount; uint256 denominator; } struct Discount { DiscountType dsctType; uint16 dsctPercent; // 100%-10000, 20%-2000, 3%-300 } struct ItemForSale { address owner; ETypes.AssetItem nft; Price[] prices; } struct Display { address owner; address beneficiary; // who will receive assets from sale uint256 enableAfter; uint256 disableAfter; address priceModel; ItemForSale[] items; } struct Place { bytes32 display; uint256 index; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; //import "IERC721Enumerable.sol"; import "LibEnvelopTypes.sol"; import "KTypes.sol"; interface IDisplayPriceModel { event DiscountChanged( bytes32 indexed display, uint8 indexed DiscountType, bytes32 DiscountParam, uint16 DiscountPercent ); event DefaultPriceChanged( bytes32 indexed display, address indexed payWithContract, uint256 indexed priceAmount ); function getItemPrices( ETypes.AssetItem memory _assetItem ) external view returns (KTypes.Price[] memory); function getDefaultDisplayPrices( ETypes.AssetItem memory _assetItem ) external view returns (KTypes.Price[] memory); function getItemDiscounts( ETypes.AssetItem memory _assetItem, address _buyer, address _referrer, bytes32 _promoHash ) external view returns (KTypes.Discount[] memory); function getBatchPrices( ETypes.AssetItem[] memory _assetItemArray ) external view returns (KTypes.Price[] memory); function getBatchDiscounts( ETypes.AssetItem[] memory _assetItemArray, address _buyer, address _referrer, bytes32 _promoHash ) external view returns (KTypes.Discount[] memory); }
// SPDX-License-Identifier: MIT // ENVELOP(NIFTSY) NFT(wNFT) Kiosk Default Price Model; pragma solidity 0.8.19; import "IDisplayPriceModel.sol"; import "IEnvelopNFTKiosk.sol"; import "IWNFT.sol"; /// @title Default price model implementation /// @author Envelop Team /// @notice This model operate sellings of erc20 collateral inside wNFTS V1 /// @dev .. contract DefaultPriceModel is IDisplayPriceModel { struct DiscountUntil { uint256 untilDate; KTypes.Discount discount; } // mapping from displayNameHash to ERC20 collateral prices mapping (bytes32 => mapping(address => KTypes.DenominatedPrice[])) public erc20CollateralPricesForDisplays; // mapping from displayNameHash to default price for all NFT at the display mapping (bytes32 => KTypes.Price[]) public defaultNFTPriceForDisplay; // mapping from displayNameHash to time discounts mapping (bytes32 => DiscountUntil[]) public timeDiscounts; // mapping from displayNameHash to PROMO hash to PROMO discount mapping (bytes32 => mapping (bytes32 => DiscountUntil)) public promoDiscounts; // mapping from displayNameHash to referrer hash to PROMO discount mapping (bytes32 => mapping (bytes32 => DiscountUntil)) public referrerDiscounts; IEnvelopNFTKiosk public kiosk; event CollateralPriceChanged( bytes32 indexed display, address indexed erc20Collateral ); constructor (address _kiosk){ kiosk = IEnvelopNFTKiosk(_kiosk); } /** * @dev Throws if called by any account other than the display owner. */ modifier onlyDisplayOwner(bytes32 _displayNameHash) { require( kiosk.getDisplayOwner(_displayNameHash) == msg.sender, "Only for Display Owner" ); _; } function setCollateralPriceForDisplay( bytes32 _displayNameHash, address _erc20, KTypes.DenominatedPrice[] calldata _prices ) external virtual onlyDisplayOwner(_displayNameHash) { KTypes.DenominatedPrice[] storage prices = erc20CollateralPricesForDisplays[_displayNameHash][_erc20]; for (uint256 i = 0; i < _prices.length; ++ i) { prices.push(_prices[i]); emit CollateralPriceChanged(_displayNameHash, _erc20); } } function editCollateralPriceRecordForDisplay( bytes32 _displayNameHash, address _erc20, uint256 _priceIndex, KTypes.DenominatedPrice calldata _price ) external virtual onlyDisplayOwner(_displayNameHash) { erc20CollateralPricesForDisplays[_displayNameHash][_erc20][_priceIndex] = _price; emit CollateralPriceChanged(_displayNameHash, _erc20); } function setDefaultNFTPriceForDisplay( bytes32 _displayNameHash, KTypes.Price[] calldata _prices ) external virtual onlyDisplayOwner(_displayNameHash) { KTypes.Price[] storage prices = defaultNFTPriceForDisplay[_displayNameHash]; for (uint256 i = 0; i < _prices.length; ++ i) { prices.push(_prices[i]); emit DefaultPriceChanged( _displayNameHash, _prices[i].payWith, _prices[i].amount ); } } function editDefaultNFTPriceRecordForDisplay( bytes32 _displayNameHash, uint256 _priceIndex, KTypes.Price calldata _price ) external virtual onlyDisplayOwner(_displayNameHash) { defaultNFTPriceForDisplay[_displayNameHash][_priceIndex] = _price; emit DefaultPriceChanged( _displayNameHash, _price.payWith, _price.amount ); } function setTimeDiscountsForDisplay( bytes32 _displayNameHash, DiscountUntil[] calldata _discounts ) external virtual onlyDisplayOwner(_displayNameHash) { DiscountUntil[] storage discounts = timeDiscounts[_displayNameHash]; for (uint256 i = 0; i < _discounts.length; ++ i) { discounts.push(_discounts[i]); emit DiscountChanged( _displayNameHash, uint8(KTypes.DiscountType.TIME), bytes32(_discounts[i].untilDate), _discounts[i].discount.dsctPercent ); } } function editTimeDiscountsForDisplay( bytes32 _displayNameHash, uint256 _discountIndex, DiscountUntil calldata _discount ) external virtual onlyDisplayOwner(_displayNameHash) { timeDiscounts[_displayNameHash][_discountIndex] = _discount; emit DiscountChanged( _displayNameHash, uint8(KTypes.DiscountType.TIME), bytes32(_discount.untilDate), _discount.discount.dsctPercent ); } function setPromoDiscountForDisplay( bytes32 _displayNameHash, bytes32 _promoHash, DiscountUntil calldata _discount ) external virtual onlyDisplayOwner(_displayNameHash) { promoDiscounts[_displayNameHash][_promoHash] = _discount; emit DiscountChanged( _displayNameHash, uint8(KTypes.DiscountType.PROMO), _promoHash, _discount.discount.dsctPercent ); } function setRefereerDiscountForDisplay( bytes32 _displayNameHash, address _referrer, DiscountUntil calldata _discount ) external virtual onlyDisplayOwner(_displayNameHash) { referrerDiscounts[_displayNameHash][keccak256(abi.encode(_referrer))] = _discount; emit DiscountChanged( _displayNameHash, uint8(KTypes.DiscountType.REFERRAL), keccak256(abi.encode(_referrer)), _discount.discount.dsctPercent ); } ///////////////////////// function getItemPrices( ETypes.AssetItem memory _assetItem ) external view virtual returns (KTypes.Price[] memory) { // 1. Try get collateral IWNFT wnftContract = IWNFT(_assetItem.asset.contractAddress); try wnftContract.wnftInfo(_assetItem.tokenId) returns (ETypes.WNFT memory wnft){ KTypes.Place memory pl = _getVirtualPlace(_assetItem); // Only first collateral asset is tradable in this pricemodel KTypes.DenominatedPrice[] memory denPrices = _getCollateralUnitPrice( pl.display, wnft.collateral[0].asset.contractAddress ); KTypes.Price[] memory prices = new KTypes.Price[](denPrices.length); for (uint256 i = 0; i < denPrices.length; ++ i ){ // Calc wNFT price prices[i].payWith = denPrices[i].payWith; prices[i].amount = denPrices[i].amount * wnft.collateral[0].amount / denPrices[i].denominator; } return prices; } catch { return getDefaultDisplayPrices(_assetItem); } } function getDefaultDisplayPrices( ETypes.AssetItem memory _assetItem ) public view virtual returns (KTypes.Price[] memory _prices) { // get display of given item KTypes.Place memory pl = _getVirtualPlace(_assetItem); _prices = defaultNFTPriceForDisplay[pl.display]; } function getDisplayTimeDiscounts( bytes32 _displayNameHash ) public view virtual returns (DiscountUntil[] memory) { return timeDiscounts[_displayNameHash]; } function getItemDiscounts( ETypes.AssetItem memory _assetItem, address _buyer, address _referrer, bytes32 _promoHash ) public view virtual returns (KTypes.Discount[] memory) { KTypes.Place memory pl = _getVirtualPlace(_assetItem); // 1.First check time discounts for this display DiscountUntil[] storage tdArray = timeDiscounts[pl.display]; KTypes.Discount memory td; for (uint256 i = 0; i < tdArray.length; ++ i){ if (tdArray[i].untilDate > block.timestamp){ td = tdArray[i].discount; break; } } // This Price Model support 3 slots for discounts KTypes.Discount[] memory discounts = new KTypes.Discount[](3); for (uint256 i = 0; i < discounts.length; ++ i){ // add time discount to result discounts[0] = td; // add promo discount to result if (promoDiscounts[pl.display][_promoHash].untilDate > block.timestamp) { discounts[1] = KTypes.Discount( promoDiscounts[pl.display][_promoHash].discount.dsctType, promoDiscounts[pl.display][_promoHash].discount.dsctPercent ); } // add ref discount if (referrerDiscounts[pl.display][keccak256(abi.encode(_referrer))].untilDate > block.timestamp) { discounts[2] = KTypes.Discount( referrerDiscounts[pl.display][keccak256(abi.encode(_referrer))].discount.dsctType, referrerDiscounts[pl.display][keccak256(abi.encode(_referrer))].discount.dsctPercent ); } } return discounts; } function getBatchPrices( ETypes.AssetItem[] memory _assetItemArray ) external view virtual returns (KTypes.Price[] memory) { } function getBatchDiscounts( ETypes.AssetItem[] memory _assetItemArray, address _buyer, address _referrer, bytes32 _promoHash ) external view virtual returns (KTypes.Discount[] memory) { } function getCollateralUnitPrice( bytes32 _displayNameHash, address _erc20 ) external view returns(KTypes.DenominatedPrice[] memory){ return _getCollateralUnitPrice(_displayNameHash,_erc20); } /////////////////////////////////////////////////////////////////// function _getCollateralUnitPrice( bytes32 _displayNameHash, address _erc20 ) internal view returns(KTypes.DenominatedPrice[] memory){ return erc20CollateralPricesForDisplays[_displayNameHash][_erc20]; } function _getVirtualPlace(ETypes.AssetItem memory _assetItem) internal view returns(KTypes.Place memory place) { place = kiosk.getAssetItemPlace(_assetItem); if (place.display == bytes32(0)) { place.display = kiosk.DEFAULT_DISPLAY(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "LibEnvelopTypes.sol"; import "KTypes.sol"; interface IEnvelopNFTKiosk { function DEFAULT_DISPLAY() external view returns (bytes32); function buyAssetItem( ETypes.AssetItem calldata _assetItem, uint256 _priceIndex, address _buyer, address _referrer, string calldata _promo ) external payable; function getDisplayOwner( bytes32 _displayNameHash ) external view returns (address); function getAssetItemPlace( ETypes.AssetItem memory _assetItem ) external view returns (KTypes.Place memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import "LibEnvelopTypes.sol"; interface IWNFT { function wnftInfo(uint256 tokenId) external view returns (ETypes.WNFT memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.19; interface IModelWhiteList { function isModelEnabled(address _model) external view returns(bool); }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "EnvelopNFTKioskService.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"address","name":"_subscrRegistry","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":"bytes32","name":"display","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"enableAfter","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"disableAfter","type":"uint256"},{"indexed":false,"internalType":"address","name":"priceModel","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"DisplayChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"display","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"DisplayTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"display","type":"bytes32"},{"indexed":true,"internalType":"address","name":"assetContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"assetTokenId","type":"uint256"}],"name":"EnvelopPurchase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"customer","type":"address"},{"indexed":true,"internalType":"address","name":"payWithToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"payWithAmount","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"percentDiscount","type":"uint16"}],"name":"EnvelopReferrer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"display","type":"bytes32"},{"indexed":true,"internalType":"address","name":"assetContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"assetTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"placeIndex","type":"uint256"}],"name":"ItemAddedToDisplay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"display","type":"bytes32"},{"indexed":true,"internalType":"address","name":"assetContract","type":"address"},{"indexed":true,"internalType":"uint256","name":"assetTokenId","type":"uint256"}],"name":"ItemPriceChanged","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"},{"inputs":[],"name":"DEFAULT_DISPLAY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_INDEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"_prices","type":"tuple[]"}],"name":"addAssetItemPriceAtIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"},{"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":"_assetItems","type":"tuple[]"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"_prices","type":"tuple[]"}],"name":"addBatchItemsToDisplayWithSamePrice","outputs":[{"components":[{"internalType":"bytes32","name":"display","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct KTypes.Place[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"},{"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"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"_prices","type":"tuple[]"}],"name":"addItemToDisplay","outputs":[{"components":[{"internalType":"bytes32","name":"display","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct KTypes.Place","name":"place","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tariffIndex","type":"uint256"},{"internalType":"address","name":"_paymentToken","type":"address"},{"internalType":"uint256","name":"_paymentAmount","type":"uint256"},{"internalType":"uint16","name":"_agentFeePercent","type":"uint16"}],"name":"addPayOption","outputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"assetAtDisplay","outputs":[{"internalType":"bytes32","name":"display","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_agent","type":"address"},{"internalType":"uint256[]","name":"_serviceTariffIndexes","type":"uint256[]"}],"name":"authorizeAgentForService","outputs":[{"internalType":"uint256[]","name":"actualTariffs","type":"uint256[]"}],"stateMutability":"nonpayable","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":"uint256","name":"_priceIndex","type":"uint256"},{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"string","name":"_promo","type":"string"}],"name":"buyAssetItem","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"checkUser","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bool","name":"needFix","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"displays","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"enableAfter","type":"uint256"},{"internalType":"uint256","name":"disableAfter","type":"uint256"},{"internalType":"address","name":"priceModel","type":"address"}],"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":"uint256","name":"_priceIndex","type":"uint256"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price","name":"_price","type":"tuple"}],"name":"editAssetItemPriceAtIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tariffIndex","type":"uint256"},{"internalType":"uint256","name":"_payWithIndex","type":"uint256"},{"internalType":"address","name":"_paymentToken","type":"address"},{"internalType":"uint256","name":"_paymentAmount","type":"uint256"},{"internalType":"uint16","name":"_agentFeePercent","type":"uint16"}],"name":"editPayOption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tariffIndex","type":"uint256"},{"internalType":"uint256","name":"_timelockPeriod","type":"uint256"},{"internalType":"uint256","name":"_ticketValidPeriod","type":"uint256"},{"internalType":"uint256","name":"_counter","type":"uint256"},{"internalType":"bool","name":"_isAvailable","type":"bool"},{"internalType":"address","name":"_beneficiary","type":"address"}],"name":"editServiceTariff","outputs":[],"stateMutability":"nonpayable","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"}],"name":"getAssetItem","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"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":"nft","type":"tuple"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"prices","type":"tuple[]"}],"internalType":"struct KTypes.ItemForSale","name":"","type":"tuple"}],"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"}],"name":"getAssetItemPlace","outputs":[{"components":[{"internalType":"bytes32","name":"display","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct KTypes.Place","name":"","type":"tuple"}],"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":"_buyer","type":"address"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"string","name":"_promo","type":"string"}],"name":"getAssetItemPricesAndDiscounts","outputs":[{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"","type":"tuple[]"},{"components":[{"internalType":"enum KTypes.DiscountType","name":"dsctType","type":"uint8"},{"internalType":"uint16","name":"dsctPercent","type":"uint16"}],"internalType":"struct KTypes.Discount[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"}],"name":"getDisplay","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"enableAfter","type":"uint256"},{"internalType":"uint256","name":"disableAfter","type":"uint256"},{"internalType":"address","name":"priceModel","type":"address"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"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":"nft","type":"tuple"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"prices","type":"tuple[]"}],"internalType":"struct KTypes.ItemForSale[]","name":"items","type":"tuple[]"}],"internalType":"struct KTypes.Display","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"}],"name":"getDisplayAssetItems","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"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":"nft","type":"tuple"},{"components":[{"internalType":"address","name":"payWith","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct KTypes.Price[]","name":"prices","type":"tuple[]"}],"internalType":"struct KTypes.ItemForSale[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"}],"name":"getDisplayOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"hlpHashString","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"modelWhiteListAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"timelockPeriod","type":"uint256"},{"internalType":"uint256","name":"ticketValidPeriod","type":"uint256"},{"internalType":"uint256","name":"counter","type":"uint256"},{"internalType":"bool","name":"isAvailable","type":"bool"},{"internalType":"address","name":"beneficiary","type":"address"}],"internalType":"struct SubscriptionType","name":"subscription","type":"tuple"},{"components":[{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint16","name":"agentFeePercent","type":"uint16"}],"internalType":"struct PayOption[]","name":"payWith","type":"tuple[]"}],"internalType":"struct Tariff","name":"_newTariff","type":"tuple"}],"name":"newTariff","outputs":[{"internalType":"uint256","name":"tariffIndex","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"timelockPeriod","type":"uint256"},{"internalType":"uint256","name":"ticketValidPeriod","type":"uint256"},{"internalType":"uint256","name":"counter","type":"uint256"},{"internalType":"bool","name":"isAvailable","type":"bool"},{"internalType":"address","name":"beneficiary","type":"address"}],"internalType":"struct SubscriptionType","name":"subscription","type":"tuple"},{"components":[{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"uint16","name":"agentFeePercent","type":"uint16"}],"internalType":"struct PayOption[]","name":"payWith","type":"tuple[]"}],"internalType":"struct Tariff","name":"_newTariff","type":"tuple"}],"name":"registerServiceTariff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","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"}],"name":"removeLastPersonalPriceForAssetItem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serviceProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_enableAfter","type":"uint256"},{"internalType":"uint256","name":"_disableAfter","type":"uint256"},{"internalType":"address","name":"_priceModel","type":"address"}],"name":"setDisplayParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnable","type":"bool"}],"name":"setSubscriptionOnOff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_subscrRegistry","type":"address"}],"name":"setSubscriptionRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_modelWhiteList","type":"address"}],"name":"setWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionRegistry","outputs":[{"internalType":"contract ISubscriptionRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes32","name":"_displayNameHash","type":"bytes32"}],"name":"transferDisplay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e0604052600860a0908152674e46544b696f736b60c01b60c052620000259062000105565b6080526004805460ff60a01b1916600160a01b1790553480156200004857600080fd5b5060405162005018380380620050188339810160408190526200006b9162000189565b600160005580806001600160a01b038116620000bd5760405162461bcd60e51b815260206004820152600d60248201526c4e6f6e207a65726f206f6e6c7960981b604482015260640160405180910390fd5b60038054306001600160a01b031991821617909155600480549091166001600160a01b0392909216919091179055620000fd620000f73390565b62000137565b50506200020b565b6000816040516020016200011a9190620001bb565b604051602081830303815290604052805190602001209050919050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200019c57600080fd5b81516001600160a01b0381168114620001b457600080fd5b9392505050565b600060208083528351808285015260005b81811015620001ea57858101830151858201604001528201620001cc565b506000604082860101526040601f19601f8301168501019250505092915050565b608051614dd562000243600039600081816103d601528181610b99015281816117820152818161318d01526132330152614dd56000f3fe60806040526004361061021a5760003560e01c8063715018a611610123578063a3fafd05116100ab578063c7eecb751161006f578063c7eecb7514610731578063d52b403814610751578063d7fe513d1461077e578063f2fde38b146107ab578063fb8adca4146107cb57600080fd5b8063a3fafd0514610686578063abba145b146106b3578063b1d065f7146106d3578063ba5aa3f214610709578063bffe185a1461071e57600080fd5b80638d69e95e116100f25780638d69e95e146105e55780638da5cb5b1461060557806390b73458146106235780639e6c2959146106505780639ec30e4a1461066657600080fd5b8063715018a61461058357806378451d001461021f57806382b710e914610598578063864438fb146105b857600080fd5b80632eeb42b3116101a65780633f62c00e116101755780633f62c00e1461045857806346d5b1c9146104e45780635751869b14610512578063596b2bcc146105325780636aa633b61461055257600080fd5b80632eeb42b3146103c45780632f85b0ae146103f857806339e899ee146104185780633c727f491461043857600080fd5b80631e9d48cf116101ed5780631e9d48cf146102e85780631f16aef31461031f5780631f7b8b7b1461033f57806320da71701461036c578063299b2660146103a457600080fd5b80630c5620d61461021f5780630c7b1c13146102525780630ca9f90314610274578063140cf192146102c8575b600080fd5b34801561022b57600080fd5b5061023f61023a366004613cd7565b6107eb565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061027261026d366004613dbc565b610804565b005b34801561028057600080fd5b506102b361028f366004613e05565b60026020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610249565b3480156102d457600080fd5b506102726102e3366004613e7c565b61093e565b3480156102f457600080fd5b50610308610303366004613ecf565b610a32565b604080519215158352901515602083015201610249565b34801561032b57600080fd5b5061027261033a366004613eec565b610a47565b34801561034b57600080fd5b5061035f61035a366004613fcb565b610a65565b6040516102499190614025565b34801561037857600080fd5b5060045461038c906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b3480156103b057600080fd5b5061035f6103bf36600461403c565b610c82565b3480156103d057600080fd5b5061023f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040457600080fd5b50610272610413366004614099565b610db6565b34801561042457600080fd5b50610272610433366004613ecf565b610ef6565b34801561044457600080fd5b5060065461038c906001600160a01b031681565b34801561046457600080fd5b506104b0610473366004614106565b6001602081905260009182526040909120805491810154600282015460038301546004909301546001600160a01b03948516949283169391921685565b604080516001600160a01b03968716815294861660208601528401929092526060830152909116608082015260a001610249565b3480156104f057600080fd5b506105046104ff36600461411f565b610f20565b6040516102499291906141cd565b34801561051e57600080fd5b5061027261052d366004614277565b610f7b565b34801561053e57600080fd5b5061027261054d366004613e05565b610f97565b34801561055e57600080fd5b5060045461057390600160a01b900460ff1681565b6040519015158152602001610249565b34801561058f57600080fd5b50610272611050565b3480156105a457600080fd5b5061023f6105b33660046142cd565b611064565b3480156105c457600080fd5b506105d86105d3366004614106565b611094565b604051610249919061446c565b3480156105f157600080fd5b5060035461038c906001600160a01b031681565b34801561061157600080fd5b506005546001600160a01b031661038c565b34801561062f57600080fd5b5061064361063e36600461403c565b61129b565b60405161024991906144c7565b34801561065c57600080fd5b5061023f61271081565b34801561067257600080fd5b50610272610681366004613ecf565b61143d565b34801561069257600080fd5b506106a66106a13660046144da565b611467565b60405161024991906145ba565b3480156106bf57600080fd5b506102726106ce3660046145cd565b611482565b3480156106df57600080fd5b5061038c6106ee366004614106565b6000908152600160205260409020546001600160a01b031690565b34801561071557600080fd5b5061023f600081565b61027261072c3660046145ea565b6114a8565b34801561073d57600080fd5b5061027261074c36600461466e565b611d0a565b34801561075d57600080fd5b5061077161076c36600461468a565b611eaa565b604051610249919061474f565b34801561078a57600080fd5b5061079e610799366004614106565b611f7a565b60405161024991906147a6565b3480156107b757600080fd5b506102726107c6366004613ecf565b6120eb565b3480156107d757600080fd5b5061023f6107e63660046147b9565b612164565b60006107f5612183565b6107fe826121dd565b92915050565b60006108186103bf3686900386018661403c565b9050336001600160a01b0316600160008360000151815260200190815260200160002060050182602001518154811061085357610853614803565b60009182526020909120600590910201546001600160a01b0316146108d85780516000908152600160205260409020546001600160a01b031633146108d85760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9103234b9b83630bc9037bbb732b960511b60448201526064015b60405180910390fd5b6108ec816000015182602001518585612251565b604084018035906109009060208701613ecf565b82516040516001600160a01b0392909216917fe27d3d65f32610d390b50c9f6af70c0bfe910e5909c6ea9c91f2a8be3924af9290600090a450505050565b60006109526103bf3686900386018661403c565b9050336001600160a01b0316600160008360000151815260200190815260200160002060050182602001518154811061098d5761098d614803565b60009182526020909120600590910201546001600160a01b031614610a1e5780516000908152600160205260409020546001600160a01b03163314610a1e5760405162461bcd60e51b815260206004820152602160248201527f4f6e6c7920646973706c6179206f776e65722063616e206564697420707269636044820152606560f81b60648201526084016108cf565b6108ec8160000151826020015185856122b3565b600080610a3e83612348565b91509150915091565b610a4f612183565b610a5d8686868686866123e7565b505050505050565b6040805180820182526000808252602080830182905286518101516001600160a01b03168252600281528382208782015183528152908390208351808501909452805480855260019091015491840191909152909190158015610aca57506020810151155b610b0b5760405162461bcd60e51b8152602060048201526012602482015271416c726561647920617420646973706c617960701b60448201526064016108cf565b610b16853330612470565b85604001511115610b795760405162461bcd60e51b815260206004820152602760248201527f496e73756666696369656e742062616c616e6365206166746572204e465420746044820152663930b739b332b960c91b60648201526084016108cf565b6000868152600160205260409020546001600160a01b03163314610c11577f00000000000000000000000000000000000000000000000000000000000000008614610c115760405162461bcd60e51b815260206004820152602260248201527f4f6e6c792044656661756c7420446973706c617920616c6c6f7720666f7220616044820152616e7960f01b60648201526084016108cf565b610c1e8633878787612af4565b915084602001518560000151602001516001600160a01b031683600001517fbebac2c3edec4f43f08e2877981bb81ddfa37d20a2f9ab5981f05761d16d004f8560200151604051610c7191815260200190565b60405180910390a450949350505050565b604080518082019091526000808252602082015260038251516007811115610cac57610cac614199565b03610d165730610cbb83612cc7565b6001600160a01b031614610d115760405162461bcd60e51b815260206004820152601d60248201527f4173736574206e6f74207472616e73666572656420746f206b696f736b00000060448201526064016108cf565b610d73565b8160400151610d258330612de4565b1015610d735760405162461bcd60e51b815260206004820152601d60248201527f4173736574206e6f74207472616e73666572656420746f206b696f736b00000060448201526064016108cf565b5080516020908101516001600160a01b03166000908152600282526040808220938301518252928252829020825180840190935280548352600101549082015290565b600654604051638e5f9ac560e01b81526001600160a01b03838116600483015290911690638e5f9ac590602401602060405180830381865afa158015610e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e249190614819565b610e705760405162461bcd60e51b815260206004820152601e60248201527f556e6578706563746564207072696365206d6f64656c2061646472657373000060448201526064016108cf565b60006001600160a01b031660016000610ebe89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b81526020810191909152604001600020546001600160a01b031603610ee857610ee633612f6c565b505b610a5d868686868686612ffb565b610efe612183565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b606080610f6d878787610f6888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b613164565b915091509550959350505050565b610f83612183565b610f90858585858561359b565b5050505050565b6000818152600160205260409020546001600160a01b03163314610ff65760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9102234b9b83630bc9027bbb732b960511b60448201526064016108cf565b60008181526001602052604080822080546001600160a01b0319166001600160a01b03861690811790915590519091339184917f22c910a2dcce4230a03ebd4d4c2512b57da90f10d23745a22c8a37e16fb6939391a45050565b611058612183565b611062600061361e565b565b600081604051602001611077919061485a565b604051602081830303815290604052805190602001209050919050565b6110e86040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b03168152602001606081525090565b6000828152600160208181526040808420815160c08101835281546001600160a01b0390811682529482015485168185015260028201548184015260038201546060820152600482015490941660808501526005810180548351818602810186019094528084529495919460a08701949192909184015b8282101561128d57600084815260209081902060408051606080820183526005870290930180546001600160a01b03168252825160a0810190935260018101805492959194918601939290918391908201908390829060ff1660078111156111c9576111c9614199565b60078111156111da576111da614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b82821015611276576000848152602090819020604080518082019091526002850290910180546001600160a01b0316825260019081015482840152908352909201910161122e565b50505050815250508152602001906001019061115f565b505050915250909392505050565b6112e360408051606080820183526000808352835160a08101855291820181815260808301829052825260208281018290529382015290918201908152602001606081525090565b60006112ee83610c82565b9050600160008260000151815260200190815260200160002060050181602001518154811061131f5761131f614803565b60009182526020918290206040805160608082018352600590940290920180546001600160a01b03168352815160a08101909252600181018054939591949186019390918391908201908390829060ff16600781111561138157611381614199565b600781111561139257611392614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b8282101561142e576000848152602090819020604080518082019091526002850290910180546001600160a01b031682526001908101548284015290835290920191016113e6565b50505091525090949350505050565b611445612183565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6060611471612183565b61147b8383613670565b9392505050565b61148a612183565b60048054911515600160a01b0260ff60a01b19909216919091179055565b6114b06136eb565b6040805160a08101825260006060820181815260808301829052825260208201819052918101829052908061152e6114ed368b90038b018b61403c565b8888610f6889898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b90925090506000805b82518110156116715782818151811061155257611552614803565b60200260200101516020015161ffff168261156d91906148a3565b9150600183828151811061158357611583614803565b60200260200101516000015160078111156115a0576115a0614199565b0361166157838a815181106115b7576115b7614803565b6020026020010151600001516001600160a01b0316336001600160a01b0316896001600160a01b03167fbe6f7c5115afd6431e5364f25028ab5075992833e68b41bb7e9cf9298b11c513878e8151811061161357611613614803565b60200260200101516020015187868151811061163157611631614803565b60200260200101516020015160405161165892919091825261ffff16602082015260400190565b60405180910390a45b61166a816148b6565b9050611537565b506040518060600160405280604051806040016040528060006001600160a01b0316878e815181106116a5576116a5614803565b6020026020010151600001516001600160a01b0316146116c65760026116c9565b60015b60078111156116da576116da614199565b8152602001868d815181106116f1576116f1614803565b6020026020010151600001516001600160a01b03168152508152602001600081526020016127108361271061172691906148cf565b868d8151811061173857611738614803565b60200260200101516020015161174e91906148e2565b61175891906148f9565b8152509350505050600080611777898036038101906103bf919061403c565b80519091506117cb577f000000000000000000000000000000000000000000000000000000000000000060008181526001602081815260408320909101549284528301526001600160a01b03169150611b0f565b60016000826000015181526020019081526020016000206005018160200151815481106117fa576117fa614803565b6000918252602080832060059283020154845184526001918290526040909320909101546001600160a01b039092169350611834916148cf565b816020015114611a53578051600090815260016020819052604080832084518452922060059081015492019161186a91906148cf565b8154811061187a5761187a614803565b906000526020600020906005020160016000836000015181526020019081526020016000206005018260200151815481106118b7576118b7614803565b60009182526020909120825460059092020180546001600160a01b0319166001600160a01b03909216919091178155600180830180548284018054929390928492849260ff90911691839160ff199091169083600781111561191b5761191b614199565b021790555090548154610100600160a81b031916610100918290046001600160a01b0316909102179055600182810154908201556002918201549101556004828101805461196c9284019190613a69565b5090505060405180604001604052808260000151815260200182602001518152506002600060016000856000015181526020019081526020016000206005018460200151815481106119c0576119c0614803565b6000918252602080832060059283020160019081015461010090046001600160a01b031685528482019590955260409384018320875184529481529282209286015192018054919290918110611a1857611a18614803565b906000526020600020906005020160010160010154815260200190815260200160002060008201518160000155602082015181600101559050505b80516000908152600160205260409020600501805480611a7557611a7561491b565b60008281526020812060056000199093019283020180546001600160a01b03191681556001810180546001600160a81b0319169055600281018290556003810182905590611ac66004830182613ae1565b5050905560026000611ade60408c0160208d01613ecf565b6001600160a01b03168152602080820192909252604090810160009081208c83013582529092528120818155600101555b805160009081526001602052604090206002015442118015611b44575080516000908152600160205260409020600301544211155b611b7f5760405162461bcd60e51b815260206004820152600c60248201526b4f6e6c7920696e2074696d6560a01b60448201526064016108cf565b60018351516007811115611b9557611b95614199565b03611c2757611ba5833084612470565b83604001511115611bc85760405162461bcd60e51b81526004016108cf90614931565b6000836040015134611bda91906148cf565b1115611c22576040830151339081906108fc90611bf790346148cf565b6040518115909202916000818181858888f19350505050158015611c1f573d6000803e3d6000fd5b50505b611c97565b3415611c695760405162461bcd60e51b81526020600482015260116024820152704f6e6c7920455243323020746f6b656e7360781b60448201526064016108cf565b611c74833384612470565b83604001511115611c975760405162461bcd60e51b81526004016108cf90614931565b611cb0611ca9368b90038b018b61403c565b3089612470565b5060408901803590611cc59060208c01613ecf565b82516040516001600160a01b0392909216917f0640a25b0e045d99b4dac93cd08c63e3c6803633e285b50f81ab66270fbbd56390600090a4505050610a5d6001600055565b6000611d1e6103bf3684900384018461403c565b9050336001600160a01b03166001600083600001518152602001908152602001600020600501826020015181548110611d5957611d59614803565b60009182526020909120600590910201546001600160a01b031614611dd95780516000908152600160205260409020546001600160a01b03163314611dd95760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9103234b9b83630bc9037bbb732b960511b60448201526064016108cf565b60006001600083600001518152602001908152602001600020600501826020015181548110611e0a57611e0a614803565b9060005260206000209060050201600401905080805480611e2d57611e2d61491b565b6000828152602080822060026000199094019384020180546001600160a01b031916815560010191909155915560408401803591611e6d91908601613ecf565b83516040516001600160a01b0392909216917fe27d3d65f32610d390b50c9f6af70c0bfe910e5909c6ea9c91f2a8be3924af9290600090a4505050565b6060600084516001600160401b03811115611ec757611ec7613b24565b604051908082528060200260200182016040528015611f0c57816020015b6040805180820190915260008082526020820152815260200190600190039081611ee55790505b50905060005b8551811015611f6e57611f4087878381518110611f3157611f31614803565b60200260200101518787610a65565b828281518110611f5257611f52614803565b602002602001018190525080611f67906148b6565b9050611f12565b5090505b949350505050565b606060016000838152602001908152602001600020600501805480602002602001604051908101604052809291908181526020016000905b828210156120e057600084815260209081902060408051606080820183526005870290930180546001600160a01b03168252825160a0810190935260018101805492959194918601939290918391908201908390829060ff16600781111561201c5761201c614199565b600781111561202d5761202d614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b828210156120c9576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101612081565b505050508152505081526020019060010190611fb2565b505050509050919050565b6120f3612183565b6001600160a01b0381166121585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108cf565b6121618161361e565b50565b600061216e612183565b61217a85858585613744565b95945050505050565b6005546001600160a01b031633146110625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108cf565b600480546040516278451d60e81b81526000926001600160a01b03909216916378451d009161220e9186910161497c565b6020604051808303816000875af115801561222d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614a32565b600084815260016020526040902060050180548291908590811061227757612277614803565b9060005260206000209060050201600401838154811061229957612299614803565b90600052602060002090600202018181610a5d9190614a4b565b60008481526001602052604081206005018054859081106122d6576122d6614803565b9060005260206000209060050201905060005b82811015610a5d578160040184848381811061230757612307614803565b8354600181018555600094855260209094206040909102929092019260020290910190506123358282614a4b565b505080612341906148b6565b90506122e9565b6004546000908190600160a01b900460ff16156123de576004805460405163496d511d60e11b81526001600160a01b03868116938201939093523060248201529116906392daa23a906044016040805180830381865afa1580156123b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d49190614a81565b9092509050915091565b60019150915091565b60048054604051631f16aef360e01b815291820188905260248201879052604482018690526064820185905283151560848301526001600160a01b0383811660a48401521690631f16aef39060c401600060405180830381600087803b15801561245057600080fd5b505af1158015612464573d6000803e3d6000fd5b50505050505050505050565b6000806001855151600781111561248957612489614199565b03612543575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d80600081146124df576040519150601f19603f3d011682016040523d82523d6000602084013e6124e4565b606091505b50509050806125275760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016108cf565b61253b826001600160a01b038616316148cf565b925050612aec565b6002855151600781111561255957612559614199565b036126af578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156125ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125cf9190614a32565b9050306001600160a01b03851603612608576040850151855160200151612603916001600160a01b039091169085906137ce565b61262c565b604085015185516020015161262c916001600160a01b039091169086908690613836565b8451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a08231906024015b602060405180830381865afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e9190614a32565b6126a891906148cf565b9150612aec565b600385515160078111156126c5576126c5614199565b14801561275157508451602090810151908601516040516331a9108f60e11b815260048101919091526001600160a01b03868116921690636352211e90602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190614abb565b6001600160a01b0316145b15612964578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156127a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c79190614a32565b8551602090810151908701516040516323b872dd60e01b81526001600160a01b0388811660048301528781166024830152604482019290925292935016906323b872dd90606401600060405180830381600087803b15801561282857600080fd5b505af115801561283c573d6000803e3d6000fd5b50505050826001600160a01b03168560000151602001516001600160a01b0316636352211e87602001516040518263ffffffff1660e01b815260040161288491815260200190565b602060405180830381865afa1580156128a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c59190614abb565b6001600160a01b031614801561295557508451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a0823190602401602060405180830381865afa158015612923573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129479190614a32565b61295191906148cf565b6001145b1561295f57600191505b612aec565b6004855151600781111561297a5761297a614199565b03612ad157845160209081015190860151604051627eeac760e11b81526001600160a01b038681166004830152602482019290925291169062fdd58e90604401602060405180830381865afa1580156129d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fb9190614a32565b8551602090810151908701516040808901519051637921219560e11b81526001600160a01b03898116600483015288811660248301526044820193909352606481019190915260a06084820152600060a4820152929350169063f242432a9060c401600060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b5050865160209081015190880151604051627eeac760e11b81526001600160a01b03888116600483015260248201929092528594509116915062fdd58e9060440161265d565b8460405163391102fb60e01b81526004016108cf9190614ad8565b509392505050565b60408051808201909152600080825260208201526000868152600160208181526040832060059081018054808501825590855291909320920290910180546001600160a01b0319166001600160a01b0388161781558551805182840180549394899491939284929091839160ff191690836007811115612b7657612b76614199565b021790555060209182015181546001600160a01b0390911661010002610100600160a81b031990911617905582015160018201556040909101516002909101558215612c205760005b83811015612c1e5781600401858583818110612bdd57612bdd614803565b835460018101855560009485526020909420604090910292909201926002029091019050612c0b8282614a4b565b505080612c17906148b6565b9050612bbf565b505b60408051808201825288815260008981526001602081815293909120600501549192830191612c4f91906148cf565b905285516020908101516001600160a01b03908116600090815260028084526040808320858c018051855290865281842087518155968601516001978801559a518501519093168252835281812098518152978252968790208751808901909852805488529091015490860152509295945050505050565b600060018251516007811115612cdf57612cdf614199565b03612cec57506000919050565b60028251516007811115612d0257612d02614199565b03612d0f57506000919050565b60038251516007811115612d2557612d25614199565b03612da6578151602090810151908301516040516331a9108f60e11b81526001600160a01b0390921691636352211e91612d659160040190815260200190565b602060405180830381865afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614abb565b60048251516007811115612dbc57612dbc614199565b03612dc957506000919050565b8160405163391102fb60e01b81526004016108cf9190614ad8565b600060018351516007811115612dfc57612dfc614199565b03612e1257506001600160a01b038116316107fe565b60028351516007811115612e2857612e28614199565b03612ea6578251602001516040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa158015612e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9f9190614a32565b90506107fe565b60038351516007811115612ebc57612ebc614199565b03612ef6578251602001516040516370a0823160e01b81526001600160a01b038481166004830152909116906370a0823190602401612e5e565b60048351516007811115612f0c57612f0c614199565b03612f5157825160209081015190840151604051627eeac760e11b81526001600160a01b038581166004830152602482019290925291169062fdd58e90604401612e5e565b8260405163391102fb60e01b81526004016108cf9190614ad8565b600454600090600160a01b900460ff1615612ff35760048054604051632e5f2cf160e01b81526001600160a01b0385811693820193909352911690632e5f2cf1906024016020604051808303816000875af1158015612fcf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614819565b506001919050565b600061303c87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b6000818152600160205260409020549091506001600160a01b031633148061307957506000818152600160205260409020546001600160a01b0316155b6130be5760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9102234b9b83630bc9027bbb732b960511b60448201526064016108cf565b6000818152600160208190526040918290208054336001600160a01b03199182168117835592820180546001600160a01b038b81169184168217909255600284018a9055600384018990556004909301805491881691909216179055915183907f4af8e278eab954a95814248126e9442f4b93f859428b736d603382314e14ac8990613153908990899089908f908f90614ae6565b60405180910390a450505050505050565b606080600061317287610c82565b805190915015801561318657506020810151155b156132e7577f0000000000000000000000000000000000000000000000000000000000000000600090815260016020526040908190206004908101549151631ddd707b60e31b81526001600160a01b039092169163eeeb83d8916131ec918b9101614ad8565b600060405180830381865afa158015613209573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132319190810190614b35565b7f0000000000000000000000000000000000000000000000000000000000000000600090815260016020526040908190206004908101549151632d15a65360e21b81526001600160a01b039092169163b456994c91613298918c918c918c918c9101614be8565b600060405180830381865afa1580156132b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132dd9190810190614c1d565b9250925050613592565b6000600160008360000151815260200190815260200160002060050182602001518154811061331857613318614803565b906000526020600020906005020160040180549050111561347857600160008260000151815260200190815260200160002060050181602001518154811061336257613362614803565b600091825260208083208451845260019091526040928390206004908101549351632d15a65360e21b815260059093029091018101926001600160a01b03169163b456994c916133ba918c918c918c918c9101614be8565b600060405180830381865afa1580156133d7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133ff9190810190614c1d565b81805480602002602001604051908101604052809291908181526020016000905b82821015613468576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101613420565b5050505091509250925050613592565b8051600090815260016020526040908190206004908101549151631ddd707b60e31b81526001600160a01b039092169163eeeb83d8916134ba918b9101614ad8565b600060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134ff9190810190614b35565b8151600090815260016020526040908190206004908101549151632d15a65360e21b81526001600160a01b039092169163b456994c91613547918c918c918c918c9101614be8565b600060405180830381865afa158015613564573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261358c9190810190614c1d565b92509250505b94509492505050565b6004805460405163650aac6160e01b8152918201879052602482018690526001600160a01b0385811660448401526064830185905261ffff84166084840152169063650aac619060a401600060405180830381600087803b1580156135ff57600080fd5b505af1158015613613573d6000803e3d6000fd5b505050505050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6004805460405163a3fafd0560e01b81526060926001600160a01b039092169163a3fafd05916136a4918791879101614cda565b6000604051808303816000875af11580156136c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261147b9190810190614cfe565b60026000540361373d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108cf565b6002600055565b60048054604051639aab948160e01b81529182018690526001600160a01b0385811660248401526044830185905261ffff84166064840152600092911690639aab9481906084016020604051808303816000875af11580156137aa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a9190614a32565b6040516001600160a01b03831660248201526044810182905261383190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613874565b505050565b6040516001600160a01b038085166024830152831660448201526064810182905261386e9085906323b872dd60e01b906084016137fa565b50505050565b60006138c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139469092919063ffffffff16565b80519091501561383157808060200190518101906138e79190614819565b6138315760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108cf565b6060611f72848460008585600080866001600160a01b0316858760405161396d9190614d83565b60006040518083038185875af1925050503d80600081146139aa576040519150601f19603f3d011682016040523d82523d6000602084013e6139af565b606091505b50915091506139c0878383876139cb565b979650505050505050565b60608315613a3a578251600003613a33576001600160a01b0385163b613a335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108cf565b5081611f72565b611f728383815115613a4f5781518083602001fd5b8060405162461bcd60e51b81526004016108cf919061485a565b828054828255906000526020600020906002028101928215613ad15760005260206000209160020282015b82811115613ad157825482546001600160a01b0319166001600160a01b039091161782556001808401549083015560029283019290910190613a94565b50613add929150613afe565b5090565b508054600082556002029060005260206000209081019061216191905b5b80821115613add5780546001600160a01b031916815560006001820155600201613aff565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715613b5c57613b5c613b24565b60405290565b604080519081016001600160401b0381118282101715613b5c57613b5c613b24565b60405160a081016001600160401b0381118282101715613b5c57613b5c613b24565b604051601f8201601f191681016001600160401b0381118282101715613bce57613bce613b24565b604052919050565b801515811461216157600080fd5b6001600160a01b038116811461216157600080fd5b60006001600160401b03821115613c1257613c12613b24565b5060051b60200190565b61ffff8116811461216157600080fd5b600082601f830112613c3d57600080fd5b81356020613c52613c4d83613bf9565b613ba6565b82815260609283028501820192828201919087851115613c7157600080fd5b8387015b85811015613cca5781818a031215613c8d5760008081fd5b613c95613b3a565b8135613ca081613be4565b81528186013586820152604080830135613cb981613c1c565b908201528452928401928101613c75565b5090979650505050505050565b600060208284031215613ce957600080fd5b81356001600160401b0380821115613d0057600080fd5b9083019081850360c0811215613d1557600080fd5b613d1d613b62565b60a0821215613d2b57600080fd5b613d33613b84565b91508335825260208401356020830152604084013560408301526060840135613d5b81613bd6565b60608301526080840135613d6e81613be4565b608083015290815260a08301359082821115613d8957600080fd5b613d9587838601613c2c565b60208201529695505050505050565b600060808284031215613db657600080fd5b50919050565b600080600083850360e0811215613dd257600080fd5b613ddc8686613da4565b9350608085013592506040609f1982011215613df757600080fd5b5060a0840190509250925092565b60008060408385031215613e1857600080fd5b8235613e2381613be4565b946020939093013593505050565b60008083601f840112613e4357600080fd5b5081356001600160401b03811115613e5a57600080fd5b6020830191508360208260061b8501011115613e7557600080fd5b9250929050565b600080600060a08486031215613e9157600080fd5b613e9b8585613da4565b925060808401356001600160401b03811115613eb657600080fd5b613ec286828701613e31565b9497909650939450505050565b600060208284031215613ee157600080fd5b813561147b81613be4565b60008060008060008060c08789031215613f0557600080fd5b863595506020870135945060408701359350606087013592506080870135613f2c81613bd6565b915060a0870135613f3c81613be4565b809150509295509295509295565b6008811061216157600080fd5b60008183036080811215613f6a57600080fd5b613f72613b3a565b91506040811215613f8257600080fd5b50613f8b613b62565b8235613f9681613f4a565b81526020830135613fa681613be4565b8060208301525080825250604082013560208201526060820135604082015292915050565b60008060008060c08587031215613fe157600080fd5b84359350613ff28660208701613f57565b925060a08501356001600160401b0381111561400d57600080fd5b61401987828801613e31565b95989497509550505050565b8151815260208083015190820152604081016107fe565b60006080828403121561404e57600080fd5b61147b8383613f57565b60008083601f84011261406a57600080fd5b5081356001600160401b0381111561408157600080fd5b602083019150836020828501011115613e7557600080fd5b60008060008060008060a087890312156140b257600080fd5b86356001600160401b038111156140c857600080fd5b6140d489828a01614058565b90975095505060208701356140e881613be4565b935060408701359250606087013591506080870135613f3c81613be4565b60006020828403121561411857600080fd5b5035919050565b600080600080600060e0868803121561413757600080fd5b6141418787613f57565b9450608086013561415181613be4565b935060a086013561416181613be4565b925060c08601356001600160401b0381111561417c57600080fd5b61418888828901614058565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b6008811061216157634e487b7160e01b600052602160045260246000fd5b60408082528351828201819052600091906020906060850190828801855b8281101561421e57815180516001600160a01b0316855260209081015190850152604084019350908401906001016141eb565b5050508481038286015285518082528683019183019060005b81811015614269578351805161424c816141af565b845285015161ffff16858401529284019291850191600101614237565b509098975050505050505050565b600080600080600060a0868803121561428f57600080fd5b853594506020860135935060408601356142a881613be4565b92506060860135915060808601356142bf81613c1c565b809150509295509295909350565b600060208083850312156142e057600080fd5b82356001600160401b03808211156142f757600080fd5b818501915085601f83011261430b57600080fd5b81358181111561431d5761431d613b24565b61432f601f8201601f19168501613ba6565b9150808252868482850101111561434557600080fd5b8084840185840137600090820190930192909252509392505050565b8051805161436e816141af565b83526020908101516001600160a01b0316818401528101516040808401919091520151606090910152565b80516001600160a01b0316825260208082015160009160c08501916143c082870182614361565b50604084015160c060a087015280519283905281019160009060e08701905b8083101561441657845180516001600160a01b031683526020908101519083015260408201915083850194506001830192506143df565b509695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015613cca57601f1986840301895261445a838351614399565b9884019892509083019060010161443e565b60208152600060018060a01b0380845116602084015280602085015116604084015260408401516060840152606084015160808401528060808501511660a08401525060a083015160c080840152611f7260e0840182614421565b60208152600061147b6020830184614399565b600080604083850312156144ed57600080fd5b82356144f881613be4565b91506020838101356001600160401b0381111561451457600080fd5b8401601f8101861361452557600080fd5b8035614533613c4d82613bf9565b81815260059190911b8201830190838101908883111561455257600080fd5b928401925b8284101561457057833582529284019290840190614557565b80955050505050509250929050565b600081518084526020808501945080840160005b838110156145af57815187529582019590820190600101614593565b509495945050505050565b60208152600061147b602083018461457f565b6000602082840312156145df57600080fd5b813561147b81613bd6565b600080600080600080610100878903121561460457600080fd5b61460e8888613da4565b95506080870135945060a087013561462581613be4565b935060c087013561463581613be4565b925060e08701356001600160401b0381111561465057600080fd5b61465c89828a01614058565b979a9699509497509295939492505050565b60006080828403121561468057600080fd5b61147b8383613da4565b600080600080606085870312156146a057600080fd5b843593506020808601356001600160401b03808211156146bf57600080fd5b818801915088601f8301126146d357600080fd5b81356146e1613c4d82613bf9565b81815260079190911b8301840190848101908b83111561470057600080fd5b938501935b82851015614729576147178c86613f57565b82528582019150608085019450614705565b97505050604088013592508083111561474157600080fd5b505061401987828801613e31565b602080825282518282018190526000919060409081850190868401855b828110156147995761478984835180518252602090810151910152565b928401929085019060010161476c565b5091979650505050505050565b60208152600061147b6020830184614421565b600080600080608085870312156147cf57600080fd5b8435935060208501356147e181613be4565b92506040850135915060608501356147f881613c1c565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561482b57600080fd5b815161147b81613bd6565b60005b83811015614851578181015183820152602001614839565b50506000910152565b6020815260008251806020840152614879816040850160208701614836565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107fe576107fe61488d565b6000600182016148c8576148c861488d565b5060010190565b818103818111156107fe576107fe61488d565b80820281158282048414176107fe576107fe61488d565b60008261491657634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fd5b6020808252602b908201527f496e73756666696369656e742062616c616e6365206166746572207061796d6560408201526a373a103a3930b739b332b960a91b606082015260800190565b602080825282518051838301528082015160408085019190915280820151606080860191909152808301511515608080870191909152909201516001600160a01b0390811660a08601528584015160c080870152805160e08701819052600095949185019386939290916101008901905b80861015614a24578651805186168352888101518984015284015161ffff16848301529587019560019590950194908201906149ed565b509998505050505050505050565b600060208284031215614a4457600080fd5b5051919050565b8135614a5681613be4565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b60008060408385031215614a9457600080fd5b8251614a9f81613bd6565b6020840151909250614ab081613bd6565b809150509250929050565b600060208284031215614acd57600080fd5b815161147b81613be4565b608081016107fe8284614361565b858152602081018590526001600160a01b03841660408201526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020808385031215614b4857600080fd5b82516001600160401b03811115614b5e57600080fd5b8301601f81018513614b6f57600080fd5b8051614b7d613c4d82613bf9565b81815260069190911b82018301908381019087831115614b9c57600080fd5b928401925b828410156139c05760408489031215614bba5760008081fd5b614bc2613b62565b8451614bcd81613be4565b81528486015186820152825260409093019290840190614ba1565b60e08101614bf68287614361565b6001600160a01b0394851660808301529290931660a084015260c090920191909152919050565b60006020808385031215614c3057600080fd5b82516001600160401b03811115614c4657600080fd5b8301601f81018513614c5757600080fd5b8051614c65613c4d82613bf9565b81815260069190911b82018301908381019087831115614c8457600080fd5b928401925b828410156139c05760408489031215614ca25760008081fd5b614caa613b62565b8451614cb581613f4a565b815284860151614cc481613c1c565b8187015282526040939093019290840190614c89565b6001600160a01b0383168152604060208201819052600090611f729083018461457f565b60006020808385031215614d1157600080fd5b82516001600160401b03811115614d2757600080fd5b8301601f81018513614d3857600080fd5b8051614d46613c4d82613bf9565b81815260059190911b82018301908381019087831115614d6557600080fd5b928401925b828410156139c057835182529284019290840190614d6a565b60008251614d95818460208701614836565b919091019291505056fea26469706673582212204a56e366ffa227b44e5b0422f65d11dcdb8a9054f7c9d8158a62016ae81abaf064736f6c63430008130033000000000000000000000000bde298fcd625d77c30cb6f1ad661a6ca4f41ae67
Deployed Bytecode
0x60806040526004361061021a5760003560e01c8063715018a611610123578063a3fafd05116100ab578063c7eecb751161006f578063c7eecb7514610731578063d52b403814610751578063d7fe513d1461077e578063f2fde38b146107ab578063fb8adca4146107cb57600080fd5b8063a3fafd0514610686578063abba145b146106b3578063b1d065f7146106d3578063ba5aa3f214610709578063bffe185a1461071e57600080fd5b80638d69e95e116100f25780638d69e95e146105e55780638da5cb5b1461060557806390b73458146106235780639e6c2959146106505780639ec30e4a1461066657600080fd5b8063715018a61461058357806378451d001461021f57806382b710e914610598578063864438fb146105b857600080fd5b80632eeb42b3116101a65780633f62c00e116101755780633f62c00e1461045857806346d5b1c9146104e45780635751869b14610512578063596b2bcc146105325780636aa633b61461055257600080fd5b80632eeb42b3146103c45780632f85b0ae146103f857806339e899ee146104185780633c727f491461043857600080fd5b80631e9d48cf116101ed5780631e9d48cf146102e85780631f16aef31461031f5780631f7b8b7b1461033f57806320da71701461036c578063299b2660146103a457600080fd5b80630c5620d61461021f5780630c7b1c13146102525780630ca9f90314610274578063140cf192146102c8575b600080fd5b34801561022b57600080fd5b5061023f61023a366004613cd7565b6107eb565b6040519081526020015b60405180910390f35b34801561025e57600080fd5b5061027261026d366004613dbc565b610804565b005b34801561028057600080fd5b506102b361028f366004613e05565b60026020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610249565b3480156102d457600080fd5b506102726102e3366004613e7c565b61093e565b3480156102f457600080fd5b50610308610303366004613ecf565b610a32565b604080519215158352901515602083015201610249565b34801561032b57600080fd5b5061027261033a366004613eec565b610a47565b34801561034b57600080fd5b5061035f61035a366004613fcb565b610a65565b6040516102499190614025565b34801561037857600080fd5b5060045461038c906001600160a01b031681565b6040516001600160a01b039091168152602001610249565b3480156103b057600080fd5b5061035f6103bf36600461403c565b610c82565b3480156103d057600080fd5b5061023f7f0b6fa5fd572a777383d3c573d07a54a7f90effe232d6da72acb8d30c0ba8a93d81565b34801561040457600080fd5b50610272610413366004614099565b610db6565b34801561042457600080fd5b50610272610433366004613ecf565b610ef6565b34801561044457600080fd5b5060065461038c906001600160a01b031681565b34801561046457600080fd5b506104b0610473366004614106565b6001602081905260009182526040909120805491810154600282015460038301546004909301546001600160a01b03948516949283169391921685565b604080516001600160a01b03968716815294861660208601528401929092526060830152909116608082015260a001610249565b3480156104f057600080fd5b506105046104ff36600461411f565b610f20565b6040516102499291906141cd565b34801561051e57600080fd5b5061027261052d366004614277565b610f7b565b34801561053e57600080fd5b5061027261054d366004613e05565b610f97565b34801561055e57600080fd5b5060045461057390600160a01b900460ff1681565b6040519015158152602001610249565b34801561058f57600080fd5b50610272611050565b3480156105a457600080fd5b5061023f6105b33660046142cd565b611064565b3480156105c457600080fd5b506105d86105d3366004614106565b611094565b604051610249919061446c565b3480156105f157600080fd5b5060035461038c906001600160a01b031681565b34801561061157600080fd5b506005546001600160a01b031661038c565b34801561062f57600080fd5b5061064361063e36600461403c565b61129b565b60405161024991906144c7565b34801561065c57600080fd5b5061023f61271081565b34801561067257600080fd5b50610272610681366004613ecf565b61143d565b34801561069257600080fd5b506106a66106a13660046144da565b611467565b60405161024991906145ba565b3480156106bf57600080fd5b506102726106ce3660046145cd565b611482565b3480156106df57600080fd5b5061038c6106ee366004614106565b6000908152600160205260409020546001600160a01b031690565b34801561071557600080fd5b5061023f600081565b61027261072c3660046145ea565b6114a8565b34801561073d57600080fd5b5061027261074c36600461466e565b611d0a565b34801561075d57600080fd5b5061077161076c36600461468a565b611eaa565b604051610249919061474f565b34801561078a57600080fd5b5061079e610799366004614106565b611f7a565b60405161024991906147a6565b3480156107b757600080fd5b506102726107c6366004613ecf565b6120eb565b3480156107d757600080fd5b5061023f6107e63660046147b9565b612164565b60006107f5612183565b6107fe826121dd565b92915050565b60006108186103bf3686900386018661403c565b9050336001600160a01b0316600160008360000151815260200190815260200160002060050182602001518154811061085357610853614803565b60009182526020909120600590910201546001600160a01b0316146108d85780516000908152600160205260409020546001600160a01b031633146108d85760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9103234b9b83630bc9037bbb732b960511b60448201526064015b60405180910390fd5b6108ec816000015182602001518585612251565b604084018035906109009060208701613ecf565b82516040516001600160a01b0392909216917fe27d3d65f32610d390b50c9f6af70c0bfe910e5909c6ea9c91f2a8be3924af9290600090a450505050565b60006109526103bf3686900386018661403c565b9050336001600160a01b0316600160008360000151815260200190815260200160002060050182602001518154811061098d5761098d614803565b60009182526020909120600590910201546001600160a01b031614610a1e5780516000908152600160205260409020546001600160a01b03163314610a1e5760405162461bcd60e51b815260206004820152602160248201527f4f6e6c7920646973706c6179206f776e65722063616e206564697420707269636044820152606560f81b60648201526084016108cf565b6108ec8160000151826020015185856122b3565b600080610a3e83612348565b91509150915091565b610a4f612183565b610a5d8686868686866123e7565b505050505050565b6040805180820182526000808252602080830182905286518101516001600160a01b03168252600281528382208782015183528152908390208351808501909452805480855260019091015491840191909152909190158015610aca57506020810151155b610b0b5760405162461bcd60e51b8152602060048201526012602482015271416c726561647920617420646973706c617960701b60448201526064016108cf565b610b16853330612470565b85604001511115610b795760405162461bcd60e51b815260206004820152602760248201527f496e73756666696369656e742062616c616e6365206166746572204e465420746044820152663930b739b332b960c91b60648201526084016108cf565b6000868152600160205260409020546001600160a01b03163314610c11577f0b6fa5fd572a777383d3c573d07a54a7f90effe232d6da72acb8d30c0ba8a93d8614610c115760405162461bcd60e51b815260206004820152602260248201527f4f6e6c792044656661756c7420446973706c617920616c6c6f7720666f7220616044820152616e7960f01b60648201526084016108cf565b610c1e8633878787612af4565b915084602001518560000151602001516001600160a01b031683600001517fbebac2c3edec4f43f08e2877981bb81ddfa37d20a2f9ab5981f05761d16d004f8560200151604051610c7191815260200190565b60405180910390a450949350505050565b604080518082019091526000808252602082015260038251516007811115610cac57610cac614199565b03610d165730610cbb83612cc7565b6001600160a01b031614610d115760405162461bcd60e51b815260206004820152601d60248201527f4173736574206e6f74207472616e73666572656420746f206b696f736b00000060448201526064016108cf565b610d73565b8160400151610d258330612de4565b1015610d735760405162461bcd60e51b815260206004820152601d60248201527f4173736574206e6f74207472616e73666572656420746f206b696f736b00000060448201526064016108cf565b5080516020908101516001600160a01b03166000908152600282526040808220938301518252928252829020825180840190935280548352600101549082015290565b600654604051638e5f9ac560e01b81526001600160a01b03838116600483015290911690638e5f9ac590602401602060405180830381865afa158015610e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e249190614819565b610e705760405162461bcd60e51b815260206004820152601e60248201527f556e6578706563746564207072696365206d6f64656c2061646472657373000060448201526064016108cf565b60006001600160a01b031660016000610ebe89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b81526020810191909152604001600020546001600160a01b031603610ee857610ee633612f6c565b505b610a5d868686868686612ffb565b610efe612183565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b606080610f6d878787610f6888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b613164565b915091509550959350505050565b610f83612183565b610f90858585858561359b565b5050505050565b6000818152600160205260409020546001600160a01b03163314610ff65760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9102234b9b83630bc9027bbb732b960511b60448201526064016108cf565b60008181526001602052604080822080546001600160a01b0319166001600160a01b03861690811790915590519091339184917f22c910a2dcce4230a03ebd4d4c2512b57da90f10d23745a22c8a37e16fb6939391a45050565b611058612183565b611062600061361e565b565b600081604051602001611077919061485a565b604051602081830303815290604052805190602001209050919050565b6110e86040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b03168152602001606081525090565b6000828152600160208181526040808420815160c08101835281546001600160a01b0390811682529482015485168185015260028201548184015260038201546060820152600482015490941660808501526005810180548351818602810186019094528084529495919460a08701949192909184015b8282101561128d57600084815260209081902060408051606080820183526005870290930180546001600160a01b03168252825160a0810190935260018101805492959194918601939290918391908201908390829060ff1660078111156111c9576111c9614199565b60078111156111da576111da614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b82821015611276576000848152602090819020604080518082019091526002850290910180546001600160a01b0316825260019081015482840152908352909201910161122e565b50505050815250508152602001906001019061115f565b505050915250909392505050565b6112e360408051606080820183526000808352835160a08101855291820181815260808301829052825260208281018290529382015290918201908152602001606081525090565b60006112ee83610c82565b9050600160008260000151815260200190815260200160002060050181602001518154811061131f5761131f614803565b60009182526020918290206040805160608082018352600590940290920180546001600160a01b03168352815160a08101909252600181018054939591949186019390918391908201908390829060ff16600781111561138157611381614199565b600781111561139257611392614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b8282101561142e576000848152602090819020604080518082019091526002850290910180546001600160a01b031682526001908101548284015290835290920191016113e6565b50505091525090949350505050565b611445612183565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6060611471612183565b61147b8383613670565b9392505050565b61148a612183565b60048054911515600160a01b0260ff60a01b19909216919091179055565b6114b06136eb565b6040805160a08101825260006060820181815260808301829052825260208201819052918101829052908061152e6114ed368b90038b018b61403c565b8888610f6889898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b90925090506000805b82518110156116715782818151811061155257611552614803565b60200260200101516020015161ffff168261156d91906148a3565b9150600183828151811061158357611583614803565b60200260200101516000015160078111156115a0576115a0614199565b0361166157838a815181106115b7576115b7614803565b6020026020010151600001516001600160a01b0316336001600160a01b0316896001600160a01b03167fbe6f7c5115afd6431e5364f25028ab5075992833e68b41bb7e9cf9298b11c513878e8151811061161357611613614803565b60200260200101516020015187868151811061163157611631614803565b60200260200101516020015160405161165892919091825261ffff16602082015260400190565b60405180910390a45b61166a816148b6565b9050611537565b506040518060600160405280604051806040016040528060006001600160a01b0316878e815181106116a5576116a5614803565b6020026020010151600001516001600160a01b0316146116c65760026116c9565b60015b60078111156116da576116da614199565b8152602001868d815181106116f1576116f1614803565b6020026020010151600001516001600160a01b03168152508152602001600081526020016127108361271061172691906148cf565b868d8151811061173857611738614803565b60200260200101516020015161174e91906148e2565b61175891906148f9565b8152509350505050600080611777898036038101906103bf919061403c565b80519091506117cb577f0b6fa5fd572a777383d3c573d07a54a7f90effe232d6da72acb8d30c0ba8a93d60008181526001602081815260408320909101549284528301526001600160a01b03169150611b0f565b60016000826000015181526020019081526020016000206005018160200151815481106117fa576117fa614803565b6000918252602080832060059283020154845184526001918290526040909320909101546001600160a01b039092169350611834916148cf565b816020015114611a53578051600090815260016020819052604080832084518452922060059081015492019161186a91906148cf565b8154811061187a5761187a614803565b906000526020600020906005020160016000836000015181526020019081526020016000206005018260200151815481106118b7576118b7614803565b60009182526020909120825460059092020180546001600160a01b0319166001600160a01b03909216919091178155600180830180548284018054929390928492849260ff90911691839160ff199091169083600781111561191b5761191b614199565b021790555090548154610100600160a81b031916610100918290046001600160a01b0316909102179055600182810154908201556002918201549101556004828101805461196c9284019190613a69565b5090505060405180604001604052808260000151815260200182602001518152506002600060016000856000015181526020019081526020016000206005018460200151815481106119c0576119c0614803565b6000918252602080832060059283020160019081015461010090046001600160a01b031685528482019590955260409384018320875184529481529282209286015192018054919290918110611a1857611a18614803565b906000526020600020906005020160010160010154815260200190815260200160002060008201518160000155602082015181600101559050505b80516000908152600160205260409020600501805480611a7557611a7561491b565b60008281526020812060056000199093019283020180546001600160a01b03191681556001810180546001600160a81b0319169055600281018290556003810182905590611ac66004830182613ae1565b5050905560026000611ade60408c0160208d01613ecf565b6001600160a01b03168152602080820192909252604090810160009081208c83013582529092528120818155600101555b805160009081526001602052604090206002015442118015611b44575080516000908152600160205260409020600301544211155b611b7f5760405162461bcd60e51b815260206004820152600c60248201526b4f6e6c7920696e2074696d6560a01b60448201526064016108cf565b60018351516007811115611b9557611b95614199565b03611c2757611ba5833084612470565b83604001511115611bc85760405162461bcd60e51b81526004016108cf90614931565b6000836040015134611bda91906148cf565b1115611c22576040830151339081906108fc90611bf790346148cf565b6040518115909202916000818181858888f19350505050158015611c1f573d6000803e3d6000fd5b50505b611c97565b3415611c695760405162461bcd60e51b81526020600482015260116024820152704f6e6c7920455243323020746f6b656e7360781b60448201526064016108cf565b611c74833384612470565b83604001511115611c975760405162461bcd60e51b81526004016108cf90614931565b611cb0611ca9368b90038b018b61403c565b3089612470565b5060408901803590611cc59060208c01613ecf565b82516040516001600160a01b0392909216917f0640a25b0e045d99b4dac93cd08c63e3c6803633e285b50f81ab66270fbbd56390600090a4505050610a5d6001600055565b6000611d1e6103bf3684900384018461403c565b9050336001600160a01b03166001600083600001518152602001908152602001600020600501826020015181548110611d5957611d59614803565b60009182526020909120600590910201546001600160a01b031614611dd95780516000908152600160205260409020546001600160a01b03163314611dd95760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9103234b9b83630bc9037bbb732b960511b60448201526064016108cf565b60006001600083600001518152602001908152602001600020600501826020015181548110611e0a57611e0a614803565b9060005260206000209060050201600401905080805480611e2d57611e2d61491b565b6000828152602080822060026000199094019384020180546001600160a01b031916815560010191909155915560408401803591611e6d91908601613ecf565b83516040516001600160a01b0392909216917fe27d3d65f32610d390b50c9f6af70c0bfe910e5909c6ea9c91f2a8be3924af9290600090a4505050565b6060600084516001600160401b03811115611ec757611ec7613b24565b604051908082528060200260200182016040528015611f0c57816020015b6040805180820190915260008082526020820152815260200190600190039081611ee55790505b50905060005b8551811015611f6e57611f4087878381518110611f3157611f31614803565b60200260200101518787610a65565b828281518110611f5257611f52614803565b602002602001018190525080611f67906148b6565b9050611f12565b5090505b949350505050565b606060016000838152602001908152602001600020600501805480602002602001604051908101604052809291908181526020016000905b828210156120e057600084815260209081902060408051606080820183526005870290930180546001600160a01b03168252825160a0810190935260018101805492959194918601939290918391908201908390829060ff16600781111561201c5761201c614199565b600781111561202d5761202d614199565b8152905461010090046001600160a01b031660209182015290825260018301548282015260029092015460409182015291835260048401805483518184028101840190945280845293820193909160009084015b828210156120c9576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101612081565b505050508152505081526020019060010190611fb2565b505050509050919050565b6120f3612183565b6001600160a01b0381166121585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108cf565b6121618161361e565b50565b600061216e612183565b61217a85858585613744565b95945050505050565b6005546001600160a01b031633146110625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108cf565b600480546040516278451d60e81b81526000926001600160a01b03909216916378451d009161220e9186910161497c565b6020604051808303816000875af115801561222d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614a32565b600084815260016020526040902060050180548291908590811061227757612277614803565b9060005260206000209060050201600401838154811061229957612299614803565b90600052602060002090600202018181610a5d9190614a4b565b60008481526001602052604081206005018054859081106122d6576122d6614803565b9060005260206000209060050201905060005b82811015610a5d578160040184848381811061230757612307614803565b8354600181018555600094855260209094206040909102929092019260020290910190506123358282614a4b565b505080612341906148b6565b90506122e9565b6004546000908190600160a01b900460ff16156123de576004805460405163496d511d60e11b81526001600160a01b03868116938201939093523060248201529116906392daa23a906044016040805180830381865afa1580156123b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d49190614a81565b9092509050915091565b60019150915091565b60048054604051631f16aef360e01b815291820188905260248201879052604482018690526064820185905283151560848301526001600160a01b0383811660a48401521690631f16aef39060c401600060405180830381600087803b15801561245057600080fd5b505af1158015612464573d6000803e3d6000fd5b50505050505050505050565b6000806001855151600781111561248957612489614199565b03612543575060408085015190516001600160a01b0384168031926000928381818185875af1925050503d80600081146124df576040519150601f19603f3d011682016040523d82523d6000602084013e6124e4565b606091505b50509050806125275760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b60448201526064016108cf565b61253b826001600160a01b038616316148cf565b925050612aec565b6002855151600781111561255957612559614199565b036126af578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156125ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125cf9190614a32565b9050306001600160a01b03851603612608576040850151855160200151612603916001600160a01b039091169085906137ce565b61262c565b604085015185516020015161262c916001600160a01b039091169086908690613836565b8451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a08231906024015b602060405180830381865afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e9190614a32565b6126a891906148cf565b9150612aec565b600385515160078111156126c5576126c5614199565b14801561275157508451602090810151908601516040516331a9108f60e11b815260048101919091526001600160a01b03868116921690636352211e90602401602060405180830381865afa158015612722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127469190614abb565b6001600160a01b0316145b15612964578451602001516040516370a0823160e01b81526001600160a01b038581166004830152909116906370a0823190602401602060405180830381865afa1580156127a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c79190614a32565b8551602090810151908701516040516323b872dd60e01b81526001600160a01b0388811660048301528781166024830152604482019290925292935016906323b872dd90606401600060405180830381600087803b15801561282857600080fd5b505af115801561283c573d6000803e3d6000fd5b50505050826001600160a01b03168560000151602001516001600160a01b0316636352211e87602001516040518263ffffffff1660e01b815260040161288491815260200190565b602060405180830381865afa1580156128a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c59190614abb565b6001600160a01b031614801561295557508451602001516040516370a0823160e01b81526001600160a01b038581166004830152839216906370a0823190602401602060405180830381865afa158015612923573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129479190614a32565b61295191906148cf565b6001145b1561295f57600191505b612aec565b6004855151600781111561297a5761297a614199565b03612ad157845160209081015190860151604051627eeac760e11b81526001600160a01b038681166004830152602482019290925291169062fdd58e90604401602060405180830381865afa1580156129d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fb9190614a32565b8551602090810151908701516040808901519051637921219560e11b81526001600160a01b03898116600483015288811660248301526044820193909352606481019190915260a06084820152600060a4820152929350169063f242432a9060c401600060405180830381600087803b158015612a7757600080fd5b505af1158015612a8b573d6000803e3d6000fd5b5050865160209081015190880151604051627eeac760e11b81526001600160a01b03888116600483015260248201929092528594509116915062fdd58e9060440161265d565b8460405163391102fb60e01b81526004016108cf9190614ad8565b509392505050565b60408051808201909152600080825260208201526000868152600160208181526040832060059081018054808501825590855291909320920290910180546001600160a01b0319166001600160a01b0388161781558551805182840180549394899491939284929091839160ff191690836007811115612b7657612b76614199565b021790555060209182015181546001600160a01b0390911661010002610100600160a81b031990911617905582015160018201556040909101516002909101558215612c205760005b83811015612c1e5781600401858583818110612bdd57612bdd614803565b835460018101855560009485526020909420604090910292909201926002029091019050612c0b8282614a4b565b505080612c17906148b6565b9050612bbf565b505b60408051808201825288815260008981526001602081815293909120600501549192830191612c4f91906148cf565b905285516020908101516001600160a01b03908116600090815260028084526040808320858c018051855290865281842087518155968601516001978801559a518501519093168252835281812098518152978252968790208751808901909852805488529091015490860152509295945050505050565b600060018251516007811115612cdf57612cdf614199565b03612cec57506000919050565b60028251516007811115612d0257612d02614199565b03612d0f57506000919050565b60038251516007811115612d2557612d25614199565b03612da6578151602090810151908301516040516331a9108f60e11b81526001600160a01b0390921691636352211e91612d659160040190815260200190565b602060405180830381865afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614abb565b60048251516007811115612dbc57612dbc614199565b03612dc957506000919050565b8160405163391102fb60e01b81526004016108cf9190614ad8565b600060018351516007811115612dfc57612dfc614199565b03612e1257506001600160a01b038116316107fe565b60028351516007811115612e2857612e28614199565b03612ea6578251602001516040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024015b602060405180830381865afa158015612e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9f9190614a32565b90506107fe565b60038351516007811115612ebc57612ebc614199565b03612ef6578251602001516040516370a0823160e01b81526001600160a01b038481166004830152909116906370a0823190602401612e5e565b60048351516007811115612f0c57612f0c614199565b03612f5157825160209081015190840151604051627eeac760e11b81526001600160a01b038581166004830152602482019290925291169062fdd58e90604401612e5e565b8260405163391102fb60e01b81526004016108cf9190614ad8565b600454600090600160a01b900460ff1615612ff35760048054604051632e5f2cf160e01b81526001600160a01b0385811693820193909352911690632e5f2cf1906024016020604051808303816000875af1158015612fcf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190614819565b506001919050565b600061303c87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061106492505050565b6000818152600160205260409020549091506001600160a01b031633148061307957506000818152600160205260409020546001600160a01b0316155b6130be5760405162461bcd60e51b815260206004820152601660248201527527b7363c903337b9102234b9b83630bc9027bbb732b960511b60448201526064016108cf565b6000818152600160208190526040918290208054336001600160a01b03199182168117835592820180546001600160a01b038b81169184168217909255600284018a9055600384018990556004909301805491881691909216179055915183907f4af8e278eab954a95814248126e9442f4b93f859428b736d603382314e14ac8990613153908990899089908f908f90614ae6565b60405180910390a450505050505050565b606080600061317287610c82565b805190915015801561318657506020810151155b156132e7577f0b6fa5fd572a777383d3c573d07a54a7f90effe232d6da72acb8d30c0ba8a93d600090815260016020526040908190206004908101549151631ddd707b60e31b81526001600160a01b039092169163eeeb83d8916131ec918b9101614ad8565b600060405180830381865afa158015613209573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132319190810190614b35565b7f0b6fa5fd572a777383d3c573d07a54a7f90effe232d6da72acb8d30c0ba8a93d600090815260016020526040908190206004908101549151632d15a65360e21b81526001600160a01b039092169163b456994c91613298918c918c918c918c9101614be8565b600060405180830381865afa1580156132b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132dd9190810190614c1d565b9250925050613592565b6000600160008360000151815260200190815260200160002060050182602001518154811061331857613318614803565b906000526020600020906005020160040180549050111561347857600160008260000151815260200190815260200160002060050181602001518154811061336257613362614803565b600091825260208083208451845260019091526040928390206004908101549351632d15a65360e21b815260059093029091018101926001600160a01b03169163b456994c916133ba918c918c918c918c9101614be8565b600060405180830381865afa1580156133d7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526133ff9190810190614c1d565b81805480602002602001604051908101604052809291908181526020016000905b82821015613468576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101613420565b5050505091509250925050613592565b8051600090815260016020526040908190206004908101549151631ddd707b60e31b81526001600160a01b039092169163eeeb83d8916134ba918b9101614ad8565b600060405180830381865afa1580156134d7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526134ff9190810190614b35565b8151600090815260016020526040908190206004908101549151632d15a65360e21b81526001600160a01b039092169163b456994c91613547918c918c918c918c9101614be8565b600060405180830381865afa158015613564573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261358c9190810190614c1d565b92509250505b94509492505050565b6004805460405163650aac6160e01b8152918201879052602482018690526001600160a01b0385811660448401526064830185905261ffff84166084840152169063650aac619060a401600060405180830381600087803b1580156135ff57600080fd5b505af1158015613613573d6000803e3d6000fd5b505050505050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6004805460405163a3fafd0560e01b81526060926001600160a01b039092169163a3fafd05916136a4918791879101614cda565b6000604051808303816000875af11580156136c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261147b9190810190614cfe565b60026000540361373d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108cf565b6002600055565b60048054604051639aab948160e01b81529182018690526001600160a01b0385811660248401526044830185905261ffff84166064840152600092911690639aab9481906084016020604051808303816000875af11580156137aa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a9190614a32565b6040516001600160a01b03831660248201526044810182905261383190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613874565b505050565b6040516001600160a01b038085166024830152831660448201526064810182905261386e9085906323b872dd60e01b906084016137fa565b50505050565b60006138c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166139469092919063ffffffff16565b80519091501561383157808060200190518101906138e79190614819565b6138315760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108cf565b6060611f72848460008585600080866001600160a01b0316858760405161396d9190614d83565b60006040518083038185875af1925050503d80600081146139aa576040519150601f19603f3d011682016040523d82523d6000602084013e6139af565b606091505b50915091506139c0878383876139cb565b979650505050505050565b60608315613a3a578251600003613a33576001600160a01b0385163b613a335760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108cf565b5081611f72565b611f728383815115613a4f5781518083602001fd5b8060405162461bcd60e51b81526004016108cf919061485a565b828054828255906000526020600020906002028101928215613ad15760005260206000209160020282015b82811115613ad157825482546001600160a01b0319166001600160a01b039091161782556001808401549083015560029283019290910190613a94565b50613add929150613afe565b5090565b508054600082556002029060005260206000209081019061216191905b5b80821115613add5780546001600160a01b031916815560006001820155600201613aff565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715613b5c57613b5c613b24565b60405290565b604080519081016001600160401b0381118282101715613b5c57613b5c613b24565b60405160a081016001600160401b0381118282101715613b5c57613b5c613b24565b604051601f8201601f191681016001600160401b0381118282101715613bce57613bce613b24565b604052919050565b801515811461216157600080fd5b6001600160a01b038116811461216157600080fd5b60006001600160401b03821115613c1257613c12613b24565b5060051b60200190565b61ffff8116811461216157600080fd5b600082601f830112613c3d57600080fd5b81356020613c52613c4d83613bf9565b613ba6565b82815260609283028501820192828201919087851115613c7157600080fd5b8387015b85811015613cca5781818a031215613c8d5760008081fd5b613c95613b3a565b8135613ca081613be4565b81528186013586820152604080830135613cb981613c1c565b908201528452928401928101613c75565b5090979650505050505050565b600060208284031215613ce957600080fd5b81356001600160401b0380821115613d0057600080fd5b9083019081850360c0811215613d1557600080fd5b613d1d613b62565b60a0821215613d2b57600080fd5b613d33613b84565b91508335825260208401356020830152604084013560408301526060840135613d5b81613bd6565b60608301526080840135613d6e81613be4565b608083015290815260a08301359082821115613d8957600080fd5b613d9587838601613c2c565b60208201529695505050505050565b600060808284031215613db657600080fd5b50919050565b600080600083850360e0811215613dd257600080fd5b613ddc8686613da4565b9350608085013592506040609f1982011215613df757600080fd5b5060a0840190509250925092565b60008060408385031215613e1857600080fd5b8235613e2381613be4565b946020939093013593505050565b60008083601f840112613e4357600080fd5b5081356001600160401b03811115613e5a57600080fd5b6020830191508360208260061b8501011115613e7557600080fd5b9250929050565b600080600060a08486031215613e9157600080fd5b613e9b8585613da4565b925060808401356001600160401b03811115613eb657600080fd5b613ec286828701613e31565b9497909650939450505050565b600060208284031215613ee157600080fd5b813561147b81613be4565b60008060008060008060c08789031215613f0557600080fd5b863595506020870135945060408701359350606087013592506080870135613f2c81613bd6565b915060a0870135613f3c81613be4565b809150509295509295509295565b6008811061216157600080fd5b60008183036080811215613f6a57600080fd5b613f72613b3a565b91506040811215613f8257600080fd5b50613f8b613b62565b8235613f9681613f4a565b81526020830135613fa681613be4565b8060208301525080825250604082013560208201526060820135604082015292915050565b60008060008060c08587031215613fe157600080fd5b84359350613ff28660208701613f57565b925060a08501356001600160401b0381111561400d57600080fd5b61401987828801613e31565b95989497509550505050565b8151815260208083015190820152604081016107fe565b60006080828403121561404e57600080fd5b61147b8383613f57565b60008083601f84011261406a57600080fd5b5081356001600160401b0381111561408157600080fd5b602083019150836020828501011115613e7557600080fd5b60008060008060008060a087890312156140b257600080fd5b86356001600160401b038111156140c857600080fd5b6140d489828a01614058565b90975095505060208701356140e881613be4565b935060408701359250606087013591506080870135613f3c81613be4565b60006020828403121561411857600080fd5b5035919050565b600080600080600060e0868803121561413757600080fd5b6141418787613f57565b9450608086013561415181613be4565b935060a086013561416181613be4565b925060c08601356001600160401b0381111561417c57600080fd5b61418888828901614058565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b6008811061216157634e487b7160e01b600052602160045260246000fd5b60408082528351828201819052600091906020906060850190828801855b8281101561421e57815180516001600160a01b0316855260209081015190850152604084019350908401906001016141eb565b5050508481038286015285518082528683019183019060005b81811015614269578351805161424c816141af565b845285015161ffff16858401529284019291850191600101614237565b509098975050505050505050565b600080600080600060a0868803121561428f57600080fd5b853594506020860135935060408601356142a881613be4565b92506060860135915060808601356142bf81613c1c565b809150509295509295909350565b600060208083850312156142e057600080fd5b82356001600160401b03808211156142f757600080fd5b818501915085601f83011261430b57600080fd5b81358181111561431d5761431d613b24565b61432f601f8201601f19168501613ba6565b9150808252868482850101111561434557600080fd5b8084840185840137600090820190930192909252509392505050565b8051805161436e816141af565b83526020908101516001600160a01b0316818401528101516040808401919091520151606090910152565b80516001600160a01b0316825260208082015160009160c08501916143c082870182614361565b50604084015160c060a087015280519283905281019160009060e08701905b8083101561441657845180516001600160a01b031683526020908101519083015260408201915083850194506001830192506143df565b509695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015613cca57601f1986840301895261445a838351614399565b9884019892509083019060010161443e565b60208152600060018060a01b0380845116602084015280602085015116604084015260408401516060840152606084015160808401528060808501511660a08401525060a083015160c080840152611f7260e0840182614421565b60208152600061147b6020830184614399565b600080604083850312156144ed57600080fd5b82356144f881613be4565b91506020838101356001600160401b0381111561451457600080fd5b8401601f8101861361452557600080fd5b8035614533613c4d82613bf9565b81815260059190911b8201830190838101908883111561455257600080fd5b928401925b8284101561457057833582529284019290840190614557565b80955050505050509250929050565b600081518084526020808501945080840160005b838110156145af57815187529582019590820190600101614593565b509495945050505050565b60208152600061147b602083018461457f565b6000602082840312156145df57600080fd5b813561147b81613bd6565b600080600080600080610100878903121561460457600080fd5b61460e8888613da4565b95506080870135945060a087013561462581613be4565b935060c087013561463581613be4565b925060e08701356001600160401b0381111561465057600080fd5b61465c89828a01614058565b979a9699509497509295939492505050565b60006080828403121561468057600080fd5b61147b8383613da4565b600080600080606085870312156146a057600080fd5b843593506020808601356001600160401b03808211156146bf57600080fd5b818801915088601f8301126146d357600080fd5b81356146e1613c4d82613bf9565b81815260079190911b8301840190848101908b83111561470057600080fd5b938501935b82851015614729576147178c86613f57565b82528582019150608085019450614705565b97505050604088013592508083111561474157600080fd5b505061401987828801613e31565b602080825282518282018190526000919060409081850190868401855b828110156147995761478984835180518252602090810151910152565b928401929085019060010161476c565b5091979650505050505050565b60208152600061147b6020830184614421565b600080600080608085870312156147cf57600080fd5b8435935060208501356147e181613be4565b92506040850135915060608501356147f881613c1c565b939692955090935050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561482b57600080fd5b815161147b81613bd6565b60005b83811015614851578181015183820152602001614839565b50506000910152565b6020815260008251806020840152614879816040850160208701614836565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107fe576107fe61488d565b6000600182016148c8576148c861488d565b5060010190565b818103818111156107fe576107fe61488d565b80820281158282048414176107fe576107fe61488d565b60008261491657634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fd5b6020808252602b908201527f496e73756666696369656e742062616c616e6365206166746572207061796d6560408201526a373a103a3930b739b332b960a91b606082015260800190565b602080825282518051838301528082015160408085019190915280820151606080860191909152808301511515608080870191909152909201516001600160a01b0390811660a08601528584015160c080870152805160e08701819052600095949185019386939290916101008901905b80861015614a24578651805186168352888101518984015284015161ffff16848301529587019560019590950194908201906149ed565b509998505050505050505050565b600060208284031215614a4457600080fd5b5051919050565b8135614a5681613be4565b81546001600160a01b0319166001600160a01b03919091161781556020919091013560019190910155565b60008060408385031215614a9457600080fd5b8251614a9f81613bd6565b6020840151909250614ab081613bd6565b809150509250929050565b600060208284031215614acd57600080fd5b815161147b81613be4565b608081016107fe8284614361565b858152602081018590526001600160a01b03841660408201526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60006020808385031215614b4857600080fd5b82516001600160401b03811115614b5e57600080fd5b8301601f81018513614b6f57600080fd5b8051614b7d613c4d82613bf9565b81815260069190911b82018301908381019087831115614b9c57600080fd5b928401925b828410156139c05760408489031215614bba5760008081fd5b614bc2613b62565b8451614bcd81613be4565b81528486015186820152825260409093019290840190614ba1565b60e08101614bf68287614361565b6001600160a01b0394851660808301529290931660a084015260c090920191909152919050565b60006020808385031215614c3057600080fd5b82516001600160401b03811115614c4657600080fd5b8301601f81018513614c5757600080fd5b8051614c65613c4d82613bf9565b81815260069190911b82018301908381019087831115614c8457600080fd5b928401925b828410156139c05760408489031215614ca25760008081fd5b614caa613b62565b8451614cb581613f4a565b815284860151614cc481613c1c565b8187015282526040939093019290840190614c89565b6001600160a01b0383168152604060208201819052600090611f729083018461457f565b60006020808385031215614d1157600080fd5b82516001600160401b03811115614d2757600080fd5b8301601f81018513614d3857600080fd5b8051614d46613c4d82613bf9565b81815260059190911b82018301908381019087831115614d6557600080fd5b928401925b828410156139c057835182529284019290840190614d6a565b60008251614d95818460208701614836565b919091019291505056fea26469706673582212204a56e366ffa227b44e5b0422f65d11dcdb8a9054f7c9d8158a62016ae81abaf064736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bde298fcd625d77c30cb6f1ad661a6ca4f41ae67
-----Decoded View---------------
Arg [0] : _subscrRegistry (address): 0xbdE298FcD625d77C30CB6F1Ad661a6CA4F41aE67
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000bde298fcd625d77c30cb6f1ad661a6ca4f41ae67
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.