From 95ee48eff359f0dad96bb8016c23c49ed3f8339c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 14 Jun 2024 15:28:51 +0200 Subject: [PATCH 01/27] remove versions from unlock js --- packages/unlock-js/scripts/compressAbi.js | 25 +- packages/unlock-js/src/abis.ts | 499 ---------------------- 2 files changed, 2 insertions(+), 522 deletions(-) diff --git a/packages/unlock-js/scripts/compressAbi.js b/packages/unlock-js/scripts/compressAbi.js index c4242bc9761..f14dda0165c 100644 --- a/packages/unlock-js/scripts/compressAbi.js +++ b/packages/unlock-js/scripts/compressAbi.js @@ -11,29 +11,8 @@ const fs = require('fs') const path = require('path') const abis = require('@unlock-protocol/contracts') -const unlockVersions = [ - 'v4', - 'v6', - 'v7', - 'v8', - 'v9', - 'v10', - 'v11', - 'v12', - 'v13', -] -const publicLockVersions = [ - 'v4', - 'v6', - 'v7', - 'v8', - 'v9', - 'v10', - 'v11', - 'v12', - 'v13', - 'v14', -] +const unlockVersions = ['v9', 'v10', 'v11', 'v12', 'v13'] +const publicLockVersions = ['v9', 'v10', 'v11', 'v12', 'v13', 'v14'] const data = { PublicLock: publicLockVersions.reduce( diff --git a/packages/unlock-js/src/abis.ts b/packages/unlock-js/src/abis.ts index 28587ef4857..b7cccec5799 100644 --- a/packages/unlock-js/src/abis.ts +++ b/packages/unlock-js/src/abis.ts @@ -4,377 +4,6 @@ const abis = { "PublicLock": { - "v4": { - "contractName": "PublicLock", - "abi": [ - "function supportsInterface(bytes4 interfaceId) constant view returns (bool)", - "function owners(uint256) constant view returns (address)", - "function name() constant view returns (string)", - "function getApproved(uint256 _tokenId) constant view returns (address)", - "function approve(address _approved,uint256 _tokenId) payable", - "function updateBeneficiary(address _beneficiary)", - "function refundPenaltyDenominator() constant view returns (uint256)", - "function refundPenaltyNumerator() constant view returns (uint256)", - "function unlockProtocol() constant view returns (address)", - "function getOwnersByPage(uint256 _page,uint256 _pageSize) constant view returns (address[])", - "function keyPrice() constant view returns (uint256)", - "function expirationDuration() constant view returns (uint256)", - "function onERC721Received(address,address,uint256,bytes) returns (bytes4)", - "function totalSupply() constant view returns (uint256)", - "function updateKeyPrice(uint256 _keyPrice)", - "function cancelAndRefund()", - "function transferFrom(address _from,address _recipient,uint256 _tokenId) payable", - "function withdraw(uint256 _amount)", - "function setBaseTokenURI(string _baseTokenURI)", - "function beneficiary() constant view returns (address)", - "function updateRefundPenalty(uint256 _refundPenaltyNumerator,uint256 _refundPenaltyDenominator)", - "function numberOfKeysSold() constant view returns (uint256)", - "function updateTransferFee(uint256 _transferFeeNumerator,uint256 _transferFeeDenominator)", - "function isAlive() constant view returns (bool)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId) payable", - "function strConcat(string _a,string _b,string _c,string _d) constant pure returns (string _concatenatedString)", - "function keyOwnerToNonce(address) constant view returns (uint256)", - "function uint2Str(uint256 _i) constant pure returns (string _uintAsString)", - "function getCancelAndRefundValueFor(address _owner) constant view returns (uint256 refund)", - "function updateLockName(string _lockName)", - "function address2Str(address _addr) constant pure returns (string)", - "function incrementNonce()", - "function ownerOf(uint256 _tokenId) constant view returns (address)", - "function getHasValidKey(address _owner) constant view returns (bool)", - "function balanceOf(address _owner) constant view returns (uint256)", - "function purchaseForFrom(address _recipient,address _referrer) payable", - "function renounceOwnership()", - "function maxNumberOfKeys() constant view returns (uint256)", - "function updateLockSymbol(string _lockSymbol)", - "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps)", - "function getTransferFee(address _owner) constant view returns (uint256)", - "function getCancelAndRefundApprovalHash(address _keyOwner,address _txSender) constant view returns (bytes32 approvalHash)", - "function owner() constant view returns (address)", - "function isOwner() constant view returns (bool)", - "function transferFeeNumerator() constant view returns (uint256)", - "function numberOfOwners() constant view returns (uint256)", - "function symbol() constant view returns (string)", - "function getTokenIdFor(address _account) constant view returns (uint256)", - "function isKeyOwner(uint256 _tokenId,address _owner) constant view returns (bool)", - "function grantKey(address _recipient,uint256 _expirationTimestamp)", - "function tokenAddress() constant view returns (address)", - "function expireKeyFor(address _owner)", - "function setApprovalForAll(address _to,bool _approved)", - "function destroyLock()", - "function keyExpirationTimestampFor(address _owner) constant view returns (uint256 timestamp)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data) payable", - "function cancelAndRefundFor(address _keyOwner,bytes _signature)", - "function disableLock()", - "function initialize(address sender)", - "function tokenURI(uint256 _tokenId) constant view returns (string)", - "function transferFeeDenominator() constant view returns (uint256)", - "function isApprovedForAll(address _owner,address _operator) constant view returns (bool)", - "function transferOwnership(address newOwner)", - "function purchaseFor(address _recipient) payable", - "function getBalance(address _account) constant view returns (uint256)", - "function grantKeys(address[] _recipients,uint256 _expirationTimestamp)", - "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", - "event RefundPenaltyChanged (uint256 oldRefundPenaltyNumerator,uint256 oldRefundPenaltyDenominator,uint256 refundPenaltyNumerator,uint256 refundPenaltyDenominator)", - "event TransferFeeChanged (uint256 oldTransferFeeNumerator,uint256 oldTransferFeeDenominator,uint256 transferFeeNumerator,uint256 transferFeeDenominator)", - "event NewLockSymbol (string symbol)", - "event ExpireKey (uint256 tokenId)", - "event PriceChanged (uint256 oldKeyPrice,uint256 keyPrice)", - "event Withdrawal (address indexed sender,address indexed beneficiary,uint256 amount)", - "event Destroy (uint256 balance,address indexed owner)", - "event Disable ()", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event Transfer (address indexed _from,address indexed _to,uint256 indexed _tokenId)", - "event Approval (address indexed _owner,address indexed _approved,uint256 indexed _tokenId)", - "event ApprovalForAll (address indexed _owner,address indexed _operator,bool _approved)", - "function publicLockVersion() constant pure returns (uint16)" - ], - "bytecodeHash": "0x0d7ea1df12ab87024edd7add411416ee61a3f09cf41a0b6aa5499e1bc4277651" - }, - "v6": { - "contractName": "PublicLock", - "abi": [ - "event Approval (address indexed owner,address indexed approved,uint256 indexed tokenId)", - "event ApprovalForAll (address indexed owner,address indexed operator,bool approved)", - "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", - "event Destroy (uint256 balance,address indexed owner)", - "event Disable ()", - "event ExpireKey (uint256 indexed tokenId)", - "event LockManagerAdded (address indexed account)", - "event LockManagerRemoved (address indexed account)", - "event NewLockSymbol (string symbol)", - "event NonceChanged (address indexed keyOwner,uint256 nextAvailableNonce)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event PricingChanged (uint256 oldKeyPrice,uint256 keyPrice,address oldTokenAddress,address tokenAddress)", - "event RefundPenaltyChanged (uint256 freeTrialLength,uint256 refundPenaltyBasisPoints)", - "event TimestampChanged (uint256 indexed _tokenId,uint256 _amount,bool _timeAdded)", - "event Transfer (address indexed from,address indexed to,uint256 indexed tokenId)", - "event TransferFeeChanged (uint256 transferFeeBasisPoints)", - "event Withdrawal (address indexed sender,address indexed tokenAddress,address indexed beneficiary,uint256 amount)", - "function BASIS_POINTS_DEN() constant view returns (uint256)", - "function CANCEL_TYPEHASH() constant view returns (bytes32)", - "function addLockManager(address account)", - "function approve(address _approved,uint256 _tokenId)", - "function balanceOf(address _owner) constant view returns (uint256)", - "function beneficiary() constant view returns (address)", - "function cancelAndRefund()", - "function cancelAndRefundFor(address _keyOwner,uint8 _v,bytes32 _r,bytes32 _s)", - "function destroyLock()", - "function disableLock()", - "function erc1820() constant view returns (address)", - "function expirationDuration() constant view returns (uint256)", - "function expireKeyFor(address _owner)", - "function freeTrialLength() constant view returns (uint256)", - "function fullRefund(address _keyOwner,uint256 amount)", - "function getApproved(uint256 _tokenId) constant view returns (address)", - "function getBalance(address _tokenAddress,address _account) constant view returns (uint256)", - "function getCancelAndRefundApprovalHash(address _keyOwner,address _txSender) constant view returns (bytes32 approvalHash)", - "function getCancelAndRefundValueFor(address _owner) constant view returns (uint256 refund)", - "function getHasValidKey(address _owner) constant view returns (bool)", - "function getOwnersByPage(uint256 _page,uint256 _pageSize) constant view returns (address[])", - "function getTokenIdFor(address _account) constant view returns (uint256)", - "function getTransferFee(address _owner,uint256 _time) constant view returns (uint256)", - "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps)", - "function invalidateOffchainApproval(uint256 _nextAvailableNonce)", - "function isAlive() constant view returns (bool)", - "function isApprovedForAll(address _owner,address _operator) constant view returns (bool)", - "function isKeyOwner(uint256 _tokenId,address _owner) constant view returns (bool)", - "function isLockManager(address account) constant view returns (bool)", - "function isOwner() constant view returns (bool)", - "function keyCancelInterfaceId() constant view returns (bytes32)", - "function keyExpirationTimestampFor(address _owner) constant view returns (uint256 timestamp)", - "function keyOwnerToNonce(address) constant view returns (uint256)", - "function keyPrice() constant view returns (uint256)", - "function keySoldInterfaceId() constant view returns (bytes32)", - "function maxNumberOfKeys() constant view returns (uint256)", - "function name() constant view returns (string)", - "function numberOfOwners() constant view returns (uint256)", - "function owner() constant view returns (address)", - "function ownerOf(uint256 _tokenId) constant view returns (address)", - "function owners(uint256) constant view returns (address)", - "function publicLockVersion() constant pure returns (uint256)", - "function purchase(uint256 _value,address _recipient,address _referrer,bytes _data) payable", - "function refundPenaltyBasisPoints() constant view returns (uint256)", - "function renounceLockManager()", - "function renounceOwnership()", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data)", - "function setApprovalForAll(address _to,bool _approved)", - "function setBaseTokenURI(string _baseTokenURI)", - "function shareKey(address _to,uint256 _tokenId,uint256 _timeShared)", - "function supportsInterface(bytes4 interfaceId) constant view returns (bool)", - "function symbol() constant view returns (string)", - "function tokenAddress() constant view returns (address)", - "function tokenByIndex(uint256 _index) constant view returns (uint256)", - "function tokenOfOwnerByIndex(address _owner,uint256 _index) constant view returns (uint256)", - "function tokenURI(uint256 _tokenId) constant view returns (string)", - "function totalSupply() constant view returns (uint256)", - "function transferFeeBasisPoints() constant view returns (uint256)", - "function transferFrom(address _from,address _recipient,uint256 _tokenId)", - "function transferOwnership(address newOwner)", - "function unlockProtocol() constant view returns (address)", - "function updateBeneficiary(address _beneficiary)", - "function updateKeyPricing(uint256 _keyPrice,address _tokenAddress)", - "function updateLockName(string _lockName)", - "function updateLockSymbol(string _lockSymbol)", - "function updateRefundPenalty(uint256 _freeTrialLength,uint256 _refundPenaltyBasisPoints)", - "function updateTransferFee(uint256 _transferFeeBasisPoints)", - "function withdraw(address _tokenAddress,uint256 _amount)", - "function initialize(address _owner,uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", - "function initialize()", - "function initialize(address sender)" - ], - "bytecodeHash": "0x39260d0911736892b9a71a2c6b5fc69a98c58d297f8c4ca0bd7ee96c54244c69" - }, - "v7": { - "contractName": "PublicLock", - "abi": [ - "event Approval (address indexed owner,address indexed approved,uint256 indexed tokenId)", - "event ApprovalForAll (address indexed owner,address indexed operator,bool approved)", - "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", - "event Disable ()", - "event ExpirationChanged (uint256 indexed _tokenId,uint256 _amount,bool _timeAdded)", - "event ExpireKey (uint256 indexed tokenId)", - "event KeyGranterAdded (address indexed account)", - "event KeyGranterRemoved (address indexed account)", - "event KeyManagerChanged (uint256 indexed _tokenId,address indexed _newManager)", - "event LockManagerAdded (address indexed account)", - "event LockManagerRemoved (address indexed account)", - "event NewLockSymbol (string symbol)", - "event NonceChanged (address indexed keyManager,uint256 nextAvailableNonce)", - "event PricingChanged (uint256 oldKeyPrice,uint256 keyPrice,address oldTokenAddress,address tokenAddress)", - "event RefundPenaltyChanged (uint256 freeTrialLength,uint256 refundPenaltyBasisPoints)", - "event RenewKeyPurchase (address indexed owner,uint256 newExpiration)", - "event Transfer (address indexed from,address indexed to,uint256 indexed tokenId)", - "event TransferFeeChanged (uint256 transferFeeBasisPoints)", - "event Withdrawal (address indexed sender,address indexed tokenAddress,address indexed beneficiary,uint256 amount)", - "function addKeyGranter(address account)", - "function addLockManager(address account)", - "function approve(address _approved,uint256 _tokenId)", - "function balanceOf(address _keyOwner) constant view returns (uint256)", - "function beneficiary() constant view returns (address)", - "function cancelAndRefund(uint256 _tokenId)", - "function cancelAndRefundFor(address _keyManager,uint8 _v,bytes32 _r,bytes32 _s,uint256 _tokenId)", - "function disableLock()", - "function expirationDuration() constant view returns (uint256)", - "function expireAndRefundFor(address _keyOwner,uint256 amount)", - "function freeTrialLength() constant view returns (uint256)", - "function getApproved(uint256 _tokenId) constant view returns (address)", - "function getBalance(address _tokenAddress,address _account) constant view returns (uint256)", - "function getCancelAndRefundApprovalHash(address _keyManager,address _txSender) constant view returns (bytes32 approvalHash)", - "function getCancelAndRefundValueFor(address _keyOwner) constant view returns (uint256 refund)", - "function getHasValidKey(address _keyOwner) constant view returns (bool)", - "function getOwnersByPage(uint256 _page,uint256 _pageSize) constant view returns (address[])", - "function getTokenIdFor(address _account) constant view returns (uint256)", - "function getTransferFee(address _keyOwner,uint256 _time) constant view returns (uint256)", - "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps,address[] _keyManagers)", - "function invalidateOffchainApproval(uint256 _nextAvailableNonce)", - "function isAlive() constant view returns (bool)", - "function isApprovedForAll(address _owner,address _operator) constant view returns (bool)", - "function isKeyGranter(address account) constant view returns (bool)", - "function isKeyOwner(uint256 _tokenId,address _keyOwner) constant view returns (bool)", - "function isLockManager(address account) constant view returns (bool)", - "function keyExpirationTimestampFor(address _keyOwner) constant view returns (uint256)", - "function keyManagerOf(uint256) constant view returns (address)", - "function keyManagerToNonce(address) constant view returns (uint256)", - "function keyPrice() constant view returns (uint256)", - "function maxNumberOfKeys() constant view returns (uint256)", - "function name() constant view returns (string)", - "function numberOfOwners() constant view returns (uint256)", - "function onKeyCancelHook() constant view returns (address)", - "function onKeyPurchaseHook() constant view returns (address)", - "function ownerOf(uint256 _tokenId) constant view returns (address)", - "function owners(uint256) constant view returns (address)", - "function publicLockVersion() constant pure returns (uint256)", - "function purchase(uint256 _value,address _recipient,address _referrer,bytes _data) payable", - "function purchasePriceFor(address _recipient,address _referrer,bytes _data) constant view returns (uint256 minKeyPrice)", - "function refundPenaltyBasisPoints() constant view returns (uint256)", - "function renounceLockManager()", - "function revokeKeyGranter(address _granter)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data)", - "function setApprovalForAll(address _to,bool _approved)", - "function setBaseTokenURI(string _baseTokenURI)", - "function setEventHooks(address _onKeyPurchaseHook,address _onKeyCancelHook)", - "function setKeyManagerOf(uint256 _tokenId,address _keyManager)", - "function shareKey(address _to,uint256 _tokenId,uint256 _timeShared)", - "function supportsInterface(bytes4 interfaceId) constant view returns (bool)", - "function symbol() constant view returns (string)", - "function tokenAddress() constant view returns (address)", - "function tokenByIndex(uint256 _index) constant view returns (uint256)", - "function tokenOfOwnerByIndex(address _keyOwner,uint256 _index) constant view returns (uint256)", - "function tokenURI(uint256 _tokenId) constant view returns (string)", - "function totalSupply() constant view returns (uint256)", - "function transferFeeBasisPoints() constant view returns (uint256)", - "function transferFrom(address _from,address _recipient,uint256 _tokenId)", - "function unlockProtocol() constant view returns (address)", - "function updateBeneficiary(address _beneficiary)", - "function updateKeyPricing(uint256 _keyPrice,address _tokenAddress)", - "function updateLockName(string _lockName)", - "function updateLockSymbol(string _lockSymbol)", - "function updateRefundPenalty(uint256 _freeTrialLength,uint256 _refundPenaltyBasisPoints)", - "function updateTransferFee(uint256 _transferFeeBasisPoints)", - "function withdraw(address _tokenAddress,uint256 _amount)", - "function initialize(address _lockCreator,uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", - "function initialize()" - ], - "bytecodeHash": "0xd66a672853995b93eff7fc1ea6eb09bac55fb58da34a8132703844b6b0837c32" - }, - "v8": { - "contractName": "PublicLock", - "abi": [ - "event Approval (address indexed owner,address indexed approved,uint256 indexed tokenId)", - "event ApprovalForAll (address indexed owner,address indexed operator,bool approved)", - "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", - "event Disable ()", - "event ExpirationChanged (uint256 indexed _tokenId,uint256 _amount,bool _timeAdded)", - "event ExpireKey (uint256 indexed tokenId)", - "event KeyGranterAdded (address indexed account)", - "event KeyGranterRemoved (address indexed account)", - "event KeyManagerChanged (uint256 indexed _tokenId,address indexed _newManager)", - "event LockManagerAdded (address indexed account)", - "event LockManagerRemoved (address indexed account)", - "event NewLockSymbol (string symbol)", - "event NonceChanged (address indexed keyManager,uint256 nextAvailableNonce)", - "event PricingChanged (uint256 oldKeyPrice,uint256 keyPrice,address oldTokenAddress,address tokenAddress)", - "event RefundPenaltyChanged (uint256 freeTrialLength,uint256 refundPenaltyBasisPoints)", - "event RenewKeyPurchase (address indexed owner,uint256 newExpiration)", - "event Transfer (address indexed from,address indexed to,uint256 indexed tokenId)", - "event TransferFeeChanged (uint256 transferFeeBasisPoints)", - "event Withdrawal (address indexed sender,address indexed tokenAddress,address indexed beneficiary,uint256 amount)", - "function addKeyGranter(address account)", - "function addLockManager(address account)", - "function approve(address _approved,uint256 _tokenId)", - "function approveBeneficiary(address _spender,uint256 _amount) returns (bool)", - "function balanceOf(address _keyOwner) constant view returns (uint256)", - "function beneficiary() constant view returns (address)", - "function cancelAndRefund(uint256 _tokenId)", - "function cancelAndRefundFor(address _keyManager,uint8 _v,bytes32 _r,bytes32 _s,uint256 _tokenId)", - "function disableLock()", - "function expirationDuration() constant view returns (uint256)", - "function expireAndRefundFor(address _keyOwner,uint256 amount)", - "function freeTrialLength() constant view returns (uint256)", - "function getApproved(uint256 _tokenId) constant view returns (address)", - "function getBalance(address _tokenAddress,address _account) constant view returns (uint256)", - "function getCancelAndRefundApprovalHash(address _keyManager,address _txSender) constant view returns (bytes32 approvalHash)", - "function getCancelAndRefundValueFor(address _keyOwner) constant view returns (uint256 refund)", - "function getHasValidKey(address _keyOwner) constant view returns (bool)", - "function getOwnersByPage(uint256 _page,uint256 _pageSize) constant view returns (address[])", - "function getTokenIdFor(address _account) constant view returns (uint256)", - "function getTransferFee(address _keyOwner,uint256 _time) constant view returns (uint256)", - "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps,address[] _keyManagers)", - "function invalidateOffchainApproval(uint256 _nextAvailableNonce)", - "function isAlive() constant view returns (bool)", - "function isApprovedForAll(address _owner,address _operator) constant view returns (bool)", - "function isKeyGranter(address account) constant view returns (bool)", - "function isKeyOwner(uint256 _tokenId,address _keyOwner) constant view returns (bool)", - "function isLockManager(address account) constant view returns (bool)", - "function keyExpirationTimestampFor(address _keyOwner) constant view returns (uint256)", - "function keyManagerOf(uint256) constant view returns (address)", - "function keyManagerToNonce(address) constant view returns (uint256)", - "function keyPrice() constant view returns (uint256)", - "function maxNumberOfKeys() constant view returns (uint256)", - "function name() constant view returns (string)", - "function numberOfOwners() constant view returns (uint256)", - "function onKeyCancelHook() constant view returns (address)", - "function onKeyPurchaseHook() constant view returns (address)", - "function ownerOf(uint256 _tokenId) constant view returns (address)", - "function owners(uint256) constant view returns (address)", - "function publicLockVersion() constant pure returns (uint256)", - "function purchase(uint256 _value,address _recipient,address _referrer,bytes _data) payable", - "function purchasePriceFor(address _recipient,address _referrer,bytes _data) constant view returns (uint256 minKeyPrice)", - "function refundPenaltyBasisPoints() constant view returns (uint256)", - "function renounceLockManager()", - "function revokeKeyGranter(address _granter)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data)", - "function setApprovalForAll(address _to,bool _approved)", - "function setBaseTokenURI(string _baseTokenURI)", - "function setEventHooks(address _onKeyPurchaseHook,address _onKeyCancelHook)", - "function setKeyManagerOf(uint256 _tokenId,address _keyManager)", - "function shareKey(address _to,uint256 _tokenId,uint256 _timeShared)", - "function supportsInterface(bytes4 interfaceId) constant view returns (bool)", - "function symbol() constant view returns (string)", - "function tokenAddress() constant view returns (address)", - "function tokenByIndex(uint256 _index) constant view returns (uint256)", - "function tokenOfOwnerByIndex(address _keyOwner,uint256 _index) constant view returns (uint256)", - "function tokenURI(uint256 _tokenId) constant view returns (string)", - "function totalSupply() constant view returns (uint256)", - "function transfer(address _to,uint256 _value) returns (bool success)", - "function transferFeeBasisPoints() constant view returns (uint256)", - "function transferFrom(address _from,address _recipient,uint256 _tokenId)", - "function unlockProtocol() constant view returns (address)", - "function updateBeneficiary(address _beneficiary)", - "function updateKeyPricing(uint256 _keyPrice,address _tokenAddress)", - "function updateLockName(string _lockName)", - "function updateLockSymbol(string _lockSymbol)", - "function updateRefundPenalty(uint256 _freeTrialLength,uint256 _refundPenaltyBasisPoints)", - "function updateTransferFee(uint256 _transferFeeBasisPoints)", - "function withdraw(address _tokenAddress,uint256 _amount)", - "function initialize(address _lockCreator,uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", - "function initialize()" - ], - "bytecodeHash": "0x04782fb9f4650646c8db40744d69e4bf68845d1e7164884afb6ba95eb04e1a41" - }, "v9": { "contractName": "PublicLock", "abi": [ @@ -1211,134 +840,6 @@ const abis = { } }, "Unlock": { - "v4": { - "contractName": "Unlock", - "abi": [ - "function locks(address) constant view returns (bool deployed,uint256 totalSales,uint256 yieldedDiscountTokens)", - "function renounceOwnership()", - "function owner() constant view returns (address)", - "function isOwner() constant view returns (bool)", - "function totalDiscountGranted() constant view returns (uint256)", - "function grossNetworkProduct() constant view returns (uint256)", - "function transferOwnership(address newOwner)", - "event NewLock (address indexed lockOwner,address indexed newLockAddress)", - "event NewTokenURI (string tokenURI)", - "event NewGlobalTokenSymbol (string tokenSymbol)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "function initialize(address _owner)", - "function createLock(uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", - "function computeAvailableDiscountFor(address _purchaser,uint256 _keyPrice) constant view returns (uint256 discount,uint256 tokens)", - "function recordKeyPurchase(uint256 _value,address _referrer)", - "function recordConsumedDiscount(uint256 _discount,uint256 _tokens)", - "function unlockVersion() constant pure returns (uint16)", - "function getGlobalBaseTokenURI() constant view returns (string)", - "function setGlobalBaseTokenURI(string _URI)", - "function getGlobalTokenSymbol() constant view returns (string)", - "function setGlobalTokenSymbol(string _symbol)" - ], - "bytecodeHash": "0xa1e7ddfa6d9183443aca067a96bd252f3ffa72a55ce36564ab77e79ce6527ac3" - }, - "v6": { - "contractName": "Unlock", - "abi": [ - "event ConfigUnlock (address publicLockAddress,string globalTokenSymbol,string globalTokenURI)", - "event NewLock (address indexed lockOwner,address indexed newLockAddress)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event ResetTrackedValue (uint256 grossNetworkProduct,uint256 totalDiscountGranted)", - "function globalBaseTokenURI() constant view returns (string)", - "function globalTokenSymbol() constant view returns (string)", - "function grossNetworkProduct() constant view returns (uint256)", - "function isOwner() constant view returns (bool)", - "function locks(address) constant view returns (bool deployed,uint256 totalSales,uint256 yieldedDiscountTokens)", - "function owner() constant view returns (address)", - "function publicLockAddress() constant view returns (address)", - "function renounceOwnership()", - "function totalDiscountGranted() constant view returns (uint256)", - "function transferOwnership(address newOwner)", - "function uniswapExchanges(address) constant view returns (address)", - "function initialize(address _owner)", - "function createLock(uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName,bytes12 _salt)", - "function computeAvailableDiscountFor(address _purchaser,uint256 _keyPrice) constant view returns (uint256 discount,uint256 tokens)", - "function recordKeyPurchase(uint256 _value,address _referrer)", - "function recordConsumedDiscount(uint256 _discount,uint256 _tokens)", - "function unlockVersion() constant pure returns (uint16)", - "function configUnlock(address _publicLockAddress,string _symbol,string _URI)", - "function setExchange(address _tokenAddress,address _exchangeAddress)", - "function resetTrackedValue(uint256 _grossNetworkProduct,uint256 _totalDiscountGranted)" - ], - "bytecodeHash": "0x7b0e23742d9e4cbda29162687b753336c14d9afa6372385323f3a32a1365f535" - }, - "v7": { - "contractName": "Unlock", - "abi": [ - "event ConfigUnlock (string globalTokenSymbol,string globalTokenURI)", - "event NewLock (address indexed lockOwner,address indexed newLockAddress)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event ResetTrackedValue (uint256 grossNetworkProduct,uint256 totalDiscountGranted)", - "event SetLockTemplate (address publicLockAddress)", - "function globalBaseTokenURI() constant view returns (string)", - "function globalTokenSymbol() constant view returns (string)", - "function grossNetworkProduct() constant view returns (uint256)", - "function isOwner() constant view returns (bool)", - "function locks(address) constant view returns (bool deployed,uint256 totalSales,uint256 yieldedDiscountTokens)", - "function owner() constant view returns (address)", - "function publicLockAddress() constant view returns (address)", - "function renounceOwnership()", - "function totalDiscountGranted() constant view returns (uint256)", - "function transferOwnership(address newOwner)", - "function uniswapExchanges(address) constant view returns (address)", - "function initialize(address _unlockOwner)", - "function createLock(uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName,bytes12 _salt)", - "function computeAvailableDiscountFor(address,uint256) constant view returns (uint256 discount,uint256 tokens)", - "function recordKeyPurchase(uint256 _value,address)", - "function recordConsumedDiscount(uint256 _discount,uint256)", - "function unlockVersion() constant pure returns (uint16)", - "function configUnlock(string _symbol,string _URI)", - "function setLockTemplate(address _publicLockAddress)", - "function setExchange(address _tokenAddress,address _exchangeAddress)", - "function resetTrackedValue(uint256 _grossNetworkProduct,uint256 _totalDiscountGranted)", - "function getGlobalBaseTokenURI() constant view returns (string)", - "function getGlobalTokenSymbol() constant view returns (string)" - ], - "bytecodeHash": "0x2f4767420e3b4affa1e3169450a565061cab422cdf7cd582179eb33b0480da0b" - }, - "v8": { - "contractName": "Unlock", - "abi": [ - "event ConfigUnlock (address udt,address weth,uint256 estimatedGasForPurchase,string globalTokenSymbol,string globalTokenURI)", - "event NewLock (address indexed lockOwner,address indexed newLockAddress)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event ResetTrackedValue (uint256 grossNetworkProduct,uint256 totalDiscountGranted)", - "event SetLockTemplate (address publicLockAddress)", - "function estimatedGasForPurchase() constant view returns (uint256)", - "function globalBaseTokenURI() constant view returns (string)", - "function globalTokenSymbol() constant view returns (string)", - "function grossNetworkProduct() constant view returns (uint256)", - "function isOwner() constant view returns (bool)", - "function locks(address) constant view returns (bool deployed,uint256 totalSales,uint256 yieldedDiscountTokens)", - "function owner() constant view returns (address)", - "function publicLockAddress() constant view returns (address)", - "function renounceOwnership()", - "function totalDiscountGranted() constant view returns (uint256)", - "function transferOwnership(address newOwner)", - "function udt() constant view returns (address)", - "function uniswapOracles(address) constant view returns (address)", - "function weth() constant view returns (address)", - "function initialize(address _unlockOwner)", - "function createLock(uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName,bytes12 _salt)", - "function computeAvailableDiscountFor(address,uint256) constant view returns (uint256 discount,uint256 tokens)", - "function recordKeyPurchase(uint256 _value,address _referrer)", - "function recordConsumedDiscount(uint256 _discount,uint256)", - "function unlockVersion() constant pure returns (uint16)", - "function configUnlock(address _udt,address _weth,uint256 _estimatedGasForPurchase,string _symbol,string _URI)", - "function setLockTemplate(address _publicLockAddress)", - "function setOracle(address _tokenAddress,address _oracleAddress)", - "function resetTrackedValue(uint256 _grossNetworkProduct,uint256 _totalDiscountGranted)", - "function getGlobalBaseTokenURI() constant view returns (string)", - "function getGlobalTokenSymbol() constant view returns (string)" - ], - "bytecodeHash": "0xa757523ba876af736fe51084850937c0750049a724990558f1753fe9d0b0ec5e" - }, "v9": { "contractName": "Unlock", "abi": [ From 898d41df1efd9fa07bc5fb8d4ac5e9eb9414b868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 14 Jun 2024 15:32:15 +0200 Subject: [PATCH 02/27] remove from contracts --- packages/contracts/hardhat.config.js | 9 - .../src/abis/PublicLock/PublicLockV0.json | 674 ----- .../src/abis/PublicLock/PublicLockV1.json | 1139 -------- .../src/abis/PublicLock/PublicLockV2.json | 1158 -------- .../src/abis/PublicLock/PublicLockV3.json | 1378 ---------- .../src/abis/PublicLock/PublicLockV4.json | 1421 ---------- .../src/abis/PublicLock/PublicLockV5.json | 1574 ----------- .../src/abis/PublicLock/PublicLockV6.json | 1687 ------------ .../src/abis/PublicLock/PublicLockV7.json | 1739 ------------ .../src/abis/PublicLock/PublicLockV8.json | 1791 ------------- .../contracts/src/abis/Unlock/UnlockV0.json | 269 -- .../contracts/src/abis/Unlock/UnlockV1.json | 266 -- .../contracts/src/abis/Unlock/UnlockV2.json | 280 -- .../contracts/src/abis/Unlock/UnlockV3.json | 359 --- .../contracts/src/abis/Unlock/UnlockV4.json | 359 --- .../contracts/src/abis/Unlock/UnlockV5.json | 482 ---- .../contracts/src/abis/Unlock/UnlockV6.json | 482 ---- .../contracts/src/abis/Unlock/UnlockV7.json | 529 ---- .../contracts/src/abis/Unlock/UnlockV8.json | 607 ----- .../contracts/PublicLock/IPublicLockV4.sol | 490 ---- .../contracts/PublicLock/IPublicLockV5.sol | 579 ---- .../contracts/PublicLock/IPublicLockV6.sol | 593 ---- .../contracts/PublicLock/IPublicLockV7.sol | 467 ---- .../PublicLock/IPublicLockV7Sol6.sol | 469 ---- .../contracts/PublicLock/IPublicLockV8.sol | 485 ---- .../PublicLock/IPublicLockV8Sol6.sol | 487 ---- .../PublicLock/IPublicLockV8sol8.sol | 439 --- .../src/contracts/Unlock/IUnlockV5.sol | 93 - .../src/contracts/Unlock/IUnlockV6.sol | 93 - .../src/contracts/Unlock/IUnlockV7.sol | 147 - .../src/contracts/Unlock/IUnlockV8.sol | 162 -- .../src/contracts/Unlock/UnlockV0.sol | 1255 --------- .../src/contracts/Unlock/UnlockV1.sol | 1957 -------------- .../src/contracts/Unlock/UnlockV2.sol | 2 - .../src/contracts/Unlock/UnlockV3.sol | 2232 --------------- .../src/contracts/Unlock/UnlockV4.sol | 2387 ----------------- .../src/contracts/Unlock/UnlockV5.sol | 2 - .../src/contracts/Unlock/UnlockV6.sol | 1212 --------- .../src/contracts/Unlock/UnlockV7.sol | 1438 ---------- .../src/contracts/Unlock/UnlockV8.sol | 1540 ----------- 40 files changed, 32732 deletions(-) delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV0.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV1.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV2.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV3.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV4.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV5.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV6.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV7.json delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV8.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV0.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV1.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV2.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV3.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV4.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV5.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV6.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV7.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV8.json delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV4.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV5.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV6.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV7.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV7Sol6.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV8.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV8Sol6.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV8sol8.sol delete mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV5.sol delete mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV6.sol delete mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV7.sol delete mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV8.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV0.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV1.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV2.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV3.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV4.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV5.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV6.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV7.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV8.sol diff --git a/packages/contracts/hardhat.config.js b/packages/contracts/hardhat.config.js index 8c5fd77d61e..899589058fc 100644 --- a/packages/contracts/hardhat.config.js +++ b/packages/contracts/hardhat.config.js @@ -33,15 +33,6 @@ const settings = { module.exports = { solidity: { compilers: [ - { version: '0.4.24', settings }, - { version: '0.4.25', settings }, - { version: '0.5.0', settings }, - { version: '0.5.12', settings }, - { version: '0.5.17', settings }, - { version: '0.5.14', settings }, - { version: '0.5.7', settings }, - { version: '0.5.9', settings }, - { version: '0.6.12', settings }, { version: '0.7.6', settings }, { version: '0.8.0', settings }, { version: '0.8.2', settings }, diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV0.json b/packages/contracts/src/abis/PublicLock/PublicLockV0.json deleted file mode 100644 index d28180ae018..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV0.json +++ /dev/null @@ -1,674 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfKeysSold", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_sender", - "type": "address" - }, - { - "indexed": false, - "name": "_amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - } - ], - "name": "OwnershipRenounced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "purchaseFor", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_referrer", - "type": "address" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "purchaseForFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_amount", - "type": "uint256" - } - ], - "name": "partialWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_approved", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "outstandingKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_page", - "type": "uint256" - }, - { - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyDataFor", - "outputs": [ - { - "name": "data", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "operator", - "type": "address" - }, - { - "name": "from", - "type": "address" - }, - { - "name": "tokenId", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x60806040523480156200001157600080fd5b5060405160808062002143833981016040908152815160208301519183015160609093015190929063bbf81e00831115620000d357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45787069726174696f6e206475726174696f6e2065786365656473203130302060448201527f7965617273000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60998054600160a060020a03191633179055620000fe84640100000000620013426200012982021704565b62000116640100000000620010626200023082021704565b609a92909255609b55609c5550620003ca565b60008054610100900460ff16806200014f57506200014f64010000000062000357810204565b806200015e575060005460ff16155b1515620001e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201526000805160206200212383398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b60008054610100900460ff16806200025657506200025664010000000062000357810204565b8062000265575060005460ff16155b1515620002e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201526000805160206200212383398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166200033d7f01ffc9a7000000000000000000000000000000000000000000000000000000006401000000006200035d810204565b600080549115156101000261ff0019909216919091179055565b303b1590565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200038d57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152603360205260409020805460ff19166001179055565b611d4980620003da6000396000f3006080604052600436106101715763ffffffff60e060020a60003504166301ffc9a78114610176578063025e7c27146101ac578063081812fc146101e0578063095ea7b3146101f85780630f15023b1461021157806310803b721461022657806310e569731461029157806311a4c03a146102b8578063150b7a02146102cd5780631f1ec0291461035957806323b872dd146103715780633ba70e311461038e5780633ccfd60b146103a357806347dc1085146103b857806353b704d0146103cd5780636352211e146103ed57806370a0823114610405578063715018a61461042657806371d2ee6c1461043b57806374b6c106146104535780638129fc1c146104685780638da5cb5b1461047d5780638f32d59b1461049257806393fd1844146104a7578063970aaeb7146104bc5780639f98d3cb146104dd578063abdf82ce146104fe578063c4d66de81461051f578063d44fa14a14610540578063d8125eb3146105d6578063f2fde38b146105fe575b600080fd5b34801561018257600080fd5b50610198600160e060020a03196004351661061f565b604080519115158252519081900360200190f35b3480156101b857600080fd5b506101c460043561063e565b60408051600160a060020a039092168252519081900360200190f35b3480156101ec57600080fd5b506101c4600435610666565b61020f600160a060020a0360043516602435610677565b005b34801561021d57600080fd5b506101c461077a565b34801561023257600080fd5b50610241600435602435610789565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561027d578181015183820152602001610265565b505050509050019250505060405180910390f35b34801561029d57600080fd5b506102a6610925565b60408051918252519081900360200190f35b3480156102c457600080fd5b506102a661092b565b3480156102d957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261033c94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506109319650505050505050565b60408051600160e060020a03199092168252519081900360200190f35b34801561036557600080fd5b5061020f60043561095a565b61020f600160a060020a03600435811690602435166044356109b7565b34801561039a57600080fd5b506102a6610d1b565b3480156103af57600080fd5b5061020f610d21565b3480156103c457600080fd5b506102a6610d9d565b61020f60048035600160a060020a03169060248035908101910135610da4565b3480156103f957600080fd5b506101c4600435610de5565b34801561041157600080fd5b506102a6600160a060020a0360043516610e60565b34801561043257600080fd5b5061020f610ef6565b34801561044757600080fd5b5061020f600435610f53565b34801561045f57600080fd5b506102a661105c565b34801561047457600080fd5b5061020f611062565b34801561048957600080fd5b506101c461116a565b34801561049e57600080fd5b50610198611179565b3480156104b357600080fd5b506102a661118a565b3480156104c857600080fd5b506102a6600160a060020a0360043516611190565b3480156104e957600080fd5b5061020f600160a060020a0360043516611212565b34801561050a57600080fd5b506102a6600160a060020a03600435166112bd565b34801561052b57600080fd5b5061020f600160a060020a0360043516611342565b34801561054c57600080fd5b50610561600160a060020a0360043516611435565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561059b578181015183820152602001610583565b50505050905090810190601f1680156105c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020f600160a060020a0360048035821691602480359091169160443591820191013561154a565b34801561060a57600080fd5b5061020f600160a060020a0360043516611603565b600160e060020a03191660009081526033602052604090205460ff1690565b60a080548290811061064c57fe5b600091825260209091200154600160a060020a0316905081565b60006106718261161f565b92915050565b6000818152609f60205260409020548190600160a060020a0316331461069c57600080fd5b600160a060020a03831615156106b157600080fd5b33600160a060020a0384161415610712576040805160e560020a62461bcd02815260206004820152601a60248201527f596f752063616e277420617070726f766520796f757273656c66000000000000604482015290519081900360640190fd5b600082815260a1602090815260408083208054600160a060020a031916600160a060020a03888116918217909255609f909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b609954600160a060020a031681565b60606000806060600080600061079d610d9d565b116107f2576040805160e560020a62461bcd02815260206004820152601360248201527f4e6f206b65797320746f20726574726965766500000000000000000000000000604482015290519081900360640190fd5b86880294506000851015801561080e575061080b610d9d565b85105b1515610864576040805160e560020a62461bcd02815260206004820152601760248201527f496e646578206d75737420626520696e2d626f756e6473000000000000000000604482015290519081900360640190fd5b60a054858801111561087f5760a05485810397509350610885565b86850193505b866040519080825280602002602001820160405280156108af578160200160208202803883390190505b509250600091508490505b838110156109195760a08054829081106108d057fe5b6000918252602090912001548351600160a060020a03909116908490849081106108f657fe5b600160a060020a03909216602092830290910190910152600191820191016108ba565b50909695505050505050565b609b5481565b609a5481565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6000610964611179565b151561096f57600080fd5b50609b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b6000609d54609c54111515610a3c576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152609e6020526040902060018101548591904210610ab2576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b6000848152609f60205260409020548490600160a060020a0316331480610ae9575033610ade8261161f565b600160a060020a0316145b1515610b3f576040805160e560020a62461bcd02815260206004820181905260248201527f4f6e6c79206b6579206f776e6572206f7220617070726f766564206f776e6572604482015290519081900360640190fd5b600160a060020a0386161515610b5457600080fd5b600160a060020a0386166000908152609e60205260409020600101549350831515610be55760a08054600181019091557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038816600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b428411610c1a57600160a060020a038088166000908152609e6020526040808220600190810154938a16835291200155610c65565b600160a060020a0387166000908152609e6020526040902060010154610c489042860363ffffffff61168e16565b600160a060020a0387166000908152609e60205260409020600101555b600160a060020a038088166000908152609e60205260408082209289168252902060029182018054610cab93928301926000196101006001841615020190911604611bf4565b50600160a060020a038088166000818152609e602090815260408083204260019091015589835260a19091528082208054600160a060020a03191690555188938a1692917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b609d5481565b6000610d2b611179565b1515610d3657600080fd5b50303160008111610d91576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610d9a816116a7565b50565b609d545b90565b610de083600084848080601f01602080910402602001604051908101604052809392919081815260200183838082843750611721945050505050565b505050565b6000818152609f60205260408120548290600160a060020a03161515610e43576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611cfe833981519152604482015290519081900360640190fd5b50506000908152609f6020526040902054600160a060020a031690565b6000600160a060020a0382161515610ec2576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382166000908152609e602052604081206001015411610eea576000610eed565b60015b60ff1692915050565b610efe611179565b1515610f0957600080fd5b606654604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a260668054600160a060020a0319169055565b6000610f5d611179565b1515610f6857600080fd5b60008211610fe6576040805160e560020a62461bcd02815260206004820152602560248201527f4d757374207265717565737420616e20616d6f756e742067726561746572207460448201527f68616e2030000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b503031600081118015610ff95750818110155b151561104f576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b611058826116a7565b5050565b609c5481565b60008054610100900460ff168061107c575061107c611b3d565b8061108a575060005460ff16155b1515611106576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166111507f01ffc9a700000000000000000000000000000000000000000000000000000000611b47565b600080549115156101000261ff0019909216919091179055565b606654600160a060020a031690565b606654600160a060020a0316331490565b60a05490565b600160a060020a0381166000908152609e60205260408120600181015483919083106111f4576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611cfe833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090205490565b61121a611179565b151561122557600080fd5b600160a060020a0381166000908152609e602052604090206001810154829190421061129b576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b5050600160a060020a03166000908152609e6020526040902042600190910155565b600160a060020a0381166000908152609e6020526040812060018101548391908310611321576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611cfe833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090206001015490565b60008054610100900460ff168061135c575061135c611b3d565b8061136a575060005460ff16155b15156113e6576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381166000908152609e6020526040812060018101546060928492911161149b576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611cfe833981519152604482015290519081900360640190fd5b600160a060020a0384166000908152609e60209081526040918290206002908101805484516001821615610100026000190190911692909204601f81018490048402830184019094528382529092909183018282801561153c5780601f106115115761010080835404028352916020019161153c565b820191906000526020600020905b81548152906001019060200180831161151f57829003601f168201915b505050505092505050919050565b600160a060020a0383166000908152609e60205260409020600181015484919042106115c0576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b6115fb868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843750611721945050505050565b505050505050565b61160b611179565b151561161657600080fd5b610d9a81611b83565b600081815260a16020526040812054600160a060020a0316801515610671576040805160e560020a62461bcd02815260206004820152601c60248201527f4e6f20617070726f76656420726563697069656e742065786973747300000000604482015290519081900360640190fd5b6000828201838110156116a057600080fd5b9392505050565b6116af61116a565b600160a060020a03166108fc829081150290604051600060405180830381858888f193505050501580156116e7573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600080600080600080609d54609c541115156117ad576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a03891615156117c257600080fd5b609954609b54604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152602482018490528251941699509195508892630cb175e39260448082019392918290030181600087803b15801561183557600080fd5b505af1158015611849573d6000803e3d6000fd5b505050506040513d604081101561185f57600080fd5b5080516020909101519095509350829150818511156118815760009150611887565b84830391505b348211156118df576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50600160a060020a0388166000908152609e6020526040902060010154428110156119ab5780151561198157609d8054600190810190915560a0805491820190557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038b16600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b609a54600160a060020a038a166000908152609e60205260409020429091016001909101556119dc565b609a546119bf90829063ffffffff61168e16565b600160a060020a038a166000908152609e60205260409020600101555b600160a060020a0389166000908152609e602090815260409091208851611a0b926002909201918a0190611c75565b506000851115611a7f5785600160a060020a0316633652466386866040518363ffffffff1660e060020a0281526004018083815260200182815260200192505050600060405180830381600087803b158015611a6657600080fd5b505af1158015611a7a573d6000803e3d6000fd5b505050505b85600160a060020a031663939d9f1f838a6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050600060405180830381600087803b158015611ae257600080fd5b505af1158015611af6573d6000803e3d6000fd5b5050604051600160a060020a038c1692508291506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050505050505050565b303b8015905b5090565b600160e060020a03198082161415611b5e57600080fd5b600160e060020a0319166000908152603360205260409020805460ff19166001179055565b600160a060020a0381161515611b9857600080fd5b606654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360668054600160a060020a031916600160a060020a0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c2d5780548555611c69565b82800160010185558215611c6957600052602060002091601f016020900482015b82811115611c69578254825591600101919060010190611c4e565b50611b43929150611ce3565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611cb657805160ff1916838001178555611c69565b82800160010185558215611c69579182015b82811115611c69578251825591602001919060010190611cc8565b610da191905b80821115611b435760008155600101611ce956004e6f2073756368206b6579000000000000000000000000000000000000000000a165627a7a72305820f1dcbf1fdf6733d1b492dd9a701d5f38474921e8f9f08680f3f7af78a868a43d0029436f6e747261637420696e7374616e63652068617320616c7265616479206265", - "deployedBytecode": "0x6080604052600436106101715763ffffffff60e060020a60003504166301ffc9a78114610176578063025e7c27146101ac578063081812fc146101e0578063095ea7b3146101f85780630f15023b1461021157806310803b721461022657806310e569731461029157806311a4c03a146102b8578063150b7a02146102cd5780631f1ec0291461035957806323b872dd146103715780633ba70e311461038e5780633ccfd60b146103a357806347dc1085146103b857806353b704d0146103cd5780636352211e146103ed57806370a0823114610405578063715018a61461042657806371d2ee6c1461043b57806374b6c106146104535780638129fc1c146104685780638da5cb5b1461047d5780638f32d59b1461049257806393fd1844146104a7578063970aaeb7146104bc5780639f98d3cb146104dd578063abdf82ce146104fe578063c4d66de81461051f578063d44fa14a14610540578063d8125eb3146105d6578063f2fde38b146105fe575b600080fd5b34801561018257600080fd5b50610198600160e060020a03196004351661061f565b604080519115158252519081900360200190f35b3480156101b857600080fd5b506101c460043561063e565b60408051600160a060020a039092168252519081900360200190f35b3480156101ec57600080fd5b506101c4600435610666565b61020f600160a060020a0360043516602435610677565b005b34801561021d57600080fd5b506101c4610719565b34801561023257600080fd5b50610241600435602435610728565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561027d578181015183820152602001610265565b505050509050019250505060405180910390f35b34801561029d57600080fd5b506102a66108c4565b60408051918252519081900360200190f35b3480156102c457600080fd5b506102a66108ca565b3480156102d957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261033c94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506108d09650505050505050565b60408051600160e060020a03199092168252519081900360200190f35b34801561036557600080fd5b5061020f6004356108f9565b61020f600160a060020a0360043581169060243516604435610956565b34801561039a57600080fd5b506102a6610cba565b3480156103af57600080fd5b5061020f610cc0565b3480156103c457600080fd5b506102a6610d3c565b61020f60048035600160a060020a03169060248035908101910135610d43565b3480156103f957600080fd5b506101c4600435610d84565b34801561041157600080fd5b506102a6600160a060020a0360043516610dff565b34801561043257600080fd5b5061020f610e95565b34801561044757600080fd5b5061020f600435610ef2565b34801561045f57600080fd5b506102a6610f7d565b34801561047457600080fd5b5061020f610f83565b34801561048957600080fd5b506101c461108b565b34801561049e57600080fd5b5061019861109a565b3480156104b357600080fd5b506102a66110ab565b3480156104c857600080fd5b506102a6600160a060020a03600435166110b1565b3480156104e957600080fd5b5061020f600160a060020a0360043516611133565b34801561050a57600080fd5b506102a6600160a060020a03600435166111de565b34801561052b57600080fd5b5061020f600160a060020a0360043516611263565b34801561054c57600080fd5b50610561600160a060020a0360043516611356565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561059b578181015183820152602001610583565b50505050905090810190601f1680156105c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020f600160a060020a0360048035821691602480359091169160443591820191013561146b565b34801561060a57600080fd5b5061020f600160a060020a0360043516611524565b600160e060020a03191660009081526033602052604090205460ff1690565b60a080548290811061064c57fe5b600091825260209091200154600160a060020a0316905081565b600061067182611540565b92915050565b6000818152609f60205260409020548190600160a060020a0316331461069c57600080fd5b600160a060020a03831615156106b157600080fd5b600082815260a1602090815260408083208054600160a060020a031916600160a060020a03888116918217909255609f909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b609954600160a060020a031681565b60606000806060600080600061073c610d3c565b11610791576040805160e560020a62461bcd02815260206004820152601360248201527f4e6f206b65797320746f20726574726965766500000000000000000000000000604482015290519081900360640190fd5b8688029450600085101580156107ad57506107aa610d3c565b85105b1515610803576040805160e560020a62461bcd02815260206004820152601760248201527f496e646578206d75737420626520696e2d626f756e6473000000000000000000604482015290519081900360640190fd5b60a054858801111561081e5760a05485810397509350610824565b86850193505b8660405190808252806020026020018201604052801561084e578160200160208202803883390190505b509250600091508490505b838110156108b85760a080548290811061086f57fe5b6000918252602090912001548351600160a060020a039091169084908490811061089557fe5b600160a060020a0390921660209283029091019091015260019182019101610859565b50909695505050505050565b609b5481565b609a5481565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b600061090361109a565b151561090e57600080fd5b50609b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b6000609d54609c541115156109db576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152609e6020526040902060018101548591904210610a51576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b6000848152609f60205260409020548490600160a060020a0316331480610a88575033610a7d82611540565b600160a060020a0316145b1515610ade576040805160e560020a62461bcd02815260206004820181905260248201527f4f6e6c79206b6579206f776e6572206f7220617070726f766564206f776e6572604482015290519081900360640190fd5b600160a060020a0386161515610af357600080fd5b600160a060020a0386166000908152609e60205260409020600101549350831515610b845760a08054600181019091557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038816600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b428411610bb957600160a060020a038088166000908152609e6020526040808220600190810154938a16835291200155610c04565b600160a060020a0387166000908152609e6020526040902060010154610be79042860363ffffffff61156416565b600160a060020a0387166000908152609e60205260409020600101555b600160a060020a038088166000908152609e60205260408082209289168252902060029182018054610c4a93928301926000196101006001841615020190911604611aca565b50600160a060020a038088166000818152609e602090815260408083204260019091015589835260a19091528082208054600160a060020a03191690555188938a1692917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b609d5481565b6000610cca61109a565b1515610cd557600080fd5b50303160008111610d30576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610d398161157d565b50565b609d545b90565b610d7f83600084848080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050565b6000818152609f60205260408120548290600160a060020a03161515610de2576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b50506000908152609f6020526040902054600160a060020a031690565b6000600160a060020a0382161515610e61576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382166000908152609e602052604081206001015411610e89576000610e8c565b60015b60ff1692915050565b610e9d61109a565b1515610ea857600080fd5b606654604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a260668054600160a060020a0319169055565b6000610efc61109a565b1515610f0757600080fd5b503031600081118015610f1a5750818110155b1515610f70576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610f798261157d565b5050565b609c5481565b60008054610100900460ff1680610f9d5750610f9d611a13565b80610fab575060005460ff16155b1515611027576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166110717f01ffc9a700000000000000000000000000000000000000000000000000000000611a1d565b600080549115156101000261ff0019909216919091179055565b606654600160a060020a031690565b606654600160a060020a0316331490565b60a05490565b600160a060020a0381166000908152609e6020526040812060018101548391908310611115576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090205490565b61113b61109a565b151561114657600080fd5b600160a060020a0381166000908152609e60205260409020600181015482919042106111bc576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b5050600160a060020a03166000908152609e6020526040902042600190910155565b600160a060020a0381166000908152609e6020526040812060018101548391908310611242576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090206001015490565b60008054610100900460ff168061127d575061127d611a13565b8061128b575060005460ff16155b1515611307576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381166000908152609e602052604081206001810154606092849291116113bc576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b600160a060020a0384166000908152609e60209081526040918290206002908101805484516001821615610100026000190190911692909204601f81018490048402830184019094528382529092909183018282801561145d5780601f106114325761010080835404028352916020019161145d565b820191906000526020600020905b81548152906001019060200180831161144057829003601f168201915b505050505092505050919050565b600160a060020a0383166000908152609e60205260409020600181015484919042106114e1576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b61151c868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050505050565b61152c61109a565b151561153757600080fd5b610d3981611a59565b600081815260a16020526040812054600160a060020a031680151561067157600080fd5b60008282018381101561157657600080fd5b9392505050565b61158561108b565b600160a060020a03166108fc829081150290604051600060405180830381858888f193505050501580156115bd573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600080600080600080609d54609c54111515611683576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a038916151561169857600080fd5b609954609b54604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152602482018490528251941699509195508892630cb175e39260448082019392918290030181600087803b15801561170b57600080fd5b505af115801561171f573d6000803e3d6000fd5b505050506040513d604081101561173557600080fd5b508051602090910151909550935082915081851115611757576000915061175d565b84830391505b348211156117b5576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50600160a060020a0388166000908152609e6020526040902060010154428110156118815780151561185757609d8054600190810190915560a0805491820190557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038b16600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b609a54600160a060020a038a166000908152609e60205260409020429091016001909101556118b2565b609a5461189590829063ffffffff61156416565b600160a060020a038a166000908152609e60205260409020600101555b600160a060020a0389166000908152609e6020908152604090912088516118e1926002909201918a0190611b4b565b5060008511156119555785600160a060020a0316633652466386866040518363ffffffff1660e060020a0281526004018083815260200182815260200192505050600060405180830381600087803b15801561193c57600080fd5b505af1158015611950573d6000803e3d6000fd5b505050505b85600160a060020a031663939d9f1f838a6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b5050604051600160a060020a038c1692508291506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050505050505050565b303b8015905b5090565b600160e060020a03198082161415611a3457600080fd5b600160e060020a0319166000908152603360205260409020805460ff19166001179055565b600160a060020a0381161515611a6e57600080fd5b606654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360668054600160a060020a031916600160a060020a0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b035780548555611b3f565b82800160010185558215611b3f57600052602060002091601f016020900482015b82811115611b3f578254825591600101919060010190611b24565b50611a19929150611bb9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b8c57805160ff1916838001178555611b3f565b82800160010185558215611b3f579182015b82811115611b3f578251825591602001919060010190611b9e565b610d4091905b80821115611a195760008155600101611bbf56004e6f2073756368206b6579000000000000000000000000000000000000000000a165627a7a72305820be0f0296c7f54e6f6a0d497b8f41b62652244fa2177534a70d7837c6fb9fc5ca0029", - "compiler": { - "name": "solc", - "version": "0.4.25+commit.59dbf8f1.Emscripten.clang" - }, - "schemaVersion": "2.0.2", - "updatedAt": "2019-03-02T13:33:23.745Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV1.json b/packages/contracts/src/abis/PublicLock/PublicLockV1.json deleted file mode 100644 index f415fd05dde..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV1.json +++ /dev/null @@ -1,1139 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_approved", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_page", - "type": "uint256" - }, - { - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_refundPenaltyNumerator", - "type": "uint256" - }, - { - "name": "_refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfKeysSold", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_transferFeeNumerator", - "type": "uint256" - }, - { - "name": "_transferFeeDenominator", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "purchaseForFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_amount", - "type": "uint256" - } - ], - "name": "partialWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - } - ], - "name": "purchaseFor", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldTransferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldTransferFeeDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeDenominator", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldRefundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldRefundPenaltyDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_sender", - "type": "address" - }, - { - "indexed": false, - "name": "_amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - } - ], - "bytecode": "0x60806040526001607455600a607555600560765560646077553480156200002557600080fd5b5060405160a080620038c2833981018060405260a08110156200004757600080fd5b50805160208201516040830151606084015160809094015192939192909190838282600186620000a07f01ffc9a700000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b600160a060020a03811615806200013a5750600081600160a060020a03166318160ddd6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156200010a57600080fd5b505afa1580156200011f573d6000803e3d6000fd5b505050506040513d60208110156200013657600080fd5b5051115b620001a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460a060020a60ff0219600160a060020a03909316600160a060020a031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200025c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054600160a060020a03191633179055606993909355606a91909155606b55606d55620002b47f80ac58cd00000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b620002cd85640100000000620022846200034582021704565b505050505062000460565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200030857600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200036a57506200036a6401000000006200045a810204565b8062000379575060015460ff16155b620003d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003894602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff1916831790925560348054600160a060020a031916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b61342480620004706000396000f3fe608060405260043610610337576000357c01000000000000000000000000000000000000000000000000000000009004806370a08231116101c85780639d76ea5811610114578063c4d66de8116100b2578063e985e9c51161008c578063e985e9c514610ddb578063f2fde38b14610e16578063f6e4641f14610e49578063f8faf94214610e6f57610337565b8063c4d66de814610d7e578063d1bbd49c14610db1578063d42cfc4114610dc657610337565b8063a843a4e7116100ee578063a843a4e714610c5b578063abdf82ce14610c70578063b88d4fde14610ca3578063c1c98d0314610d6957610337565b80639d76ea5814610bd85780639f98d3cb14610bed578063a22cb46514610c2057610337565b80638da5cb5b1161018157806393fd18441161015b57806393fd184414610b1e578063970aaeb714610b33578063994a8a7114610b665780639b3f0b1714610b9f57610337565b80638da5cb5b14610adf5780638f32d59b14610af45780638f98ce8f14610b0957610337565b806370a082311461095b57806370efb7701461098e578063715018a6146109bc57806371d2ee6c146109d157806374b6c106146109fb5780637c7c425314610a1057610337565b80631f1ec029116102875780633d3359cb1161024057806352d6a8e41161021a57806352d6a8e41461084e578063550ef3a8146108815780636352211e146108fe5780636d8ea5b41461092857610337565b80633d3359cb146107d35780634136aa351461080357806342842e0e1461081857610337565b80631f1ec029146107045780632009dc651461072e57806323b872dd1461074357806339f46986146107795780633ba70e31146107a95780633ccfd60b146107be57610337565b80630ed3e2cc116102f457806310e56973116102ce57806310e56973146105d557806311a4c03a146105ea578063150b7a02146105ff57806318160ddd146106ef57610337565b80630ed3e2cc1461052b5780630f15023b1461054057806310803b721461055557610337565b806301ffc9a714610394578063025e7c27146103dc57806306fdde0314610422578063081812fc146104ac578063095ea7b3146104d65780630c79130f14610504575b34801561034357600080fd5b506040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b3480156103a057600080fd5b506103c8600480360360208110156103b757600080fd5b5035600160e060020a031916610eec565b604080519115158252519081900360200190f35b3480156103e857600080fd5b50610406600480360360208110156103ff57600080fd5b5035610f0f565b60408051600160a060020a039092168252519081900360200190f35b34801561042e57600080fd5b50610437610f36565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610471578181015183820152602001610459565b50505050905090810190601f16801561049e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104b857600080fd5b50610406600480360360208110156104cf57600080fd5b5035610fcd565b610502600480360360408110156104ec57600080fd5b50600160a060020a038135169060200135610fde565b005b34801561051057600080fd5b50610519611191565b60408051918252519081900360200190f35b34801561053757600080fd5b50610519611197565b34801561054c57600080fd5b5061040661119d565b34801561056157600080fd5b506105856004803603604081101561057857600080fd5b50803590602001356111ac565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105c15781810151838201526020016105a9565b505050509050019250505060405180910390f35b3480156105e157600080fd5b506105196112d1565b3480156105f657600080fd5b506105196112d7565b34801561060b57600080fd5b506106d26004803603608081101561062257600080fd5b600160a060020a0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561065d57600080fd5b82018360208201111561066f57600080fd5b8035906020019184600183028401116401000000008311171561069157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112dd945050505050565b60408051600160e060020a03199092168252519081900360200190f35b3480156106fb57600080fd5b50610519611307565b34801561071057600080fd5b506105026004803603602081101561072757600080fd5b503561130d565b34801561073a57600080fd5b506105026113b4565b6105026004803603606081101561075957600080fd5b50600160a060020a03813581169160208101359091169060400135611420565b34801561078557600080fd5b506105026004803603604081101561079c57600080fd5b508035906020013561164f565b3480156107b557600080fd5b5061051961170d565b3480156107ca57600080fd5b50610502611713565b3480156107df57600080fd5b50610502600480360360408110156107f657600080fd5b5080359060200135611795565b34801561080f57600080fd5b506103c8611853565b6105026004803603606081101561082e57600080fd5b50600160a060020a03813581169160208101359091169060400135611863565b34801561085a57600080fd5b506105196004803603602081101561087157600080fd5b5035600160a060020a0316611883565b34801561088d57600080fd5b50610502600480360360208110156108a457600080fd5b8101906020810181356401000000008111156108bf57600080fd5b8201836020820111156108d157600080fd5b803590602001918460018302840111640100000000831117156108f357600080fd5b50909250905061188e565b34801561090a57600080fd5b506104066004803603602081101561092157600080fd5b50356118ab565b34801561093457600080fd5b506103c86004803603602081101561094b57600080fd5b5035600160a060020a0316611936565b34801561096757600080fd5b506105196004803603602081101561097e57600080fd5b5035600160a060020a0316611956565b610502600480360360408110156109a457600080fd5b50600160a060020a03813581169160200135166119d7565b3480156109c857600080fd5b50610502611a7c565b3480156109dd57600080fd5b50610502600480360360208110156109f457600080fd5b5035611ae4565b348015610a0757600080fd5b50610519611bbb565b348015610a1c57600080fd5b5061050260048036036040811015610a3357600080fd5b810190602081018135640100000000811115610a4e57600080fd5b820183602082011115610a6057600080fd5b80359060200191846020830284011164010000000083111715610a8257600080fd5b919390929091602081019035640100000000811115610aa057600080fd5b820183602082011115610ab257600080fd5b80359060200191846020830284011164010000000083111715610ad457600080fd5b509092509050611bc1565b348015610aeb57600080fd5b50610406611c23565b348015610b0057600080fd5b506103c8611c32565b348015610b1557600080fd5b50610519611c43565b348015610b2a57600080fd5b50610519611c49565b348015610b3f57600080fd5b5061051960048036036020811015610b5657600080fd5b5035600160a060020a0316611c4f565b348015610b7257600080fd5b506103c860048036036040811015610b8957600080fd5b5080359060200135600160a060020a0316611ce1565b348015610bab57600080fd5b5061050260048036036040811015610bc257600080fd5b50600160a060020a038135169060200135611d02565b348015610be457600080fd5b50610406611d1d565b348015610bf957600080fd5b5061050260048036036020811015610c1057600080fd5b5035600160a060020a0316611d2c565b348015610c2c57600080fd5b5061050260048036036040811015610c4357600080fd5b50600160a060020a0381351690602001351515611de4565b348015610c6757600080fd5b50610502611f02565b348015610c7c57600080fd5b5061051960048036036020811015610c9357600080fd5b5035600160a060020a0316611faf565b61050260048036036080811015610cb957600080fd5b600160a060020a03823581169260208101359091169160408201359190810190608081016060820135640100000000811115610cf457600080fd5b820183602082011115610d0657600080fd5b80359060200191846001830284011164010000000083111715610d2857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612044945050505050565b348015610d7557600080fd5b506105026121db565b348015610d8a57600080fd5b5061050260048036036020811015610da157600080fd5b5035600160a060020a0316612284565b348015610dbd57600080fd5b50610519612380565b348015610dd257600080fd5b50610519612386565b348015610de757600080fd5b506103c860048036036040811015610dfe57600080fd5b50600160a060020a038135811691602001351661238c565b348015610e2257600080fd5b5061050260048036036020811015610e3957600080fd5b5035600160a060020a03166123ba565b61050260048036036020811015610e5f57600080fd5b5035600160a060020a03166123d4565b348015610e7b57600080fd5b5061050260048036036040811015610e9257600080fd5b810190602081018135640100000000811115610ead57600080fd5b820183602082011115610ebf57600080fd5b80359060200191846020830284011164010000000083111715610ee157600080fd5b91935091503561242e565b600160e060020a0319811660009081526020819052604090205460ff165b919050565b60708181548110610f1c57fe5b600091825260209091200154600160a060020a0316905081565b60738054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fc25780601f10610f9757610100808354040283529160200191610fc2565b820191906000526020600020905b815481529060010190602001808311610fa557829003601f168201915b505050505090505b90565b6000610fd88261247d565b92915050565b60675460a060020a900460ff1661102d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b806110388133611ce1565b80611048575061104881336124ea565b80611060575061106061105a826118ab565b3361238c565b6110b4576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b33600160a060020a0384161415611115576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b6000828152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385169081179091558290611157826118ab565b600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60755481565b60745481565b606854600160a060020a031681565b607054606090611206576040805160e560020a62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b60705482908482029060009082840111156112295750607054818103925061122e565b508082015b60608360405190808252806020026020018201604052801561125a578160200160208202803883390190505b5090506000835b838110156112c4576070818154811061127657fe5b9060005260206000200160009054906101000a9004600160a060020a03168383815181106112a057fe5b600160a060020a039092166020928302919091019091015260019182019101611261565b5090979650505050505050565b606a5481565b60695481565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b606c5490565b611315611c32565b61131e57600080fd5b60675460a060020a900460ff1661136d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113bf3361250b565b905060006113cc33612525565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a3426001830155801561141c5761141c3382612605565b5050565b60675460a060020a900460ff1661146f576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8261147981611936565b6114bb576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b816114c68133611ce1565b806114d657506114d681336124ea565b806114e857506114e861105a826118ab565b61153c576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b600160a060020a038416611588576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b60006115938661250b565b905060006115a08661250b565b60018101548154919250906115b457825482555b6115c287836000015461283b565b4281116115d857600180840154908301556115f5565b60018301546115ef9042830363ffffffff6128cf16565b60018301555b426001840155611604866128e8565b8587600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611657611c32565b61166057600080fd5b806116b5576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607491909155607555565b606c5481565b61171b611c32565b61172457600080fd5b600061172f30612930565b905060008111611789576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792816129d7565b50565b61179d611c32565b6117a657600080fd5b806117fb576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b60675460a060020a900460ff1681565b61187e83838360405180602001604052806000815250612044565b505050565b6000610fd882612525565b611896611c32565b61189f57600080fd5b61187e607383836132d2565b6000818152606f60205260408120548290600160a060020a0316611919576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b50506000908152606f6020526040902054600160a060020a031690565b600160a060020a03166000908152606e6020526040902060010154421090565b6000600160a060020a0382166119a4576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e60205260409020600101546119cb5760006119ce565b60015b60ff1692915050565b60675460a060020a900460ff16611a26576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b80611a3081611936565b611a72576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b61187e8383612a21565b611a84611c32565b611a8d57600080fd5b603454604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36034805473ffffffffffffffffffffffffffffffffffffffff19169055565b611aec611c32565b611af557600080fd5b60008111611b4d576040805160e560020a62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5830612930565b905081811015611bb2576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b61141c826129d7565b606b5481565b611bc9611c32565b611bd257600080fd5b60005b83811015611c1c57611c14858583818110611bec57fe5b90506020020135600160a060020a0316848484818110611c0857fe5b90506020020135612d43565b600101611bd5565b5050505050565b603454600160a060020a031690565b603454600160a060020a0316331490565b60765481565b60705490565b600160a060020a0381166000908152606e602052604081206001810154839190611cc3576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090205490565b6000918252606f602052604090912054600160a060020a0391821691161490565b611d0a611c32565b611d1357600080fd5b61141c8282612d43565b606754600160a060020a031681565b611d34611c32565b611d3d57600080fd5b80611d4781611936565b611d89576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b60675460a060020a900460ff16611e33576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b600160a060020a038216331415611e94576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152607260209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611f0a611c32565b611f1357600080fd5b60675460a060020a900460ff1615611f75576040805160e560020a62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b600160a060020a0381166000908152606e602052604081206001810154839190612023576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090206001015490565b60675460a060020a900460ff16612093576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8161209e8133611ce1565b806120ae57506120ae81336124ea565b806120c057506120c061105a826118ab565b612114576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b61211d836118ab565b61212681611936565b612168576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b612173868686611420565b61217f86868686612e52565b6121d3576040805160e560020a62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6121e3611c32565b6121ec57600080fd5b60675460a060020a900460ff1661223b576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061229d575061229d612fb7565b806122ab575060015460ff16155b6122e95760405160e560020a62461bcd02815260040180806020018281038252602e81526020018061338b602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff191683179092556034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606d5481565b60775481565b600160a060020a03918216600090815260726020908152604080832093909416825291909152205460ff1690565b6123c2611c32565b6123cb57600080fd5b61179281612fbd565b60675460a060020a900460ff16612423576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b611792816000612a21565b612436611c32565b61243f57600080fd5b60005b828110156124775761246f84848381811061245957fe5b90506020020135600160a060020a031683612d43565b600101612442565b50505050565b600081815260716020526040812054600160a060020a031680610fd8576040805160e560020a62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b60009182526071602052604090912054600160a060020a0391821691161490565b600160a060020a03166000908152606e6020526040902090565b60008161253181611936565b612573576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600061257e8461250b565b90506000428260010154039050606954811061259e57606a5493506125bf565b606954606a546125b4908363ffffffff61303916565b816125bb57fe5b0493505b60006075546125db607454606a5461303990919063ffffffff16565b816125e257fe5b049050808511156125f75780850394506125fc565b600094505b50505050919050565b606754600160a060020a031661265157604051600160a060020a0383169082156108fc029083906000818181858888f1935050505015801561264b573d6000803e3d6000fd5b5061141c565b6067546040805160e060020a6370a08231028152600160a060020a0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b1580156126a657600080fd5b505afa1580156126ba573d6000803e3d6000fd5b505050506040513d60208110156126d057600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561274157600080fd5b505af1158015612755573d6000803e3d6000fd5b505050506040513d602081101561276b57600080fd5b50506040805160e060020a6370a08231028152600160a060020a038681166004830152915183928516916370a08231916024808301926020929190829003018186803b1580156127ba57600080fd5b505afa1580156127ce573d6000803e3d6000fd5b505050506040513d60208110156127e457600080fd5b505111612477576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b6000818152606f6020526040902054600160a060020a0383811691161461141c5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b018054600160a060020a03841673ffffffffffffffffffffffffffffffffffffffff1991821681179092556000838152606f60205260409020805490911690911790555050565b6000828201838110156128e157600080fd5b9392505050565b600081815260716020526040902054600160a060020a031615611792576000908152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b606754600090600160a060020a03166129545750600160a060020a03811631610f0a565b6067546040805160e060020a6370a08231028152600160a060020a038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156129a457600080fd5b505afa1580156129b8573d6000803e3d6000fd5b505050506040513d60208110156129ce57600080fd5b50519050610f0a565b6129e86129e2611c23565b82612605565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606c54606b5411612a7c576040805160e560020a62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216612ac8576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b606a54606854604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612b3a57600080fd5b505afa158015612b4e573d6000803e3d6000fd5b505050506040513d6040811015612b6457600080fd5b50805160209091015190935091508080841115612b8357506000612b88565b508281035b612b9181613060565b6000612b9c8761250b565b600181015490915042811015612bd257612bb5826132b7565b612bc388836000015461283b565b60695442016001830155612bec565b606954612be690829063ffffffff6128cf16565b60018301555b8515612c7857606854604080517f3652466300000000000000000000000000000000000000000000000000000000815260048101899052602481018890529051600160a060020a039092169163365246639160448082019260009290919082900301818387803b158015612c5f57600080fd5b505af1158015612c73573d6000803e3d6000fd5b505050505b606854604080517f939d9f1f00000000000000000000000000000000000000000000000000000000815260048101869052600160a060020a038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612ce657600080fd5b505af1158015612cfa573d6000803e3d6000fd5b5050606c54604051909250600160a060020a038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b600160a060020a038216612d8f576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b6000612d9a8361250b565b905080600101548211612df7576040805160e560020a62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b612e00816132b7565b612e0e83826000015461283b565b600181018290558054604051600160a060020a038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000612e6684600160a060020a03166132cc565b612e72575060016112ff565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015612f05578181015183820152602001612eed565b50505050905090810190601f168015612f325780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612f5457600080fd5b505af1158015612f68573d6000803e3d6000fd5b505050506040513d6020811015612f7e57600080fd5b5051600160e060020a0319167f150b7a020000000000000000000000000000000000000000000000000000000014915050949350505050565b303b1590565b600160a060020a038116612fd057600080fd5b603454604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008261304857506000610fd8565b8282028284828161305557fe5b04146128e157600080fd5b606754600160a060020a03166130cd57803410156130c8576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792565b6067546040805160e060020a6370a082310281523060048201529051600160a060020a039092169160009183916370a0823191602480820192602092909190829003018186803b15801561312057600080fd5b505afa158015613134573d6000803e3d6000fd5b505050506040513d602081101561314a57600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690529051919250600160a060020a038416916323b872dd916064808201926020929091908290030181600087803b1580156131be57600080fd5b505af11580156131d2573d6000803e3d6000fd5b505050506040513d60208110156131e857600080fd5b50506040805160e060020a6370a0823102815230600482015290518291600160a060020a038516916370a0823191602480820192602092909190829003018186803b15801561323657600080fd5b505afa15801561324a573d6000803e3d6000fd5b505050506040513d602081101561326057600080fd5b50511161187e576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b805461179257606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106133135782800160ff19823516178555613340565b82800160010185558215613340579182015b82811115613340578235825591602001919060010190613325565b5061334c929150613350565b5090565b610fca91905b8082111561334c576000815560010161335656fe4c4f434b5f444550524543415445440000000000000000000000000000000000436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65644b45595f4e4f545f56414c494400000000000000000000000000000000000000494e56414c49445f414444524553530000000000000000000000000000000000a165627a7a72305820307d7415f1879a4c56340443cd73d8bea62267dd331ec6d62442029fc4f258790029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564", - "deployedBytecode": "0x608060405260043610610337576000357c01000000000000000000000000000000000000000000000000000000009004806370a08231116101c85780639d76ea5811610114578063c4d66de8116100b2578063e985e9c51161008c578063e985e9c514610ddb578063f2fde38b14610e16578063f6e4641f14610e49578063f8faf94214610e6f57610337565b8063c4d66de814610d7e578063d1bbd49c14610db1578063d42cfc4114610dc657610337565b8063a843a4e7116100ee578063a843a4e714610c5b578063abdf82ce14610c70578063b88d4fde14610ca3578063c1c98d0314610d6957610337565b80639d76ea5814610bd85780639f98d3cb14610bed578063a22cb46514610c2057610337565b80638da5cb5b1161018157806393fd18441161015b57806393fd184414610b1e578063970aaeb714610b33578063994a8a7114610b665780639b3f0b1714610b9f57610337565b80638da5cb5b14610adf5780638f32d59b14610af45780638f98ce8f14610b0957610337565b806370a082311461095b57806370efb7701461098e578063715018a6146109bc57806371d2ee6c146109d157806374b6c106146109fb5780637c7c425314610a1057610337565b80631f1ec029116102875780633d3359cb1161024057806352d6a8e41161021a57806352d6a8e41461084e578063550ef3a8146108815780636352211e146108fe5780636d8ea5b41461092857610337565b80633d3359cb146107d35780634136aa351461080357806342842e0e1461081857610337565b80631f1ec029146107045780632009dc651461072e57806323b872dd1461074357806339f46986146107795780633ba70e31146107a95780633ccfd60b146107be57610337565b80630ed3e2cc116102f457806310e56973116102ce57806310e56973146105d557806311a4c03a146105ea578063150b7a02146105ff57806318160ddd146106ef57610337565b80630ed3e2cc1461052b5780630f15023b1461054057806310803b721461055557610337565b806301ffc9a714610394578063025e7c27146103dc57806306fdde0314610422578063081812fc146104ac578063095ea7b3146104d65780630c79130f14610504575b34801561034357600080fd5b506040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b3480156103a057600080fd5b506103c8600480360360208110156103b757600080fd5b5035600160e060020a031916610eec565b604080519115158252519081900360200190f35b3480156103e857600080fd5b50610406600480360360208110156103ff57600080fd5b5035610f0f565b60408051600160a060020a039092168252519081900360200190f35b34801561042e57600080fd5b50610437610f36565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610471578181015183820152602001610459565b50505050905090810190601f16801561049e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104b857600080fd5b50610406600480360360208110156104cf57600080fd5b5035610fcd565b610502600480360360408110156104ec57600080fd5b50600160a060020a038135169060200135610fde565b005b34801561051057600080fd5b50610519611191565b60408051918252519081900360200190f35b34801561053757600080fd5b50610519611197565b34801561054c57600080fd5b5061040661119d565b34801561056157600080fd5b506105856004803603604081101561057857600080fd5b50803590602001356111ac565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105c15781810151838201526020016105a9565b505050509050019250505060405180910390f35b3480156105e157600080fd5b506105196112d1565b3480156105f657600080fd5b506105196112d7565b34801561060b57600080fd5b506106d26004803603608081101561062257600080fd5b600160a060020a0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561065d57600080fd5b82018360208201111561066f57600080fd5b8035906020019184600183028401116401000000008311171561069157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112dd945050505050565b60408051600160e060020a03199092168252519081900360200190f35b3480156106fb57600080fd5b50610519611307565b34801561071057600080fd5b506105026004803603602081101561072757600080fd5b503561130d565b34801561073a57600080fd5b506105026113b4565b6105026004803603606081101561075957600080fd5b50600160a060020a03813581169160208101359091169060400135611420565b34801561078557600080fd5b506105026004803603604081101561079c57600080fd5b508035906020013561164f565b3480156107b557600080fd5b5061051961170d565b3480156107ca57600080fd5b50610502611713565b3480156107df57600080fd5b50610502600480360360408110156107f657600080fd5b5080359060200135611795565b34801561080f57600080fd5b506103c8611853565b6105026004803603606081101561082e57600080fd5b50600160a060020a03813581169160208101359091169060400135611863565b34801561085a57600080fd5b506105196004803603602081101561087157600080fd5b5035600160a060020a0316611883565b34801561088d57600080fd5b50610502600480360360208110156108a457600080fd5b8101906020810181356401000000008111156108bf57600080fd5b8201836020820111156108d157600080fd5b803590602001918460018302840111640100000000831117156108f357600080fd5b50909250905061188e565b34801561090a57600080fd5b506104066004803603602081101561092157600080fd5b50356118ab565b34801561093457600080fd5b506103c86004803603602081101561094b57600080fd5b5035600160a060020a0316611936565b34801561096757600080fd5b506105196004803603602081101561097e57600080fd5b5035600160a060020a0316611956565b610502600480360360408110156109a457600080fd5b50600160a060020a03813581169160200135166119d7565b3480156109c857600080fd5b50610502611a7c565b3480156109dd57600080fd5b50610502600480360360208110156109f457600080fd5b5035611ae4565b348015610a0757600080fd5b50610519611bbb565b348015610a1c57600080fd5b5061050260048036036040811015610a3357600080fd5b810190602081018135640100000000811115610a4e57600080fd5b820183602082011115610a6057600080fd5b80359060200191846020830284011164010000000083111715610a8257600080fd5b919390929091602081019035640100000000811115610aa057600080fd5b820183602082011115610ab257600080fd5b80359060200191846020830284011164010000000083111715610ad457600080fd5b509092509050611bc1565b348015610aeb57600080fd5b50610406611c23565b348015610b0057600080fd5b506103c8611c32565b348015610b1557600080fd5b50610519611c43565b348015610b2a57600080fd5b50610519611c49565b348015610b3f57600080fd5b5061051960048036036020811015610b5657600080fd5b5035600160a060020a0316611c4f565b348015610b7257600080fd5b506103c860048036036040811015610b8957600080fd5b5080359060200135600160a060020a0316611ce1565b348015610bab57600080fd5b5061050260048036036040811015610bc257600080fd5b50600160a060020a038135169060200135611d02565b348015610be457600080fd5b50610406611d1d565b348015610bf957600080fd5b5061050260048036036020811015610c1057600080fd5b5035600160a060020a0316611d2c565b348015610c2c57600080fd5b5061050260048036036040811015610c4357600080fd5b50600160a060020a0381351690602001351515611de4565b348015610c6757600080fd5b50610502611f02565b348015610c7c57600080fd5b5061051960048036036020811015610c9357600080fd5b5035600160a060020a0316611faf565b61050260048036036080811015610cb957600080fd5b600160a060020a03823581169260208101359091169160408201359190810190608081016060820135640100000000811115610cf457600080fd5b820183602082011115610d0657600080fd5b80359060200191846001830284011164010000000083111715610d2857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612044945050505050565b348015610d7557600080fd5b506105026121db565b348015610d8a57600080fd5b5061050260048036036020811015610da157600080fd5b5035600160a060020a0316612284565b348015610dbd57600080fd5b50610519612380565b348015610dd257600080fd5b50610519612386565b348015610de757600080fd5b506103c860048036036040811015610dfe57600080fd5b50600160a060020a038135811691602001351661238c565b348015610e2257600080fd5b5061050260048036036020811015610e3957600080fd5b5035600160a060020a03166123ba565b61050260048036036020811015610e5f57600080fd5b5035600160a060020a03166123d4565b348015610e7b57600080fd5b5061050260048036036040811015610e9257600080fd5b810190602081018135640100000000811115610ead57600080fd5b820183602082011115610ebf57600080fd5b80359060200191846020830284011164010000000083111715610ee157600080fd5b91935091503561242e565b600160e060020a0319811660009081526020819052604090205460ff165b919050565b60708181548110610f1c57fe5b600091825260209091200154600160a060020a0316905081565b60738054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fc25780601f10610f9757610100808354040283529160200191610fc2565b820191906000526020600020905b815481529060010190602001808311610fa557829003601f168201915b505050505090505b90565b6000610fd88261247d565b92915050565b60675460a060020a900460ff1661102d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b806110388133611ce1565b80611048575061104881336124ea565b80611060575061106061105a826118ab565b3361238c565b6110b4576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b33600160a060020a0384161415611115576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b6000828152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385169081179091558290611157826118ab565b600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60755481565b60745481565b606854600160a060020a031681565b607054606090611206576040805160e560020a62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b60705482908482029060009082840111156112295750607054818103925061122e565b508082015b60608360405190808252806020026020018201604052801561125a578160200160208202803883390190505b5090506000835b838110156112c4576070818154811061127657fe5b9060005260206000200160009054906101000a9004600160a060020a03168383815181106112a057fe5b600160a060020a039092166020928302919091019091015260019182019101611261565b5090979650505050505050565b606a5481565b60695481565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b606c5490565b611315611c32565b61131e57600080fd5b60675460a060020a900460ff1661136d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113bf3361250b565b905060006113cc33612525565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a3426001830155801561141c5761141c3382612605565b5050565b60675460a060020a900460ff1661146f576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8261147981611936565b6114bb576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b816114c68133611ce1565b806114d657506114d681336124ea565b806114e857506114e861105a826118ab565b61153c576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b600160a060020a038416611588576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b60006115938661250b565b905060006115a08661250b565b60018101548154919250906115b457825482555b6115c287836000015461283b565b4281116115d857600180840154908301556115f5565b60018301546115ef9042830363ffffffff6128cf16565b60018301555b426001840155611604866128e8565b8587600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611657611c32565b61166057600080fd5b806116b5576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607491909155607555565b606c5481565b61171b611c32565b61172457600080fd5b600061172f30612930565b905060008111611789576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792816129d7565b50565b61179d611c32565b6117a657600080fd5b806117fb576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b60675460a060020a900460ff1681565b61187e83838360405180602001604052806000815250612044565b505050565b6000610fd882612525565b611896611c32565b61189f57600080fd5b61187e607383836132d2565b6000818152606f60205260408120548290600160a060020a0316611919576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b50506000908152606f6020526040902054600160a060020a031690565b600160a060020a03166000908152606e6020526040902060010154421090565b6000600160a060020a0382166119a4576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e60205260409020600101546119cb5760006119ce565b60015b60ff1692915050565b60675460a060020a900460ff16611a26576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b80611a3081611936565b611a72576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b61187e8383612a21565b611a84611c32565b611a8d57600080fd5b603454604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36034805473ffffffffffffffffffffffffffffffffffffffff19169055565b611aec611c32565b611af557600080fd5b60008111611b4d576040805160e560020a62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5830612930565b905081811015611bb2576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b61141c826129d7565b606b5481565b611bc9611c32565b611bd257600080fd5b60005b83811015611c1c57611c14858583818110611bec57fe5b90506020020135600160a060020a0316848484818110611c0857fe5b90506020020135612d43565b600101611bd5565b5050505050565b603454600160a060020a031690565b603454600160a060020a0316331490565b60765481565b60705490565b600160a060020a0381166000908152606e602052604081206001810154839190611cc3576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090205490565b6000918252606f602052604090912054600160a060020a0391821691161490565b611d0a611c32565b611d1357600080fd5b61141c8282612d43565b606754600160a060020a031681565b611d34611c32565b611d3d57600080fd5b80611d4781611936565b611d89576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b60675460a060020a900460ff16611e33576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b600160a060020a038216331415611e94576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152607260209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611f0a611c32565b611f1357600080fd5b60675460a060020a900460ff1615611f75576040805160e560020a62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b600160a060020a0381166000908152606e602052604081206001810154839190612023576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090206001015490565b60675460a060020a900460ff16612093576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8161209e8133611ce1565b806120ae57506120ae81336124ea565b806120c057506120c061105a826118ab565b612114576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b61211d836118ab565b61212681611936565b612168576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b612173868686611420565b61217f86868686612e52565b6121d3576040805160e560020a62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6121e3611c32565b6121ec57600080fd5b60675460a060020a900460ff1661223b576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061229d575061229d612fb7565b806122ab575060015460ff16155b6122e95760405160e560020a62461bcd02815260040180806020018281038252602e81526020018061338b602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff191683179092556034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606d5481565b60775481565b600160a060020a03918216600090815260726020908152604080832093909416825291909152205460ff1690565b6123c2611c32565b6123cb57600080fd5b61179281612fbd565b60675460a060020a900460ff16612423576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b611792816000612a21565b612436611c32565b61243f57600080fd5b60005b828110156124775761246f84848381811061245957fe5b90506020020135600160a060020a031683612d43565b600101612442565b50505050565b600081815260716020526040812054600160a060020a031680610fd8576040805160e560020a62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b60009182526071602052604090912054600160a060020a0391821691161490565b600160a060020a03166000908152606e6020526040902090565b60008161253181611936565b612573576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600061257e8461250b565b90506000428260010154039050606954811061259e57606a5493506125bf565b606954606a546125b4908363ffffffff61303916565b816125bb57fe5b0493505b60006075546125db607454606a5461303990919063ffffffff16565b816125e257fe5b049050808511156125f75780850394506125fc565b600094505b50505050919050565b606754600160a060020a031661265157604051600160a060020a0383169082156108fc029083906000818181858888f1935050505015801561264b573d6000803e3d6000fd5b5061141c565b6067546040805160e060020a6370a08231028152600160a060020a0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b1580156126a657600080fd5b505afa1580156126ba573d6000803e3d6000fd5b505050506040513d60208110156126d057600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561274157600080fd5b505af1158015612755573d6000803e3d6000fd5b505050506040513d602081101561276b57600080fd5b50506040805160e060020a6370a08231028152600160a060020a038681166004830152915183928516916370a08231916024808301926020929190829003018186803b1580156127ba57600080fd5b505afa1580156127ce573d6000803e3d6000fd5b505050506040513d60208110156127e457600080fd5b505111612477576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b6000818152606f6020526040902054600160a060020a0383811691161461141c5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b018054600160a060020a03841673ffffffffffffffffffffffffffffffffffffffff1991821681179092556000838152606f60205260409020805490911690911790555050565b6000828201838110156128e157600080fd5b9392505050565b600081815260716020526040902054600160a060020a031615611792576000908152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b606754600090600160a060020a03166129545750600160a060020a03811631610f0a565b6067546040805160e060020a6370a08231028152600160a060020a038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156129a457600080fd5b505afa1580156129b8573d6000803e3d6000fd5b505050506040513d60208110156129ce57600080fd5b50519050610f0a565b6129e86129e2611c23565b82612605565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606c54606b5411612a7c576040805160e560020a62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216612ac8576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b606a54606854604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612b3a57600080fd5b505afa158015612b4e573d6000803e3d6000fd5b505050506040513d6040811015612b6457600080fd5b50805160209091015190935091508080841115612b8357506000612b88565b508281035b612b9181613060565b6000612b9c8761250b565b600181015490915042811015612bd257612bb5826132b7565b612bc388836000015461283b565b60695442016001830155612bec565b606954612be690829063ffffffff6128cf16565b60018301555b8515612c7857606854604080517f3652466300000000000000000000000000000000000000000000000000000000815260048101899052602481018890529051600160a060020a039092169163365246639160448082019260009290919082900301818387803b158015612c5f57600080fd5b505af1158015612c73573d6000803e3d6000fd5b505050505b606854604080517f939d9f1f00000000000000000000000000000000000000000000000000000000815260048101869052600160a060020a038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612ce657600080fd5b505af1158015612cfa573d6000803e3d6000fd5b5050606c54604051909250600160a060020a038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b600160a060020a038216612d8f576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b6000612d9a8361250b565b905080600101548211612df7576040805160e560020a62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b612e00816132b7565b612e0e83826000015461283b565b600181018290558054604051600160a060020a038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000612e6684600160a060020a03166132cc565b612e72575060016112ff565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015612f05578181015183820152602001612eed565b50505050905090810190601f168015612f325780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612f5457600080fd5b505af1158015612f68573d6000803e3d6000fd5b505050506040513d6020811015612f7e57600080fd5b5051600160e060020a0319167f150b7a020000000000000000000000000000000000000000000000000000000014915050949350505050565b303b1590565b600160a060020a038116612fd057600080fd5b603454604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008261304857506000610fd8565b8282028284828161305557fe5b04146128e157600080fd5b606754600160a060020a03166130cd57803410156130c8576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792565b6067546040805160e060020a6370a082310281523060048201529051600160a060020a039092169160009183916370a0823191602480820192602092909190829003018186803b15801561312057600080fd5b505afa158015613134573d6000803e3d6000fd5b505050506040513d602081101561314a57600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690529051919250600160a060020a038416916323b872dd916064808201926020929091908290030181600087803b1580156131be57600080fd5b505af11580156131d2573d6000803e3d6000fd5b505050506040513d60208110156131e857600080fd5b50506040805160e060020a6370a0823102815230600482015290518291600160a060020a038516916370a0823191602480820192602092909190829003018186803b15801561323657600080fd5b505afa15801561324a573d6000803e3d6000fd5b505050506040513d602081101561326057600080fd5b50511161187e576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b805461179257606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106133135782800160ff19823516178555613340565b82800160010185558215613340579182015b82811115613340578235825591602001919060010190613325565b5061334c929150613350565b5090565b610fca91905b8082111561334c576000815560010161335656fe4c4f434b5f444550524543415445440000000000000000000000000000000000436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65644b45595f4e4f545f56414c494400000000000000000000000000000000000000494e56414c49445f414444524553530000000000000000000000000000000000a165627a7a72305820307d7415f1879a4c56340443cd73d8bea62267dd331ec6d62442029fc4f258790029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.6", - "updatedAt": "2019-04-04T15:05:08.513Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV2.json b/packages/contracts/src/abis/PublicLock/PublicLockV2.json deleted file mode 100644 index d990679ab70..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV2.json +++ /dev/null @@ -1,1158 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_approved", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_page", - "type": "uint256" - }, - { - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_refundPenaltyNumerator", - "type": "uint256" - }, - { - "name": "_refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfKeysSold", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_transferFeeNumerator", - "type": "uint256" - }, - { - "name": "_transferFeeDenominator", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "purchaseForFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_amount", - "type": "uint256" - } - ], - "name": "partialWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - } - ], - "name": "purchaseFor", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldRefundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldRefundPenaltyDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldTransferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldTransferFeeDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeDenominator", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_sender", - "type": "address" - }, - { - "indexed": false, - "name": "_amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - } - ], - "bytecode": "0x6080604052600060745560646075556001607655600a6077553480156200002557600080fd5b5060405160a08062003831833981018060405260a08110156200004757600080fd5b508051602080830151604084015160608501516080909501519394919390928490839083906001908790620000a2907f01ffc9a70000000000000000000000000000000000000000000000000000000090620002cb811b901c565b6001600160a01b03811615806200012057506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015620000f057600080fd5b505afa15801562000105573d6000803e3d6000fd5b505050506040513d60208110156200011c57600080fd5b5051115b6200018c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60688054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200024257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606980546001600160a01b03191633179055606a93909355606b91909155606c55606e805460ff90921660ff19909216919091179055620002aa7f80ac58cd00000000000000000000000000000000000000000000000000000000620002cb602090811b901c565b620002c0856200033860201b620023341760201c565b505050505062000450565b7fffffffff000000000000000000000000000000000000000000000000000000008082161415620002fb57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200035a57506200035a6200044a60201b60201c565b8062000369575060015460ff16155b620003c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003803602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b6133a380620004606000396000f3fe6080604052600436106103355760003560e01c806370efb770116101ab5780639d76ea58116100f7578063c4d66de811610095578063e985e9c51161006f578063e985e9c514610e09578063f2fde38b14610e44578063f6e4641f14610e77578063f8faf94214610e9d57610335565b8063c4d66de814610d96578063d1bbd49c14610dc9578063d42cfc4114610df457610335565b8063a843a4e7116100d1578063a843a4e714610c75578063abdf82ce14610c8a578063b88d4fde14610cbd578063c1c98d0314610d8157610335565b80639d76ea5814610bf25780639f98d3cb14610c07578063a22cb46514610c3a57610335565b80638da5cb5b1161016457806393fd18441161013e57806393fd184414610b38578063970aaeb714610b4d578063994a8a7114610b805780639b3f0b1714610bb957610335565b80638da5cb5b14610af95780638f32d59b14610b0e5780638f98ce8f14610b2357610335565b806370efb77014610979578063715018a6146109a757806371d2ee6c146109bc57806374b6c106146109e65780637c7c4253146109fb57806383cb0fa914610ac657610335565b80631f1ec029116102855780634136aa3511610223578063550ef3a8116101fd578063550ef3a81461086e5780636352211e146108e95780636d8ea5b41461091357806370a082311461094657610335565b80634136aa35146107f057806342842e0e1461080557806352d6a8e41461083b57610335565b806339f469861161025f57806339f46986146107665780633ba70e31146107965780633ccfd60b146107ab5780633d3359cb146107c057610335565b80631f1ec029146106f15780632009dc651461071b57806323b872dd1461073057610335565b80630ed3e2cc116102f257806310e56973116102cc57806310e56973146105c457806311a4c03a146105d9578063150b7a02146105ee57806318160ddd146106dc57610335565b80630ed3e2cc1461051a5780630f15023b1461052f57806310803b721461054457610335565b806301ffc9a714610383578063025e7c27146103cb57806306fdde0314610411578063081812fc1461049b578063095ea7b3146104c55780630c79130f146104f3575b34801561034157600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561038f57600080fd5b506103b7600480360360208110156103a657600080fd5b50356001600160e01b031916610f18565b604080519115158252519081900360200190f35b3480156103d757600080fd5b506103f5600480360360208110156103ee57600080fd5b5035610f3b565b604080516001600160a01b039092168252519081900360200190f35b34801561041d57600080fd5b50610426610f62565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610460578181015183820152602001610448565b50505050905090810190601f16801561048d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104a757600080fd5b506103f5600480360360208110156104be57600080fd5b5035610ff9565b6104f1600480360360408110156104db57600080fd5b506001600160a01b03813516906020013561100a565b005b3480156104ff57600080fd5b506105086111a9565b60408051918252519081900360200190f35b34801561052657600080fd5b506105086111af565b34801561053b57600080fd5b506103f56111b5565b34801561055057600080fd5b506105746004803603604081101561056757600080fd5b50803590602001356111c4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105b0578181015183820152602001610598565b505050509050019250505060405180910390f35b3480156105d057600080fd5b506105086112e9565b3480156105e557600080fd5b506105086112ef565b3480156105fa57600080fd5b506106bf6004803603608081101561061157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561064b57600080fd5b82018360208201111561065d57600080fd5b803590602001918460018302840111600160201b8311171561067e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112f5945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156106e857600080fd5b50610508611309565b3480156106fd57600080fd5b506104f16004803603602081101561071457600080fd5b503561130f565b34801561072757600080fd5b506104f16113bd565b6104f16004803603606081101561074657600080fd5b506001600160a01b03813581169160208101359091169060400135611429565b34801561077257600080fd5b506104f16004803603604081101561078957600080fd5b508035906020013561167c565b3480156107a257600080fd5b5061050861172c565b3480156107b757600080fd5b506104f1611732565b3480156107cc57600080fd5b506104f1600480360360408110156107e357600080fd5b50803590602001356117aa565b3480156107fc57600080fd5b506103b761185a565b6104f16004803603606081101561081b57600080fd5b506001600160a01b0381358116916020810135909116906040013561186a565b34801561084757600080fd5b506105086004803603602081101561085e57600080fd5b50356001600160a01b031661188a565b34801561087a57600080fd5b506104f16004803603602081101561089157600080fd5b810190602081018135600160201b8111156108ab57600080fd5b8201836020820111156108bd57600080fd5b803590602001918460018302840111600160201b831117156108de57600080fd5b509092509050611895565b3480156108f557600080fd5b506103f56004803603602081101561090c57600080fd5b50356118b2565b34801561091f57600080fd5b506103b76004803603602081101561093657600080fd5b50356001600160a01b031661192e565b34801561095257600080fd5b506105086004803603602081101561096957600080fd5b50356001600160a01b031661194e565b6104f16004803603604081101561098f57600080fd5b506001600160a01b03813581169160200135166119d6565b3480156109b357600080fd5b506104f1611a87565b3480156109c857600080fd5b506104f1600480360360208110156109df57600080fd5b5035611ae2565b3480156109f257600080fd5b50610508611baf565b348015610a0757600080fd5b506104f160048036036040811015610a1e57600080fd5b810190602081018135600160201b811115610a3857600080fd5b820183602082011115610a4a57600080fd5b803590602001918460208302840111600160201b83111715610a6b57600080fd5b919390929091602081019035600160201b811115610a8857600080fd5b820183602082011115610a9a57600080fd5b803590602001918460208302840111600160201b83111715610abb57600080fd5b509092509050611bb5565b348015610ad257600080fd5b5061050860048036036020811015610ae957600080fd5b50356001600160a01b0316611c17565b348015610b0557600080fd5b506103f5611ce0565b348015610b1a57600080fd5b506103b7611cef565b348015610b2f57600080fd5b50610508611d00565b348015610b4457600080fd5b50610508611d06565b348015610b5957600080fd5b5061050860048036036020811015610b7057600080fd5b50356001600160a01b0316611d0c565b348015610b8c57600080fd5b506103b760048036036040811015610ba357600080fd5b50803590602001356001600160a01b0316611d8f565b348015610bc557600080fd5b506104f160048036036040811015610bdc57600080fd5b506001600160a01b038135169060200135611db0565b348015610bfe57600080fd5b506103f5611dcb565b348015610c1357600080fd5b506104f160048036036020811015610c2a57600080fd5b50356001600160a01b0316611dda565b348015610c4657600080fd5b506104f160048036036040811015610c5d57600080fd5b506001600160a01b0381351690602001351515611e97565b348015610c8157600080fd5b506104f1611fae565b348015610c9657600080fd5b5061050860048036036020811015610cad57600080fd5b50356001600160a01b031661205b565b6104f160048036036080811015610cd357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610d0d57600080fd5b820183602082011115610d1f57600080fd5b803590602001918460018302840111600160201b83111715610d4057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506120e1945050505050565b348015610d8d57600080fd5b506104f1612284565b348015610da257600080fd5b506104f160048036036020811015610db957600080fd5b50356001600160a01b0316612334565b348015610dd557600080fd5b50610dde612423565b6040805160ff9092168252519081900360200190f35b348015610e0057600080fd5b5061050861242c565b348015610e1557600080fd5b506103b760048036036040811015610e2c57600080fd5b506001600160a01b0381358116916020013516612432565b348015610e5057600080fd5b506104f160048036036020811015610e6757600080fd5b50356001600160a01b0316612460565b6104f160048036036020811015610e8d57600080fd5b50356001600160a01b031661247a565b348015610ea957600080fd5b506104f160048036036040811015610ec057600080fd5b810190602081018135600160201b811115610eda57600080fd5b820183602082011115610eec57600080fd5b803590602001918460208302840111600160201b83111715610f0d57600080fd5b9193509150356124db565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60718181548110610f4857fe5b6000918252602090912001546001600160a01b0316905081565b60678054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fee5780601f10610fc357610100808354040283529160200191610fee565b820191906000526020600020905b815481529060010190602001808311610fd157829003601f168201915b505050505090505b90565b60006110048261252a565b92915050565b606854600160a01b900460ff166110605760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b8061106b8133611d8f565b8061107b575061107b8133612597565b80611093575061109361108d826118b2565b33612432565b6110e75760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b038416141561113a5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260726020526040902080546001600160a01b0319166001600160a01b038516908117909155829061116f826118b2565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60775481565b60765481565b6069546001600160a01b031681565b60715460609061121e5760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b607154829084820290600090828401111561124157506071548181039250611246565b508082015b606083604051908082528060200260200182016040528015611272578160200160208202803883390190505b5090506000835b838110156112dc576071818154811061128e57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106112b857fe5b6001600160a01b039092166020928302919091019091015260019182019101611279565b5090979650505050505050565b606b5481565b606a5481565b600160e11b630a85bd01025b949350505050565b606d5490565b611317611cef565b61132057600080fd5b606854600160a01b900460ff166113765760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113c8336125b8565b905060006113d5336125d2565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a342600183015580156114255761142533826126b7565b5050565b606854600160a01b900460ff1661147f5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826114898161192e565b6114d05760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816114db8133611d8f565b806114eb57506114eb8133612597565b806114fd57506114fd61108d826118b2565b6115515760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b0384166115a45760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6115b56115b086611c17565b6128cc565b60006115c0866125b8565b905060006115cd866125b8565b60018101548154919250906115e157825482555b6115ef878360000154612af8565b4281116116055760018084015490830155611622565b600183015461161c9042830363ffffffff612b7f16565b60018301555b42600184015561163186612b98565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611684611cef565b61168d57600080fd5b806116d45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607691909155607755565b606d5481565b61173a611cef565b61174357600080fd5b600061174e30612bd3565b90506000811161179e5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a781612c7a565b50565b6117b2611cef565b6117bb57600080fd5b806118025760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607491909155607555565b606854600160a01b900460ff1681565b611885838383604051806020016040528060008152506120e1565b505050565b6000611004826125d2565b61189d611cef565b6118a657600080fd5b611885606783836132b1565b60008181526070602052604081205482906001600160a01b03166119115760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152607060205260409020546001600160a01b031690565b6001600160a01b03166000908152606f6020526040902060010154421090565b60006001600160a01b0382166119a35760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6001600160a01b0382166000908152606f60205260409020600101546119ca5760006119cd565b60015b60ff1692915050565b606854600160a01b900460ff16611a2c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b80611a368161192e565b611a7d5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6118858383612cc4565b611a8f611cef565b611a9857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b611aea611cef565b611af357600080fd5b60008111611b4b5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5630612bd3565b905081811015611ba65760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61142582612c7a565b606c5481565b611bbd611cef565b611bc657600080fd5b60005b83811015611c1057611c08858583818110611be057fe5b905060200201356001600160a01b0316848484818110611bfc57fe5b90506020020135612fab565b600101611bc9565b5050505050565b600081611c238161192e565b611c6a5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000611c75846125b8565b905060004282600101540390506000606a548210611c965750606b54611cb7565b606a54606b54611cac908463ffffffff6130c116565b81611cb357fe5b0490505b607554607454611cce90839063ffffffff6130c116565b81611cd557fe5b049695505050505050565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60745481565b60715490565b6001600160a01b0381166000908152606f602052604081206001810154839190611d715760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090205490565b600091825260706020526040909120546001600160a01b0391821691161490565b611db8611cef565b611dc157600080fd5b6114258282612fab565b6068546001600160a01b031681565b611de2611cef565b611deb57600080fd5b80611df58161192e565b611e3c5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606f602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606854600160a01b900460ff16611eed5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415611f405760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526073602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611fb6611cef565b611fbf57600080fd5b606854600160a01b900460ff16156120215760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b6001600160a01b0381166000908152606f6020526040812060018101548391906120c05760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090206001015490565b606854600160a01b900460ff166121375760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b816121428133611d8f565b8061215257506121528133612597565b80612164575061216461108d826118b2565b6121b85760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6121c1836118b2565b6121ca8161192e565b6122115760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b61221c868686611429565b612228868686866130e8565b61227c5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b61228c611cef565b61229557600080fd5b606854600160a01b900460ff166122eb5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16068805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061234d575061234d613221565b8061235b575060015460ff16155b61239957604051600160e51b62461bcd02815260040180806020018281038252602e81526020018061334a602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606e5460ff1681565b60755481565b6001600160a01b03918216600090815260736020908152604080832093909416825291909152205460ff1690565b612468611cef565b61247157600080fd5b6117a781613227565b606854600160a01b900460ff166124d05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6117a7816000612cc4565b6124e3611cef565b6124ec57600080fd5b60005b828110156125245761251c84848381811061250657fe5b905060200201356001600160a01b031683612fab565b6001016124ef565b50505050565b6000818152607260205260408120546001600160a01b0316806110045760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260726020526040909120546001600160a01b0391821691161490565b6001600160a01b03166000908152606f6020526040902090565b6000816125de8161192e565b6126255760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000612630846125b8565b90506000428260010154039050606a54811061265057606b549350612671565b606a54606b54612666908363ffffffff6130c116565b8161266d57fe5b0493505b600060775461268d607654606b546130c190919063ffffffff16565b8161269457fe5b049050808511156126a95780850394506126ae565b600094505b50505050919050565b6068546001600160a01b0316612703576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156126fd573d6000803e3d6000fd5b50611425565b60685460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b15801561275857600080fd5b505afa15801561276c573d6000803e3d6000fd5b505050506040513d602081101561278257600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d602081101561280757600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b15801561285657600080fd5b505afa15801561286a573d6000803e3d6000fd5b505050506040513d602081101561288057600080fd5b5051116125245760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6068546001600160a01b031661292f578034101561292a5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a7565b60685460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b158015612a0a57600080fd5b505af1158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015612a8257600080fd5b505afa158015612a96573d6000803e3d6000fd5b505050506040513d6020811015612aac57600080fd5b5051116118855760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6000818152607060205260409020546001600160a01b038381169116146114255760718054600181019091557fa1fcd19bfe8c32a61095b6bfbb2664842857e148fcbb5188386c8cd40348d5b60180546001600160a01b0384166001600160a01b031991821681179092556000838152607060205260409020805490911690911790555050565b600082820183811015612b9157600080fd5b9392505050565b6000818152607260205260409020546001600160a01b0316156117a757600090815260726020526040902080546001600160a01b0319169055565b6068546000906001600160a01b0316612bf757506001600160a01b03811631610f36565b60685460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d6020811015612c7157600080fd5b50519050610f36565b612c8b612c85611ce0565b826126b7565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606d54606c5411612d1f5760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216612d725760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606b5460695460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d6040811015612df857600080fd5b50805160209091015190935091508080841115612e1757506000612e1c565b508281035b612e25816128cc565b6000612e30876125b8565b600181015490915042811015612e6657612e4982613296565b612e57888360000154612af8565b606a5442016001830155612e80565b606a54612e7a90829063ffffffff612b7f16565b60018301555b8515612ef65760695460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015612edd57600080fd5b505af1158015612ef1573d6000803e3d6000fd5b505050505b60695460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612f4e57600080fd5b505af1158015612f62573d6000803e3d6000fd5b5050606d546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216612ffe5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613009836125b8565b9050806001015482116130665760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b61306f81613296565b61307d838260000154612af8565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000826130d057506000611004565b828202828482816130dd57fe5b0414612b9157600080fd5b60006130fc846001600160a01b03166132ab565b61310857506001611301565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b8381101561318557818101518382015260200161316d565b50505050905090810190601f1680156131b25780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156131d457600080fd5b505af11580156131e8573d6000803e3d6000fd5b505050506040513d60208110156131fe57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b303b1590565b6001600160a01b03811661323a57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546117a757606d8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132f25782800160ff1982351617855561331f565b8280016001018555821561331f579182015b8281111561331f578235825591602001919060010190613304565b5061332b92915061332f565b5090565b610ff691905b8082111561332b576000815560010161333556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582090e2645e8f5c8a27b9aa3e516ad14db63bd34f8938f3f859e51115419dc428460029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564", - "deployedBytecode": "0x6080604052600436106103355760003560e01c806370efb770116101ab5780639d76ea58116100f7578063c4d66de811610095578063e985e9c51161006f578063e985e9c514610e09578063f2fde38b14610e44578063f6e4641f14610e77578063f8faf94214610e9d57610335565b8063c4d66de814610d96578063d1bbd49c14610dc9578063d42cfc4114610df457610335565b8063a843a4e7116100d1578063a843a4e714610c75578063abdf82ce14610c8a578063b88d4fde14610cbd578063c1c98d0314610d8157610335565b80639d76ea5814610bf25780639f98d3cb14610c07578063a22cb46514610c3a57610335565b80638da5cb5b1161016457806393fd18441161013e57806393fd184414610b38578063970aaeb714610b4d578063994a8a7114610b805780639b3f0b1714610bb957610335565b80638da5cb5b14610af95780638f32d59b14610b0e5780638f98ce8f14610b2357610335565b806370efb77014610979578063715018a6146109a757806371d2ee6c146109bc57806374b6c106146109e65780637c7c4253146109fb57806383cb0fa914610ac657610335565b80631f1ec029116102855780634136aa3511610223578063550ef3a8116101fd578063550ef3a81461086e5780636352211e146108e95780636d8ea5b41461091357806370a082311461094657610335565b80634136aa35146107f057806342842e0e1461080557806352d6a8e41461083b57610335565b806339f469861161025f57806339f46986146107665780633ba70e31146107965780633ccfd60b146107ab5780633d3359cb146107c057610335565b80631f1ec029146106f15780632009dc651461071b57806323b872dd1461073057610335565b80630ed3e2cc116102f257806310e56973116102cc57806310e56973146105c457806311a4c03a146105d9578063150b7a02146105ee57806318160ddd146106dc57610335565b80630ed3e2cc1461051a5780630f15023b1461052f57806310803b721461054457610335565b806301ffc9a714610383578063025e7c27146103cb57806306fdde0314610411578063081812fc1461049b578063095ea7b3146104c55780630c79130f146104f3575b34801561034157600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561038f57600080fd5b506103b7600480360360208110156103a657600080fd5b50356001600160e01b031916610f18565b604080519115158252519081900360200190f35b3480156103d757600080fd5b506103f5600480360360208110156103ee57600080fd5b5035610f3b565b604080516001600160a01b039092168252519081900360200190f35b34801561041d57600080fd5b50610426610f62565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610460578181015183820152602001610448565b50505050905090810190601f16801561048d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104a757600080fd5b506103f5600480360360208110156104be57600080fd5b5035610ff9565b6104f1600480360360408110156104db57600080fd5b506001600160a01b03813516906020013561100a565b005b3480156104ff57600080fd5b506105086111a9565b60408051918252519081900360200190f35b34801561052657600080fd5b506105086111af565b34801561053b57600080fd5b506103f56111b5565b34801561055057600080fd5b506105746004803603604081101561056757600080fd5b50803590602001356111c4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105b0578181015183820152602001610598565b505050509050019250505060405180910390f35b3480156105d057600080fd5b506105086112e9565b3480156105e557600080fd5b506105086112ef565b3480156105fa57600080fd5b506106bf6004803603608081101561061157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561064b57600080fd5b82018360208201111561065d57600080fd5b803590602001918460018302840111600160201b8311171561067e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112f5945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156106e857600080fd5b50610508611309565b3480156106fd57600080fd5b506104f16004803603602081101561071457600080fd5b503561130f565b34801561072757600080fd5b506104f16113bd565b6104f16004803603606081101561074657600080fd5b506001600160a01b03813581169160208101359091169060400135611429565b34801561077257600080fd5b506104f16004803603604081101561078957600080fd5b508035906020013561167c565b3480156107a257600080fd5b5061050861172c565b3480156107b757600080fd5b506104f1611732565b3480156107cc57600080fd5b506104f1600480360360408110156107e357600080fd5b50803590602001356117aa565b3480156107fc57600080fd5b506103b761185a565b6104f16004803603606081101561081b57600080fd5b506001600160a01b0381358116916020810135909116906040013561186a565b34801561084757600080fd5b506105086004803603602081101561085e57600080fd5b50356001600160a01b031661188a565b34801561087a57600080fd5b506104f16004803603602081101561089157600080fd5b810190602081018135600160201b8111156108ab57600080fd5b8201836020820111156108bd57600080fd5b803590602001918460018302840111600160201b831117156108de57600080fd5b509092509050611895565b3480156108f557600080fd5b506103f56004803603602081101561090c57600080fd5b50356118b2565b34801561091f57600080fd5b506103b76004803603602081101561093657600080fd5b50356001600160a01b031661192e565b34801561095257600080fd5b506105086004803603602081101561096957600080fd5b50356001600160a01b031661194e565b6104f16004803603604081101561098f57600080fd5b506001600160a01b03813581169160200135166119d6565b3480156109b357600080fd5b506104f1611a87565b3480156109c857600080fd5b506104f1600480360360208110156109df57600080fd5b5035611ae2565b3480156109f257600080fd5b50610508611baf565b348015610a0757600080fd5b506104f160048036036040811015610a1e57600080fd5b810190602081018135600160201b811115610a3857600080fd5b820183602082011115610a4a57600080fd5b803590602001918460208302840111600160201b83111715610a6b57600080fd5b919390929091602081019035600160201b811115610a8857600080fd5b820183602082011115610a9a57600080fd5b803590602001918460208302840111600160201b83111715610abb57600080fd5b509092509050611bb5565b348015610ad257600080fd5b5061050860048036036020811015610ae957600080fd5b50356001600160a01b0316611c17565b348015610b0557600080fd5b506103f5611ce0565b348015610b1a57600080fd5b506103b7611cef565b348015610b2f57600080fd5b50610508611d00565b348015610b4457600080fd5b50610508611d06565b348015610b5957600080fd5b5061050860048036036020811015610b7057600080fd5b50356001600160a01b0316611d0c565b348015610b8c57600080fd5b506103b760048036036040811015610ba357600080fd5b50803590602001356001600160a01b0316611d8f565b348015610bc557600080fd5b506104f160048036036040811015610bdc57600080fd5b506001600160a01b038135169060200135611db0565b348015610bfe57600080fd5b506103f5611dcb565b348015610c1357600080fd5b506104f160048036036020811015610c2a57600080fd5b50356001600160a01b0316611dda565b348015610c4657600080fd5b506104f160048036036040811015610c5d57600080fd5b506001600160a01b0381351690602001351515611e97565b348015610c8157600080fd5b506104f1611fae565b348015610c9657600080fd5b5061050860048036036020811015610cad57600080fd5b50356001600160a01b031661205b565b6104f160048036036080811015610cd357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610d0d57600080fd5b820183602082011115610d1f57600080fd5b803590602001918460018302840111600160201b83111715610d4057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506120e1945050505050565b348015610d8d57600080fd5b506104f1612284565b348015610da257600080fd5b506104f160048036036020811015610db957600080fd5b50356001600160a01b0316612334565b348015610dd557600080fd5b50610dde612423565b6040805160ff9092168252519081900360200190f35b348015610e0057600080fd5b5061050861242c565b348015610e1557600080fd5b506103b760048036036040811015610e2c57600080fd5b506001600160a01b0381358116916020013516612432565b348015610e5057600080fd5b506104f160048036036020811015610e6757600080fd5b50356001600160a01b0316612460565b6104f160048036036020811015610e8d57600080fd5b50356001600160a01b031661247a565b348015610ea957600080fd5b506104f160048036036040811015610ec057600080fd5b810190602081018135600160201b811115610eda57600080fd5b820183602082011115610eec57600080fd5b803590602001918460208302840111600160201b83111715610f0d57600080fd5b9193509150356124db565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60718181548110610f4857fe5b6000918252602090912001546001600160a01b0316905081565b60678054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fee5780601f10610fc357610100808354040283529160200191610fee565b820191906000526020600020905b815481529060010190602001808311610fd157829003601f168201915b505050505090505b90565b60006110048261252a565b92915050565b606854600160a01b900460ff166110605760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b8061106b8133611d8f565b8061107b575061107b8133612597565b80611093575061109361108d826118b2565b33612432565b6110e75760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b038416141561113a5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260726020526040902080546001600160a01b0319166001600160a01b038516908117909155829061116f826118b2565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60775481565b60765481565b6069546001600160a01b031681565b60715460609061121e5760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b607154829084820290600090828401111561124157506071548181039250611246565b508082015b606083604051908082528060200260200182016040528015611272578160200160208202803883390190505b5090506000835b838110156112dc576071818154811061128e57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106112b857fe5b6001600160a01b039092166020928302919091019091015260019182019101611279565b5090979650505050505050565b606b5481565b606a5481565b600160e11b630a85bd01025b949350505050565b606d5490565b611317611cef565b61132057600080fd5b606854600160a01b900460ff166113765760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113c8336125b8565b905060006113d5336125d2565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a342600183015580156114255761142533826126b7565b5050565b606854600160a01b900460ff1661147f5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826114898161192e565b6114d05760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816114db8133611d8f565b806114eb57506114eb8133612597565b806114fd57506114fd61108d826118b2565b6115515760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b0384166115a45760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6115b56115b086611c17565b6128cc565b60006115c0866125b8565b905060006115cd866125b8565b60018101548154919250906115e157825482555b6115ef878360000154612af8565b4281116116055760018084015490830155611622565b600183015461161c9042830363ffffffff612b7f16565b60018301555b42600184015561163186612b98565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611684611cef565b61168d57600080fd5b806116d45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607691909155607755565b606d5481565b61173a611cef565b61174357600080fd5b600061174e30612bd3565b90506000811161179e5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a781612c7a565b50565b6117b2611cef565b6117bb57600080fd5b806118025760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607491909155607555565b606854600160a01b900460ff1681565b611885838383604051806020016040528060008152506120e1565b505050565b6000611004826125d2565b61189d611cef565b6118a657600080fd5b611885606783836132b1565b60008181526070602052604081205482906001600160a01b03166119115760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152607060205260409020546001600160a01b031690565b6001600160a01b03166000908152606f6020526040902060010154421090565b60006001600160a01b0382166119a35760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6001600160a01b0382166000908152606f60205260409020600101546119ca5760006119cd565b60015b60ff1692915050565b606854600160a01b900460ff16611a2c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b80611a368161192e565b611a7d5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6118858383612cc4565b611a8f611cef565b611a9857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b611aea611cef565b611af357600080fd5b60008111611b4b5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5630612bd3565b905081811015611ba65760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61142582612c7a565b606c5481565b611bbd611cef565b611bc657600080fd5b60005b83811015611c1057611c08858583818110611be057fe5b905060200201356001600160a01b0316848484818110611bfc57fe5b90506020020135612fab565b600101611bc9565b5050505050565b600081611c238161192e565b611c6a5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000611c75846125b8565b905060004282600101540390506000606a548210611c965750606b54611cb7565b606a54606b54611cac908463ffffffff6130c116565b81611cb357fe5b0490505b607554607454611cce90839063ffffffff6130c116565b81611cd557fe5b049695505050505050565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60745481565b60715490565b6001600160a01b0381166000908152606f602052604081206001810154839190611d715760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090205490565b600091825260706020526040909120546001600160a01b0391821691161490565b611db8611cef565b611dc157600080fd5b6114258282612fab565b6068546001600160a01b031681565b611de2611cef565b611deb57600080fd5b80611df58161192e565b611e3c5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606f602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606854600160a01b900460ff16611eed5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415611f405760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526073602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611fb6611cef565b611fbf57600080fd5b606854600160a01b900460ff16156120215760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b6001600160a01b0381166000908152606f6020526040812060018101548391906120c05760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090206001015490565b606854600160a01b900460ff166121375760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b816121428133611d8f565b8061215257506121528133612597565b80612164575061216461108d826118b2565b6121b85760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6121c1836118b2565b6121ca8161192e565b6122115760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b61221c868686611429565b612228868686866130e8565b61227c5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b61228c611cef565b61229557600080fd5b606854600160a01b900460ff166122eb5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16068805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061234d575061234d613221565b8061235b575060015460ff16155b61239957604051600160e51b62461bcd02815260040180806020018281038252602e81526020018061334a602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606e5460ff1681565b60755481565b6001600160a01b03918216600090815260736020908152604080832093909416825291909152205460ff1690565b612468611cef565b61247157600080fd5b6117a781613227565b606854600160a01b900460ff166124d05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6117a7816000612cc4565b6124e3611cef565b6124ec57600080fd5b60005b828110156125245761251c84848381811061250657fe5b905060200201356001600160a01b031683612fab565b6001016124ef565b50505050565b6000818152607260205260408120546001600160a01b0316806110045760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260726020526040909120546001600160a01b0391821691161490565b6001600160a01b03166000908152606f6020526040902090565b6000816125de8161192e565b6126255760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000612630846125b8565b90506000428260010154039050606a54811061265057606b549350612671565b606a54606b54612666908363ffffffff6130c116565b8161266d57fe5b0493505b600060775461268d607654606b546130c190919063ffffffff16565b8161269457fe5b049050808511156126a95780850394506126ae565b600094505b50505050919050565b6068546001600160a01b0316612703576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156126fd573d6000803e3d6000fd5b50611425565b60685460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b15801561275857600080fd5b505afa15801561276c573d6000803e3d6000fd5b505050506040513d602081101561278257600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d602081101561280757600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b15801561285657600080fd5b505afa15801561286a573d6000803e3d6000fd5b505050506040513d602081101561288057600080fd5b5051116125245760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6068546001600160a01b031661292f578034101561292a5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a7565b60685460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b158015612a0a57600080fd5b505af1158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015612a8257600080fd5b505afa158015612a96573d6000803e3d6000fd5b505050506040513d6020811015612aac57600080fd5b5051116118855760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6000818152607060205260409020546001600160a01b038381169116146114255760718054600181019091557fa1fcd19bfe8c32a61095b6bfbb2664842857e148fcbb5188386c8cd40348d5b60180546001600160a01b0384166001600160a01b031991821681179092556000838152607060205260409020805490911690911790555050565b600082820183811015612b9157600080fd5b9392505050565b6000818152607260205260409020546001600160a01b0316156117a757600090815260726020526040902080546001600160a01b0319169055565b6068546000906001600160a01b0316612bf757506001600160a01b03811631610f36565b60685460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d6020811015612c7157600080fd5b50519050610f36565b612c8b612c85611ce0565b826126b7565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606d54606c5411612d1f5760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216612d725760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606b5460695460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d6040811015612df857600080fd5b50805160209091015190935091508080841115612e1757506000612e1c565b508281035b612e25816128cc565b6000612e30876125b8565b600181015490915042811015612e6657612e4982613296565b612e57888360000154612af8565b606a5442016001830155612e80565b606a54612e7a90829063ffffffff612b7f16565b60018301555b8515612ef65760695460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015612edd57600080fd5b505af1158015612ef1573d6000803e3d6000fd5b505050505b60695460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612f4e57600080fd5b505af1158015612f62573d6000803e3d6000fd5b5050606d546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216612ffe5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613009836125b8565b9050806001015482116130665760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b61306f81613296565b61307d838260000154612af8565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000826130d057506000611004565b828202828482816130dd57fe5b0414612b9157600080fd5b60006130fc846001600160a01b03166132ab565b61310857506001611301565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b8381101561318557818101518382015260200161316d565b50505050905090810190601f1680156131b25780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156131d457600080fd5b505af11580156131e8573d6000803e3d6000fd5b505050506040513d60208110156131fe57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b303b1590565b6001600160a01b03811661323a57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546117a757606d8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132f25782800160ff1982351617855561331f565b8280016001018555821561331f579182015b8281111561331f578235825591602001919060010190613304565b5061332b92915061332f565b5090565b610ff691905b8082111561332b576000815560010161333556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582090e2645e8f5c8a27b9aa3e516ad14db63bd34f8938f3f859e51115419dc428460029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.6", - "updatedAt": "2019-04-18T21:59:58.635Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV3.json b/packages/contracts/src/abis/PublicLock/PublicLockV3.json deleted file mode 100644 index a61c7ce123e..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV3.json +++ /dev/null @@ -1,1378 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_approved", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_page", - "type": "uint256" - }, - { - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_refundPenaltyNumerator", - "type": "uint256" - }, - { - "name": "_refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfKeysSold", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_transferFeeNumerator", - "type": "uint256" - }, - { - "name": "_transferFeeDenominator", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_a", - "type": "string" - }, - { - "name": "_b", - "type": "string" - }, - { - "name": "_c", - "type": "string" - }, - { - "name": "_d", - "type": "string" - } - ], - "name": "strConcat", - "outputs": [ - { - "name": "_concatenatedString", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "keyOwnerToNonce", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_i", - "type": "uint256" - } - ], - "name": "uint2Str", - "outputs": [ - { - "name": "_uintAsString", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "name": "address2Str", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "incrementNonce", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "purchaseForFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_amount", - "type": "uint256" - } - ], - "name": "partialWithdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_keyOwner", - "type": "address" - }, - { - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyOwner", - "type": "address" - }, - { - "name": "_signature", - "type": "bytes" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - } - ], - "name": "purchaseFor", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "name": "_lockName", - "type": "string" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldRefundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldRefundPenaltyDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldTransferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldTransferFeeDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeDenominator", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_sender", - "type": "address" - }, - { - "indexed": false, - "name": "_amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "bytecode": "0x6080604052600060755560646076556001607755600a6078553480156200002557600080fd5b50604051620049ab380380620049ab833981018060405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50509291905050508085848487620000db6301ffc9a760e01b6200030260201b60201c565b6001600160a01b03811615806200015957506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200012957600080fd5b505afa1580156200013e573d6000803e3d6000fd5b505050506040513d60208110156200015557600080fd5b5051115b620001c557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60678054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200027b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606880546001600160a01b03191633179055606992909255606a55606b558051620002ae90607090602084019062000488565b50620002c7635b5e139f60e01b6200030260201b60201c565b50620002e06380ac58cd60e01b6200030260201b60201c565b620002f6866200036f60201b62002ff81760201c565b5050505050506200052a565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200033257600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620003915750620003916200048160201b60201c565b80620003a0575060015460ff16155b620003f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806200497d602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004cb57805160ff1916838001178555620004fb565b82800160010185558215620004fb579182015b82811115620004fb578251825591602001919060010190620004de565b50620005099291506200050d565b5090565b6200048591905b8082111562000509576000815560010162000514565b614443806200053a6000396000f3fe6080604052600436106103ce5760003560e01c806370a08231116101fd5780639b3f0b1711610118578063c1c98d03116100ab578063d42cfc411161007a578063d42cfc411461136e578063e985e9c514611383578063f2fde38b146113be578063f6e4641f146113f1578063f8faf94214611417576103ce565b8063c1c98d03146112d0578063c4d66de8146112e5578063c87b56dd14611318578063d1bbd49c14611342576103ce565b8063a843a4e7116100e7578063a843a4e714611139578063abdf82ce1461114e578063b88d4fde14611181578063b8968bb414611245576103ce565b80639b3f0b171461107d5780639d76ea58146110b65780639f98d3cb146110cb578063a22cb465146110fe576103ce565b80638d0361fc1161019057806393fd18441161015f57806393fd184414610fe757806395d89b4114610ffc578063970aaeb714611011578063994a8a7114611044576103ce565b80638d0361fc14610f6d5780638da5cb5b14610fa85780638f32d59b14610fbd5780638f98ce8f14610fd2576103ce565b806374b6c106116101cc57806374b6c10614610ddf578063782a4ade14610df45780637c7c425314610e6f57806383cb0fa914610f3a576103ce565b806370a0823114610d3f57806370efb77014610d72578063715018a614610da057806371d2ee6c14610db5576103ce565b806330176e13116102ed5780634bc5a135116102805780635fdb97e11161024f5780635fdb97e114610c9a578063627cdcb914610ccd5780636352211e14610ce25780636d8ea5b414610d0c576103ce565b80634bc5a13514610b8f5780634c7a12a014610bc257806352d6a8e414610bec578063550ef3a814610c1f576103ce565b80633d3359cb116102bc5780633d3359cb146108d45780634136aa351461090457806342842e0e1461091957806345e965cd1461094f576103ce565b806330176e13146107ff57806339f469861461087a5780633ba70e31146108aa5780633ccfd60b146108bf576103ce565b806310803b721161036557806318160ddd1161033457806318160ddd146107755780631f1ec0291461078a5780632009dc65146107b457806323b872dd146107c9576103ce565b806310803b72146105dd57806310e569731461065d57806311a4c03a14610672578063150b7a0214610687576103ce565b8063095ea7b3116103a1578063095ea7b31461055e5780630c79130f1461058c5780630ed3e2cc146105b35780630f15023b146105c8576103ce565b806301ffc9a71461041c578063025e7c271461046457806306fdde03146104aa578063081812fc14610534575b3480156103da57600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561042857600080fd5b506104506004803603602081101561043f57600080fd5b50356001600160e01b031916611492565b604080519115158252519081900360200190f35b34801561047057600080fd5b5061048e6004803603602081101561048757600080fd5b50356114b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104b657600080fd5b506104bf6114dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104f95781810151838201526020016104e1565b50505050905090810190601f1680156105265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054057600080fd5b5061048e6004803603602081101561055757600080fd5b5035611573565b61058a6004803603604081101561057457600080fd5b506001600160a01b038135169060200135611584565b005b34801561059857600080fd5b506105a1611723565b60408051918252519081900360200190f35b3480156105bf57600080fd5b506105a1611729565b3480156105d457600080fd5b5061048e61172f565b3480156105e957600080fd5b5061060d6004803603604081101561060057600080fd5b508035906020013561173e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610649578181015183820152602001610631565b505050509050019250505060405180910390f35b34801561066957600080fd5b506105a1611863565b34801561067e57600080fd5b506105a1611869565b34801561069357600080fd5b50610758600480360360808110156106aa57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156106e457600080fd5b8201836020820111156106f657600080fd5b803590602001918460018302840111600160201b8311171561071757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061186f945050505050565b604080516001600160e01b03199092168252519081900360200190f35b34801561078157600080fd5b506105a1611883565b34801561079657600080fd5b5061058a600480360360208110156107ad57600080fd5b5035611889565b3480156107c057600080fd5b5061058a611937565b61058a600480360360608110156107df57600080fd5b506001600160a01b03813581169160208101359091169060400135611942565b34801561080b57600080fd5b5061058a6004803603602081101561082257600080fd5b810190602081018135600160201b81111561083c57600080fd5b82018360208201111561084e57600080fd5b803590602001918460018302840111600160201b8311171561086f57600080fd5b509092509050611ba4565b34801561088657600080fd5b5061058a6004803603604081101561089d57600080fd5b5080359060200135611bc6565b3480156108b657600080fd5b506105a1611c76565b3480156108cb57600080fd5b5061058a611c7c565b3480156108e057600080fd5b5061058a600480360360408110156108f757600080fd5b5080359060200135611cf4565b34801561091057600080fd5b50610450611da4565b61058a6004803603606081101561092f57600080fd5b506001600160a01b03813581169160208101359091169060400135611db4565b34801561095b57600080fd5b506104bf6004803603608081101561097257600080fd5b810190602081018135600160201b81111561098c57600080fd5b82018360208201111561099e57600080fd5b803590602001918460018302840111600160201b831117156109bf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1157600080fd5b820183602082011115610a2357600080fd5b803590602001918460018302840111600160201b83111715610a4457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a9657600080fd5b820183602082011115610aa857600080fd5b803590602001918460018302840111600160201b83111715610ac957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b1b57600080fd5b820183602082011115610b2d57600080fd5b803590602001918460018302840111600160201b83111715610b4e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611dcf945050505050565b348015610b9b57600080fd5b506105a160048036036020811015610bb257600080fd5b50356001600160a01b0316611f84565b348015610bce57600080fd5b506104bf60048036036020811015610be557600080fd5b5035611f96565b348015610bf857600080fd5b506105a160048036036020811015610c0f57600080fd5b50356001600160a01b031661205d565b348015610c2b57600080fd5b5061058a60048036036020811015610c4257600080fd5b810190602081018135600160201b811115610c5c57600080fd5b820183602082011115610c6e57600080fd5b803590602001918460018302840111600160201b83111715610c8f57600080fd5b509092509050612068565b348015610ca657600080fd5b506104bf60048036036020811015610cbd57600080fd5b50356001600160a01b0316612085565b348015610cd957600080fd5b5061058a61221d565b348015610cee57600080fd5b5061048e60048036036020811015610d0557600080fd5b5035612235565b348015610d1857600080fd5b5061045060048036036020811015610d2f57600080fd5b50356001600160a01b03166122b1565b348015610d4b57600080fd5b506105a160048036036020811015610d6257600080fd5b50356001600160a01b03166122d1565b61058a60048036036040811015610d8857600080fd5b506001600160a01b0381358116916020013516612346565b348015610dac57600080fd5b5061058a6123f7565b348015610dc157600080fd5b5061058a60048036036020811015610dd857600080fd5b5035612452565b348015610deb57600080fd5b506105a1612523565b348015610e0057600080fd5b5061058a60048036036020811015610e1757600080fd5b810190602081018135600160201b811115610e3157600080fd5b820183602082011115610e4357600080fd5b803590602001918460018302840111600160201b83111715610e6457600080fd5b509092509050612529565b348015610e7b57600080fd5b5061058a60048036036040811015610e9257600080fd5b810190602081018135600160201b811115610eac57600080fd5b820183602082011115610ebe57600080fd5b803590602001918460208302840111600160201b83111715610edf57600080fd5b919390929091602081019035600160201b811115610efc57600080fd5b820183602082011115610f0e57600080fd5b803590602001918460208302840111600160201b83111715610f2f57600080fd5b5090925090506125ab565b348015610f4657600080fd5b506105a160048036036020811015610f5d57600080fd5b50356001600160a01b031661260d565b348015610f7957600080fd5b506105a160048036036040811015610f9057600080fd5b506001600160a01b03813581169160200135166126d6565b348015610fb457600080fd5b5061048e61272d565b348015610fc957600080fd5b5061045061273c565b348015610fde57600080fd5b506105a161274d565b348015610ff357600080fd5b506105a1612753565b34801561100857600080fd5b506104bf612759565b34801561101d57600080fd5b506105a16004803603602081101561103457600080fd5b50356001600160a01b03166128e4565b34801561105057600080fd5b506104506004803603604081101561106757600080fd5b50803590602001356001600160a01b0316612954565b34801561108957600080fd5b5061058a600480360360408110156110a057600080fd5b506001600160a01b038135169060200135612975565b3480156110c257600080fd5b5061048e612990565b3480156110d757600080fd5b5061058a600480360360208110156110ee57600080fd5b50356001600160a01b031661299f565b34801561110a57600080fd5b5061058a6004803603604081101561112157600080fd5b506001600160a01b0381351690602001351515612a5c565b34801561114557600080fd5b5061058a612b73565b34801561115a57600080fd5b506105a16004803603602081101561117157600080fd5b50356001600160a01b0316612c32565b61058a6004803603608081101561119757600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111d157600080fd5b8201836020820111156111e357600080fd5b803590602001918460018302840111600160201b8311171561120457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612cc4945050505050565b34801561125157600080fd5b5061058a6004803603604081101561126857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561129257600080fd5b8201836020820111156112a457600080fd5b803590602001918460018302840111600160201b831117156112c557600080fd5b509092509050612e67565b3480156112dc57600080fd5b5061058a612f48565b3480156112f157600080fd5b5061058a6004803603602081101561130857600080fd5b50356001600160a01b0316612ff8565b34801561132457600080fd5b506104bf6004803603602081101561133b57600080fd5b50356130e7565b34801561134e57600080fd5b50611357613308565b6040805161ffff9092168252519081900360200190f35b34801561137a57600080fd5b506105a161330d565b34801561138f57600080fd5b50610450600480360360408110156113a657600080fd5b506001600160a01b0381358116916020013516613313565b3480156113ca57600080fd5b5061058a600480360360208110156113e157600080fd5b50356001600160a01b0316613341565b61058a6004803603602081101561140757600080fd5b50356001600160a01b031661335b565b34801561142357600080fd5b5061058a6004803603604081101561143a57600080fd5b810190602081018135600160201b81111561145457600080fd5b82018360208201111561146657600080fd5b803590602001918460208302840111600160201b8311171561148757600080fd5b9193509150356133bc565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b606f81815481106114c257fe5b6000918252602090912001546001600160a01b0316905081565b60708054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115685780601f1061153d57610100808354040283529160200191611568565b820191906000526020600020905b81548152906001019060200180831161154b57829003601f168201915b505050505090505b90565b600061157e8261340b565b92915050565b606754600160a01b900460ff166115da5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806115e58133612954565b806115f557506115f58133613478565b8061160d575061160d61160782612235565b33613313565b6116615760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b03841614156116b45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260736020526040902080546001600160a01b0319166001600160a01b03851690811790915582906116e982612235565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60785481565b60775481565b6068546001600160a01b031681565b606f546060906117985760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b606f5482908482029060009082840111156117bb5750606f5481810392506117c0565b508082015b6060836040519080825280602002602001820160405280156117ec578160200160208202803883390190505b5090506000835b8381101561185657606f818154811061180857fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061183257fe5b6001600160a01b0390921660209283029190910190910152600191820191016117f3565b5090979650505050505050565b606a5481565b60695481565b600160e11b630a85bd01025b949350505050565b606c5490565b61189161273c565b61189a57600080fd5b606754600160a01b900460ff166118f05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b61194033613499565b565b606754600160a01b900460ff166119985760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826119a2816122b1565b6119e95760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816119f48133612954565b80611a045750611a048133613478565b80611a165750611a1661160782612235565b611a6a5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b038416611abd5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b611ace611ac98661260d565b61350e565b6000611ad986613740565b90506000611ae686613740565b6001810154815491925090611b05578254808355611b0590889061375a565b428111611b29576001808401549083015582548255611b24878761375a565b611b46565b6001830154611b409042830363ffffffff6137e116565b60018301555b42600184015560008355611b59866137fa565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611bac61273c565b611bb557600080fd5b611bc160728383614351565b505050565b611bce61273c565b611bd757600080fd5b80611c1e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60775460785460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607791909155607855565b606c5481565b611c8461273c565b611c8d57600080fd5b6000611c9830613835565b905060008111611ce85760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1816138dc565b50565b611cfc61273c565b611d0557600080fd5b80611d4c5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60755460765460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607591909155607655565b606754600160a01b900460ff1681565b611bc183838360405180602001604052806000815250612cc4565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015611e1b576020820181803883390190505b509050806000805b8751811015611e7457878181518110611e3857fe5b602001015160f81c60f81b838380600101945081518110611e5557fe5b60200101906001600160f81b031916908160001a905350600101611e23565b5060005b8651811015611ec957868181518110611e8d57fe5b602001015160f81c60f81b838380600101945081518110611eaa57fe5b60200101906001600160f81b031916908160001a905350600101611e78565b5060005b8551811015611f1e57858181518110611ee257fe5b602001015160f81c60f81b838380600101945081518110611eff57fe5b60200101906001600160f81b031916908160001a905350600101611ecd565b5060005b8451811015611f7357848181518110611f3757fe5b602001015160f81c60f81b838380600101945081518110611f5457fe5b60200101906001600160f81b031916908160001a905350600101611f22565b50909b9a5050505050505050505050565b60796020526000908152604090205481565b60608180611fc05750506040805180820190915260018152600160fc1b60030260208201526114b0565b8260005b8115611fd857600101600a82049150611fc4565b6060816040519080825280601f01601f191660200182016040528015612005576020820181803883390190505b50905060001982015b841561205357600a850660300160f81b8282806001900393508151811061203157fe5b60200101906001600160f81b031916908160001a905350600a8504945061200e565b5095945050505050565b600061157e82613926565b61207061273c565b61207957600080fd5b611bc160708383614351565b604080518082018252601081527f303132333435363738396162636465660000000000000000000000000000000060208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600160fc1b600302816000815181106120f957fe5b60200101906001600160f81b031916908160001a905350600160fb1b600f028160018151811061212557fe5b60200101906001600160f81b031916908160001a90535060005b6014811015612214578260048583600c016020811061215a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061217a57fe5b602001015160f81c60f81b82826002026002018151811061219757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106121be57fe5b1a60f81b600f60f81b1660f81c60ff16815181106121d857fe5b602001015160f81c60f81b8282600202600301815181106121f557fe5b60200101906001600160f81b031916908160001a90535060010161213f565b50949350505050565b33600090815260796020526040902080546001019055565b6000818152606e602052604081205482906001600160a01b03166122945760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152606e60205260409020546001600160a01b031690565b6001600160a01b03166000908152606d6020526040902060010154421090565b60006001600160a01b0382166123265760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b61232f826122b1565b61233a57600061233d565b60015b60ff1692915050565b606754600160a01b900460ff1661239c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806123a6816122b1565b6123ed5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b611bc18383613a0b565b6123ff61273c565b61240857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b61245a61273c565b61246357600080fd5b600081116124bb5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b60006124c630613835565b9050818110156125165760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61251f826138dc565b5050565b606b5481565b61253161273c565b61253a57600080fd5b61254660718383614351565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125b361273c565b6125bc57600080fd5b60005b83811015612606576125fe8585838181106125d657fe5b905060200201356001600160a01b03168484848181106125f257fe5b90506020020135613cf1565b6001016125bf565b5050505050565b600081612619816122b1565b6126605760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061266b84613740565b905060004282600101540390506000606954821061268c5750606a546126ad565b606954606a546126a2908463ffffffff613e0716565b816126a957fe5b0490505b6076546075546126c490839063ffffffff613e0716565b816126cb57fe5b049695505050505050565b6001600160a01b0391821660009081526079602090815260409182902054825130606090811b8285015260348201929092529390941690931b60548301528051808303604801815260689092019052805191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60755481565b606f5490565b6071546060906002600019610100600184161502019091160461285257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156127c457600080fd5b505afa1580156127d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561280157600080fd5b810190808051600160201b81111561281857600080fd5b8201602081018481111561282b57600080fd5b8151600160201b81118282018710171561284457600080fd5b509094506115709350505050565b6071805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156128d85780601f106128ad576101008083540402835291602001916128d8565b820191906000526020600020905b8154815290600101906020018083116128bb57829003601f168201915b50505050509050611570565b6000816128f0816122b1565b6129375760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090205490565b6000918252606e6020526040909120546001600160a01b0391821691161490565b61297d61273c565b61298657600080fd5b61251f8282613cf1565b6067546001600160a01b031681565b6129a761273c565b6129b057600080fd5b806129ba816122b1565b612a015760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606d602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ab25760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415612b055760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526074602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612b7b61273c565b612b8457600080fd5b606754600160a01b900460ff1615612be65760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612c2f33612c2a30613835565b613e2e565b33ff5b6001600160a01b0381166000908152606d60205260408120600101548290612ca45760408051600160e51b62461bcd02815260206004820152601360248201527f4841535f4e455645525f4f574e45445f4b455900000000000000000000000000604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090206001015490565b606754600160a01b900460ff16612d1a5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b81612d258133612954565b80612d355750612d358133613478565b80612d475750612d4761160782612235565b612d9b5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b612da483612235565b612dad816122b1565b612df45760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b612dff868686611942565b612e0b86868686614049565b612e5f5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612ec2612e86612e8186336126d6565b614182565b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141d392505050565b6001600160a01b031614612f205760408051600160e51b62461bcd02815260206004820152601160248201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038316600090815260796020526040902080546001019055611bc183613499565b612f5061273c565b612f5957600080fd5b606754600160a01b900460ff16612faf5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061301157506130116142c1565b8061301f575060015460ff16155b61305d57604051600160e51b62461bcd02815260040180806020018281038252602e8152602001806143ea602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b6000818152606e602052604090205460609082906001600160a01b03166131495760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b6072546060906002600019610100600184161502019091160461324257606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b1580156131b457600080fd5b505afa1580156131c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156131f157600080fd5b810190808051600160201b81111561320857600080fd5b8201602081018481111561321b57600080fd5b8151600160201b81118282018710171561323457600080fd5b509094506132d09350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156132c85780601f1061329d576101008083540402835291602001916132c8565b820191906000526020600020905b8154815290600101906020018083116132ab57829003601f168201915b505050505090505b61187b816132dd30612085565b604051806040016040528060018152602001600160f81b602f0281525061330388611f96565b611dcf565b600390565b60765481565b6001600160a01b03918216600090815260746020908152604080832093909416825291909152205460ff1690565b61334961273c565b61335257600080fd5b611cf1816142c7565b606754600160a01b900460ff166133b15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b611cf1816000613a0b565b6133c461273c565b6133cd57600080fd5b60005b82811015613405576133fd8484838181106133e757fe5b905060200201356001600160a01b031683613cf1565b6001016133d0565b50505050565b6000818152607360205260408120546001600160a01b03168061157e5760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260736020526040909120546001600160a01b0391821691161490565b60006134a482613740565b905060006134b183613926565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611bc157611bc13382613e2e565b8015611cf1576067546001600160a01b031661357757803410156135725760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1565b60675460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156135ca57600080fd5b505afa1580156135de573d6000803e3d6000fd5b505050506040513d60208110156135f457600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561365257600080fd5b505af1158015613666573d6000803e3d6000fd5b505050506040513d602081101561367c57600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156136ca57600080fd5b505afa1580156136de573d6000803e3d6000fd5b505050506040513d60208110156136f457600080fd5b505111611bc15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6001600160a01b03166000908152606d6020526040902090565b6000818152606e60205260409020546001600160a01b0383811691161461251f57606f8054600181019091557f39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e127110180546001600160a01b0384166001600160a01b031991821681179092556000838152606e60205260409020805490911690911790555050565b6000828201838110156137f357600080fd5b9392505050565b6000818152607360205260409020546001600160a01b031615611cf157600090815260736020526040902080546001600160a01b0319169055565b6067546000906001600160a01b031661385957506001600160a01b038116316114b0565b60675460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156138a957600080fd5b505afa1580156138bd573d6000803e3d6000fd5b505050506040513d60208110156138d357600080fd5b505190506114b0565b6138ed6138e761272d565b82613e2e565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600081613932816122b1565b6139795760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061398484613740565b9050600042826001015403905060695481106139a457606a5493506139c5565b606954606a546139ba908363ffffffff613e0716565b816139c157fe5b0493505b60006078546139e1607754606a54613e0790919063ffffffff16565b816139e857fe5b049050808511156139fd578085039450613a02565b600094505b50505050919050565b606c54606b5411613a665760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216613ab95760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606a5460685460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613b1557600080fd5b505afa158015613b29573d6000803e3d6000fd5b505050506040513d6040811015613b3f57600080fd5b50805160209091015190935091508080841115613b5e57506000613b63565b508281035b613b6c8161350e565b6000613b7787613740565b6001810154815491925090613bac57613b8f82614336565b613b9d88836000015461375a565b60695442016001830155613bc6565b606954613bc090829063ffffffff6137e116565b60018301555b8515613c3c5760685460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613c2357600080fd5b505af1158015613c37573d6000803e3d6000fd5b505050505b60685460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613c9457600080fd5b505af1158015613ca8573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216613d445760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613d4f83613740565b905080600101548211613dac5760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b613db581614336565b613dc383826000015461375a565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082613e165750600061157e565b82820282848281613e2357fe5b04146137f357600080fd5b801561251f576067546001600160a01b0316613e80576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015613e7a573d6000803e3d6000fd5b5061251f565b60675460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613ed557600080fd5b505afa158015613ee9573d6000803e3d6000fd5b505050506040513d6020811015613eff57600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613f5a57600080fd5b505af1158015613f6e573d6000803e3d6000fd5b505050506040513d6020811015613f8457600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6020811015613ffd57600080fd5b5051116134055760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b600061405d846001600160a01b031661434b565b6140695750600161187b565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b838110156140e65781810151838201526020016140ce565b50505050905090810190601f1680156141135780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561413557600080fd5b505af1158015614149573d6000803e3d6000fd5b505050506040513d602081101561415f57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b600081516041146141e65750600061157e565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561422c576000935050505061157e565b8060ff16601b1415801561424457508060ff16601c14155b15614255576000935050505061157e565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142ac573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b0381166142da57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b8054611cf157606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143925782800160ff198235161785556143bf565b828001600101855582156143bf579182015b828111156143bf5782358255916020019190600101906143a4565b506143cb9291506143cf565b5090565b61157091905b808211156143cb57600081556001016143d556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582031474d01281aa90a56dde5554eed5c93cdafcfbf9c58bfb981584096593435520029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564", - "deployedBytecode": "0x6080604052600436106103ce5760003560e01c806370a08231116101fd5780639b3f0b1711610118578063c1c98d03116100ab578063d42cfc411161007a578063d42cfc411461136e578063e985e9c514611383578063f2fde38b146113be578063f6e4641f146113f1578063f8faf94214611417576103ce565b8063c1c98d03146112d0578063c4d66de8146112e5578063c87b56dd14611318578063d1bbd49c14611342576103ce565b8063a843a4e7116100e7578063a843a4e714611139578063abdf82ce1461114e578063b88d4fde14611181578063b8968bb414611245576103ce565b80639b3f0b171461107d5780639d76ea58146110b65780639f98d3cb146110cb578063a22cb465146110fe576103ce565b80638d0361fc1161019057806393fd18441161015f57806393fd184414610fe757806395d89b4114610ffc578063970aaeb714611011578063994a8a7114611044576103ce565b80638d0361fc14610f6d5780638da5cb5b14610fa85780638f32d59b14610fbd5780638f98ce8f14610fd2576103ce565b806374b6c106116101cc57806374b6c10614610ddf578063782a4ade14610df45780637c7c425314610e6f57806383cb0fa914610f3a576103ce565b806370a0823114610d3f57806370efb77014610d72578063715018a614610da057806371d2ee6c14610db5576103ce565b806330176e13116102ed5780634bc5a135116102805780635fdb97e11161024f5780635fdb97e114610c9a578063627cdcb914610ccd5780636352211e14610ce25780636d8ea5b414610d0c576103ce565b80634bc5a13514610b8f5780634c7a12a014610bc257806352d6a8e414610bec578063550ef3a814610c1f576103ce565b80633d3359cb116102bc5780633d3359cb146108d45780634136aa351461090457806342842e0e1461091957806345e965cd1461094f576103ce565b806330176e13146107ff57806339f469861461087a5780633ba70e31146108aa5780633ccfd60b146108bf576103ce565b806310803b721161036557806318160ddd1161033457806318160ddd146107755780631f1ec0291461078a5780632009dc65146107b457806323b872dd146107c9576103ce565b806310803b72146105dd57806310e569731461065d57806311a4c03a14610672578063150b7a0214610687576103ce565b8063095ea7b3116103a1578063095ea7b31461055e5780630c79130f1461058c5780630ed3e2cc146105b35780630f15023b146105c8576103ce565b806301ffc9a71461041c578063025e7c271461046457806306fdde03146104aa578063081812fc14610534575b3480156103da57600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561042857600080fd5b506104506004803603602081101561043f57600080fd5b50356001600160e01b031916611492565b604080519115158252519081900360200190f35b34801561047057600080fd5b5061048e6004803603602081101561048757600080fd5b50356114b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104b657600080fd5b506104bf6114dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104f95781810151838201526020016104e1565b50505050905090810190601f1680156105265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054057600080fd5b5061048e6004803603602081101561055757600080fd5b5035611573565b61058a6004803603604081101561057457600080fd5b506001600160a01b038135169060200135611584565b005b34801561059857600080fd5b506105a1611723565b60408051918252519081900360200190f35b3480156105bf57600080fd5b506105a1611729565b3480156105d457600080fd5b5061048e61172f565b3480156105e957600080fd5b5061060d6004803603604081101561060057600080fd5b508035906020013561173e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610649578181015183820152602001610631565b505050509050019250505060405180910390f35b34801561066957600080fd5b506105a1611863565b34801561067e57600080fd5b506105a1611869565b34801561069357600080fd5b50610758600480360360808110156106aa57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156106e457600080fd5b8201836020820111156106f657600080fd5b803590602001918460018302840111600160201b8311171561071757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061186f945050505050565b604080516001600160e01b03199092168252519081900360200190f35b34801561078157600080fd5b506105a1611883565b34801561079657600080fd5b5061058a600480360360208110156107ad57600080fd5b5035611889565b3480156107c057600080fd5b5061058a611937565b61058a600480360360608110156107df57600080fd5b506001600160a01b03813581169160208101359091169060400135611942565b34801561080b57600080fd5b5061058a6004803603602081101561082257600080fd5b810190602081018135600160201b81111561083c57600080fd5b82018360208201111561084e57600080fd5b803590602001918460018302840111600160201b8311171561086f57600080fd5b509092509050611ba4565b34801561088657600080fd5b5061058a6004803603604081101561089d57600080fd5b5080359060200135611bc6565b3480156108b657600080fd5b506105a1611c76565b3480156108cb57600080fd5b5061058a611c7c565b3480156108e057600080fd5b5061058a600480360360408110156108f757600080fd5b5080359060200135611cf4565b34801561091057600080fd5b50610450611da4565b61058a6004803603606081101561092f57600080fd5b506001600160a01b03813581169160208101359091169060400135611db4565b34801561095b57600080fd5b506104bf6004803603608081101561097257600080fd5b810190602081018135600160201b81111561098c57600080fd5b82018360208201111561099e57600080fd5b803590602001918460018302840111600160201b831117156109bf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1157600080fd5b820183602082011115610a2357600080fd5b803590602001918460018302840111600160201b83111715610a4457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a9657600080fd5b820183602082011115610aa857600080fd5b803590602001918460018302840111600160201b83111715610ac957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b1b57600080fd5b820183602082011115610b2d57600080fd5b803590602001918460018302840111600160201b83111715610b4e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611dcf945050505050565b348015610b9b57600080fd5b506105a160048036036020811015610bb257600080fd5b50356001600160a01b0316611f84565b348015610bce57600080fd5b506104bf60048036036020811015610be557600080fd5b5035611f96565b348015610bf857600080fd5b506105a160048036036020811015610c0f57600080fd5b50356001600160a01b031661205d565b348015610c2b57600080fd5b5061058a60048036036020811015610c4257600080fd5b810190602081018135600160201b811115610c5c57600080fd5b820183602082011115610c6e57600080fd5b803590602001918460018302840111600160201b83111715610c8f57600080fd5b509092509050612068565b348015610ca657600080fd5b506104bf60048036036020811015610cbd57600080fd5b50356001600160a01b0316612085565b348015610cd957600080fd5b5061058a61221d565b348015610cee57600080fd5b5061048e60048036036020811015610d0557600080fd5b5035612235565b348015610d1857600080fd5b5061045060048036036020811015610d2f57600080fd5b50356001600160a01b03166122b1565b348015610d4b57600080fd5b506105a160048036036020811015610d6257600080fd5b50356001600160a01b03166122d1565b61058a60048036036040811015610d8857600080fd5b506001600160a01b0381358116916020013516612346565b348015610dac57600080fd5b5061058a6123f7565b348015610dc157600080fd5b5061058a60048036036020811015610dd857600080fd5b5035612452565b348015610deb57600080fd5b506105a1612523565b348015610e0057600080fd5b5061058a60048036036020811015610e1757600080fd5b810190602081018135600160201b811115610e3157600080fd5b820183602082011115610e4357600080fd5b803590602001918460018302840111600160201b83111715610e6457600080fd5b509092509050612529565b348015610e7b57600080fd5b5061058a60048036036040811015610e9257600080fd5b810190602081018135600160201b811115610eac57600080fd5b820183602082011115610ebe57600080fd5b803590602001918460208302840111600160201b83111715610edf57600080fd5b919390929091602081019035600160201b811115610efc57600080fd5b820183602082011115610f0e57600080fd5b803590602001918460208302840111600160201b83111715610f2f57600080fd5b5090925090506125ab565b348015610f4657600080fd5b506105a160048036036020811015610f5d57600080fd5b50356001600160a01b031661260d565b348015610f7957600080fd5b506105a160048036036040811015610f9057600080fd5b506001600160a01b03813581169160200135166126d6565b348015610fb457600080fd5b5061048e61272d565b348015610fc957600080fd5b5061045061273c565b348015610fde57600080fd5b506105a161274d565b348015610ff357600080fd5b506105a1612753565b34801561100857600080fd5b506104bf612759565b34801561101d57600080fd5b506105a16004803603602081101561103457600080fd5b50356001600160a01b03166128e4565b34801561105057600080fd5b506104506004803603604081101561106757600080fd5b50803590602001356001600160a01b0316612954565b34801561108957600080fd5b5061058a600480360360408110156110a057600080fd5b506001600160a01b038135169060200135612975565b3480156110c257600080fd5b5061048e612990565b3480156110d757600080fd5b5061058a600480360360208110156110ee57600080fd5b50356001600160a01b031661299f565b34801561110a57600080fd5b5061058a6004803603604081101561112157600080fd5b506001600160a01b0381351690602001351515612a5c565b34801561114557600080fd5b5061058a612b73565b34801561115a57600080fd5b506105a16004803603602081101561117157600080fd5b50356001600160a01b0316612c32565b61058a6004803603608081101561119757600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111d157600080fd5b8201836020820111156111e357600080fd5b803590602001918460018302840111600160201b8311171561120457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612cc4945050505050565b34801561125157600080fd5b5061058a6004803603604081101561126857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561129257600080fd5b8201836020820111156112a457600080fd5b803590602001918460018302840111600160201b831117156112c557600080fd5b509092509050612e67565b3480156112dc57600080fd5b5061058a612f48565b3480156112f157600080fd5b5061058a6004803603602081101561130857600080fd5b50356001600160a01b0316612ff8565b34801561132457600080fd5b506104bf6004803603602081101561133b57600080fd5b50356130e7565b34801561134e57600080fd5b50611357613308565b6040805161ffff9092168252519081900360200190f35b34801561137a57600080fd5b506105a161330d565b34801561138f57600080fd5b50610450600480360360408110156113a657600080fd5b506001600160a01b0381358116916020013516613313565b3480156113ca57600080fd5b5061058a600480360360208110156113e157600080fd5b50356001600160a01b0316613341565b61058a6004803603602081101561140757600080fd5b50356001600160a01b031661335b565b34801561142357600080fd5b5061058a6004803603604081101561143a57600080fd5b810190602081018135600160201b81111561145457600080fd5b82018360208201111561146657600080fd5b803590602001918460208302840111600160201b8311171561148757600080fd5b9193509150356133bc565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b606f81815481106114c257fe5b6000918252602090912001546001600160a01b0316905081565b60708054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115685780601f1061153d57610100808354040283529160200191611568565b820191906000526020600020905b81548152906001019060200180831161154b57829003601f168201915b505050505090505b90565b600061157e8261340b565b92915050565b606754600160a01b900460ff166115da5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806115e58133612954565b806115f557506115f58133613478565b8061160d575061160d61160782612235565b33613313565b6116615760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b03841614156116b45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260736020526040902080546001600160a01b0319166001600160a01b03851690811790915582906116e982612235565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60785481565b60775481565b6068546001600160a01b031681565b606f546060906117985760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b606f5482908482029060009082840111156117bb5750606f5481810392506117c0565b508082015b6060836040519080825280602002602001820160405280156117ec578160200160208202803883390190505b5090506000835b8381101561185657606f818154811061180857fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061183257fe5b6001600160a01b0390921660209283029190910190910152600191820191016117f3565b5090979650505050505050565b606a5481565b60695481565b600160e11b630a85bd01025b949350505050565b606c5490565b61189161273c565b61189a57600080fd5b606754600160a01b900460ff166118f05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b61194033613499565b565b606754600160a01b900460ff166119985760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826119a2816122b1565b6119e95760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816119f48133612954565b80611a045750611a048133613478565b80611a165750611a1661160782612235565b611a6a5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b038416611abd5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b611ace611ac98661260d565b61350e565b6000611ad986613740565b90506000611ae686613740565b6001810154815491925090611b05578254808355611b0590889061375a565b428111611b29576001808401549083015582548255611b24878761375a565b611b46565b6001830154611b409042830363ffffffff6137e116565b60018301555b42600184015560008355611b59866137fa565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611bac61273c565b611bb557600080fd5b611bc160728383614351565b505050565b611bce61273c565b611bd757600080fd5b80611c1e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60775460785460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607791909155607855565b606c5481565b611c8461273c565b611c8d57600080fd5b6000611c9830613835565b905060008111611ce85760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1816138dc565b50565b611cfc61273c565b611d0557600080fd5b80611d4c5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60755460765460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607591909155607655565b606754600160a01b900460ff1681565b611bc183838360405180602001604052806000815250612cc4565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015611e1b576020820181803883390190505b509050806000805b8751811015611e7457878181518110611e3857fe5b602001015160f81c60f81b838380600101945081518110611e5557fe5b60200101906001600160f81b031916908160001a905350600101611e23565b5060005b8651811015611ec957868181518110611e8d57fe5b602001015160f81c60f81b838380600101945081518110611eaa57fe5b60200101906001600160f81b031916908160001a905350600101611e78565b5060005b8551811015611f1e57858181518110611ee257fe5b602001015160f81c60f81b838380600101945081518110611eff57fe5b60200101906001600160f81b031916908160001a905350600101611ecd565b5060005b8451811015611f7357848181518110611f3757fe5b602001015160f81c60f81b838380600101945081518110611f5457fe5b60200101906001600160f81b031916908160001a905350600101611f22565b50909b9a5050505050505050505050565b60796020526000908152604090205481565b60608180611fc05750506040805180820190915260018152600160fc1b60030260208201526114b0565b8260005b8115611fd857600101600a82049150611fc4565b6060816040519080825280601f01601f191660200182016040528015612005576020820181803883390190505b50905060001982015b841561205357600a850660300160f81b8282806001900393508151811061203157fe5b60200101906001600160f81b031916908160001a905350600a8504945061200e565b5095945050505050565b600061157e82613926565b61207061273c565b61207957600080fd5b611bc160708383614351565b604080518082018252601081527f303132333435363738396162636465660000000000000000000000000000000060208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600160fc1b600302816000815181106120f957fe5b60200101906001600160f81b031916908160001a905350600160fb1b600f028160018151811061212557fe5b60200101906001600160f81b031916908160001a90535060005b6014811015612214578260048583600c016020811061215a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061217a57fe5b602001015160f81c60f81b82826002026002018151811061219757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106121be57fe5b1a60f81b600f60f81b1660f81c60ff16815181106121d857fe5b602001015160f81c60f81b8282600202600301815181106121f557fe5b60200101906001600160f81b031916908160001a90535060010161213f565b50949350505050565b33600090815260796020526040902080546001019055565b6000818152606e602052604081205482906001600160a01b03166122945760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152606e60205260409020546001600160a01b031690565b6001600160a01b03166000908152606d6020526040902060010154421090565b60006001600160a01b0382166123265760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b61232f826122b1565b61233a57600061233d565b60015b60ff1692915050565b606754600160a01b900460ff1661239c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806123a6816122b1565b6123ed5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b611bc18383613a0b565b6123ff61273c565b61240857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b61245a61273c565b61246357600080fd5b600081116124bb5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b60006124c630613835565b9050818110156125165760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61251f826138dc565b5050565b606b5481565b61253161273c565b61253a57600080fd5b61254660718383614351565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125b361273c565b6125bc57600080fd5b60005b83811015612606576125fe8585838181106125d657fe5b905060200201356001600160a01b03168484848181106125f257fe5b90506020020135613cf1565b6001016125bf565b5050505050565b600081612619816122b1565b6126605760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061266b84613740565b905060004282600101540390506000606954821061268c5750606a546126ad565b606954606a546126a2908463ffffffff613e0716565b816126a957fe5b0490505b6076546075546126c490839063ffffffff613e0716565b816126cb57fe5b049695505050505050565b6001600160a01b0391821660009081526079602090815260409182902054825130606090811b8285015260348201929092529390941690931b60548301528051808303604801815260689092019052805191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60755481565b606f5490565b6071546060906002600019610100600184161502019091160461285257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156127c457600080fd5b505afa1580156127d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561280157600080fd5b810190808051600160201b81111561281857600080fd5b8201602081018481111561282b57600080fd5b8151600160201b81118282018710171561284457600080fd5b509094506115709350505050565b6071805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156128d85780601f106128ad576101008083540402835291602001916128d8565b820191906000526020600020905b8154815290600101906020018083116128bb57829003601f168201915b50505050509050611570565b6000816128f0816122b1565b6129375760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090205490565b6000918252606e6020526040909120546001600160a01b0391821691161490565b61297d61273c565b61298657600080fd5b61251f8282613cf1565b6067546001600160a01b031681565b6129a761273c565b6129b057600080fd5b806129ba816122b1565b612a015760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606d602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ab25760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415612b055760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526074602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612b7b61273c565b612b8457600080fd5b606754600160a01b900460ff1615612be65760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612c2f33612c2a30613835565b613e2e565b33ff5b6001600160a01b0381166000908152606d60205260408120600101548290612ca45760408051600160e51b62461bcd02815260206004820152601360248201527f4841535f4e455645525f4f574e45445f4b455900000000000000000000000000604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090206001015490565b606754600160a01b900460ff16612d1a5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b81612d258133612954565b80612d355750612d358133613478565b80612d475750612d4761160782612235565b612d9b5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b612da483612235565b612dad816122b1565b612df45760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b612dff868686611942565b612e0b86868686614049565b612e5f5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612ec2612e86612e8186336126d6565b614182565b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141d392505050565b6001600160a01b031614612f205760408051600160e51b62461bcd02815260206004820152601160248201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038316600090815260796020526040902080546001019055611bc183613499565b612f5061273c565b612f5957600080fd5b606754600160a01b900460ff16612faf5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061301157506130116142c1565b8061301f575060015460ff16155b61305d57604051600160e51b62461bcd02815260040180806020018281038252602e8152602001806143ea602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b6000818152606e602052604090205460609082906001600160a01b03166131495760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b6072546060906002600019610100600184161502019091160461324257606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b1580156131b457600080fd5b505afa1580156131c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156131f157600080fd5b810190808051600160201b81111561320857600080fd5b8201602081018481111561321b57600080fd5b8151600160201b81118282018710171561323457600080fd5b509094506132d09350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156132c85780601f1061329d576101008083540402835291602001916132c8565b820191906000526020600020905b8154815290600101906020018083116132ab57829003601f168201915b505050505090505b61187b816132dd30612085565b604051806040016040528060018152602001600160f81b602f0281525061330388611f96565b611dcf565b600390565b60765481565b6001600160a01b03918216600090815260746020908152604080832093909416825291909152205460ff1690565b61334961273c565b61335257600080fd5b611cf1816142c7565b606754600160a01b900460ff166133b15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b611cf1816000613a0b565b6133c461273c565b6133cd57600080fd5b60005b82811015613405576133fd8484838181106133e757fe5b905060200201356001600160a01b031683613cf1565b6001016133d0565b50505050565b6000818152607360205260408120546001600160a01b03168061157e5760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260736020526040909120546001600160a01b0391821691161490565b60006134a482613740565b905060006134b183613926565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611bc157611bc13382613e2e565b8015611cf1576067546001600160a01b031661357757803410156135725760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1565b60675460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156135ca57600080fd5b505afa1580156135de573d6000803e3d6000fd5b505050506040513d60208110156135f457600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561365257600080fd5b505af1158015613666573d6000803e3d6000fd5b505050506040513d602081101561367c57600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156136ca57600080fd5b505afa1580156136de573d6000803e3d6000fd5b505050506040513d60208110156136f457600080fd5b505111611bc15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6001600160a01b03166000908152606d6020526040902090565b6000818152606e60205260409020546001600160a01b0383811691161461251f57606f8054600181019091557f39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e127110180546001600160a01b0384166001600160a01b031991821681179092556000838152606e60205260409020805490911690911790555050565b6000828201838110156137f357600080fd5b9392505050565b6000818152607360205260409020546001600160a01b031615611cf157600090815260736020526040902080546001600160a01b0319169055565b6067546000906001600160a01b031661385957506001600160a01b038116316114b0565b60675460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156138a957600080fd5b505afa1580156138bd573d6000803e3d6000fd5b505050506040513d60208110156138d357600080fd5b505190506114b0565b6138ed6138e761272d565b82613e2e565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600081613932816122b1565b6139795760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061398484613740565b9050600042826001015403905060695481106139a457606a5493506139c5565b606954606a546139ba908363ffffffff613e0716565b816139c157fe5b0493505b60006078546139e1607754606a54613e0790919063ffffffff16565b816139e857fe5b049050808511156139fd578085039450613a02565b600094505b50505050919050565b606c54606b5411613a665760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216613ab95760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606a5460685460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613b1557600080fd5b505afa158015613b29573d6000803e3d6000fd5b505050506040513d6040811015613b3f57600080fd5b50805160209091015190935091508080841115613b5e57506000613b63565b508281035b613b6c8161350e565b6000613b7787613740565b6001810154815491925090613bac57613b8f82614336565b613b9d88836000015461375a565b60695442016001830155613bc6565b606954613bc090829063ffffffff6137e116565b60018301555b8515613c3c5760685460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613c2357600080fd5b505af1158015613c37573d6000803e3d6000fd5b505050505b60685460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613c9457600080fd5b505af1158015613ca8573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216613d445760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613d4f83613740565b905080600101548211613dac5760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b613db581614336565b613dc383826000015461375a565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082613e165750600061157e565b82820282848281613e2357fe5b04146137f357600080fd5b801561251f576067546001600160a01b0316613e80576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015613e7a573d6000803e3d6000fd5b5061251f565b60675460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613ed557600080fd5b505afa158015613ee9573d6000803e3d6000fd5b505050506040513d6020811015613eff57600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613f5a57600080fd5b505af1158015613f6e573d6000803e3d6000fd5b505050506040513d6020811015613f8457600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6020811015613ffd57600080fd5b5051116134055760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b600061405d846001600160a01b031661434b565b6140695750600161187b565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b838110156140e65781810151838201526020016140ce565b50505050905090810190601f1680156141135780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561413557600080fd5b505af1158015614149573d6000803e3d6000fd5b505050506040513d602081101561415f57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b600081516041146141e65750600061157e565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561422c576000935050505061157e565b8060ff16601b1415801561424457508060ff16601c14155b15614255576000935050505061157e565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142ac573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b0381166142da57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b8054611cf157606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143925782800160ff198235161785556143bf565b828001600101855582156143bf579182015b828111156143bf5782358255916020019190600101906143a4565b506143cb9291506143cf565b5090565b61157091905b808211156143cb57600081556001016143d556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582031474d01281aa90a56dde5554eed5c93cdafcfbf9c58bfb981584096593435520029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.9", - "updatedAt": "2019-05-21T02:16:43.430Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV4.json b/packages/contracts/src/abis/PublicLock/PublicLockV4.json deleted file mode 100644 index 3b3a8ababfe..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV4.json +++ /dev/null @@ -1,1421 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_approved", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_page", - "type": "uint256" - }, - { - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_refundPenaltyNumerator", - "type": "uint256" - }, - { - "name": "_refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfKeysSold", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_transferFeeNumerator", - "type": "uint256" - }, - { - "name": "_transferFeeDenominator", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_a", - "type": "string" - }, - { - "name": "_b", - "type": "string" - }, - { - "name": "_c", - "type": "string" - }, - { - "name": "_d", - "type": "string" - } - ], - "name": "strConcat", - "outputs": [ - { - "name": "_concatenatedString", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "keyOwnerToNonce", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_i", - "type": "uint256" - } - ], - "name": "uint2Str", - "outputs": [ - { - "name": "_uintAsString", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "name": "address2Str", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "incrementNonce", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "purchaseForFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_keyOwner", - "type": "address" - }, - { - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeNumerator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_tokenId", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_keyOwner", - "type": "address" - }, - { - "name": "_signature", - "type": "bytes" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeDenominator", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipient", - "type": "address" - } - ], - "name": "purchaseFor", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_account", - "type": "address" - } - ], - "name": "getBalance", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_recipients", - "type": "address[]" - }, - { - "name": "_expirationTimestamp", - "type": "uint256" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "name": "_lockName", - "type": "string" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldRefundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldRefundPenaltyDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "refundPenaltyDenominator", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldTransferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "oldTransferFeeDenominator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeNumerator", - "type": "uint256" - }, - { - "indexed": false, - "name": "transferFeeDenominator", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "bytecode": "0x6080604052600060765560646077556001607855600a6079553480156200002557600080fd5b5060405162004af138038062004af1833981810160405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50909350839250889150879050858588620000fa7f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b6001600160a01b03811615806200017857506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200014857600080fd5b505afa1580156200015d573d6000803e3d6000fd5b505050506040513d60208110156200017457600080fd5b5051115b620001e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460ff60a01b196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200029757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054336001600160a01b031991821617909155606d80549091166001600160a01b039590951694909417909355606991909155606a55606b558051620002e790607190602084019062000565565b506200031c7f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b50620003517f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b62000367866200044260201b620030891760201c565b50505050505062000607565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200040557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620004675750620004676001600160e01b036200055e16565b8062000476575060015460ff16155b620004cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062004ac3602e913960400191505060405180910390fd5b600154610100900460ff16158015620004f8576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156200055a576001805461ff00191690555b5050565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005a857805160ff1916838001178555620005d8565b82800160010185558215620005d8579182015b82811115620005d8578251825591602001919060010190620005bb565b50620005e6929150620005ea565b5090565b6200056291905b80821115620005e65760008155600101620005f1565b6144ac80620006176000396000f3fe6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564", - "deployedBytecode": "0x6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032", - "compiler": { - "name": "solc", - "version": "0.5.9+commit.e560f70d.Emscripten.clang" - }, - "schemaVersion": "3.0.10", - "updatedAt": "2019-06-05T17:55:27.559Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV5.json b/packages/contracts/src/abis/PublicLock/PublicLockV5.json deleted file mode 100644 index 481bdc863a3..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV5.json +++ /dev/null @@ -1,1574 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keyOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextAvailableNonce", - "type": "uint256" - } - ], - "name": "NonceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - } - ], - "name": "PriceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_timeAdded", - "type": "bool" - } - ], - "name": "TimestampChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BASIS_POINTS_DEN", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_signature", - "type": "bytes" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "erc1820", - "outputs": [ - { - "internalType": "contract IERC1820Registry", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "freeTrialLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "fullRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_page", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_time", - "type": "uint256" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address[]", - "name": "_recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_nextAvailableNonce", - "type": "uint256" - } - ], - "name": "invalidateOffchainApproval", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyCancelInterfaceId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "keyOwnerToNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keySoldInterfaceId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchase", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timeShared", - "type": "uint256" - } - ], - "name": "shareKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "internalType": "contract IUnlock", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "updateKeyPrice", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x6080604052615592806100136000396000f3fe6080604052600436106103ef5760003560e01c806374b6c10611610208578063a843a4e711610118578063d1bbd49c116100ab578063f12c6b6e1161007a578063f12c6b6e146111e0578063f2fde38b1461121f578063f3fef3a314611252578063f7514bce1461128b578063fc42b58f146112c4576103ef565b8063d1bbd49c14611140578063d4fac45d14611155578063e7e2736e14611190578063e985e9c5146111a5576103ef565b8063b8968bb4116100e7578063b8968bb414611043578063c1c98d03146110ce578063c4d66de8146110e3578063c87b56dd14611116576103ef565b8063a843a4e714610f15578063abdf82ce14610f2a578063b3084f0814610f5d578063b88d4fde14610f72576103ef565b8063936d2aa41161019b578063994a8a711161016a578063994a8a7114610e445780639d76ea5814610e7d5780639f98d3cb14610e92578063a22cb46514610ec5578063a375cb0514610f00576103ef565b8063936d2aa414610dd257806393fd184414610de757806395d89b4114610dfc578063970aaeb714610e11576103ef565b80638577a6d5116101d75780638577a6d514610d435780638d0361fc14610d6d5780638da5cb5b14610da85780638f32d59b14610dbd576103ef565b806374b6c10614610bd3578063782a4ade14610be85780637c7c425314610c635780638129fc1c14610d2e576103ef565b806335576ad0116103035780634fd24d30116102965780636352211e116102655780636352211e14610a525780636d8ea5b414610a7c5780636eadde4314610aaf57806370a0823114610b8b578063715018a614610bbe576103ef565b80634fd24d301461097a57806352d6a8e41461098f578063550ef3a8146109c257806356e0d51f14610a3d576103ef565b80634136aa35116102d25780634136aa35146108c557806342842e0e146108da5780634bc5a1351461091d5780634f6ccce714610950576103ef565b806335576ad0146107c857806338af3eed146107f257806339f46986146108075780633f33133a14610837576103ef565b806310e56973116103865780631f1ec029116103555780631f1ec029146106925780632009dc65146106bc57806323b872dd146106d15780632f745c591461071457806330176e131461074d576103ef565b806310e569731461062c57806311a4c03a1461065357806318160ddd14610668578063183767da1461067d576103ef565b8063095ea7b3116103c2578063095ea7b3146105365780630aaffd2a146105645780630f15023b1461059757806310803b72146105ac576103ef565b806301ffc9a7146103f4578063025e7c271461043c57806306fdde0314610482578063081812fc1461050c575b600080fd5b34801561040057600080fd5b506104286004803603602081101561041757600080fd5b50356001600160e01b0319166112fd565b604080519115158252519081900360200190f35b34801561044857600080fd5b506104666004803603602081101561045f57600080fd5b5035611320565b604080516001600160a01b039092168252519081900360200190f35b34801561048e57600080fd5b50610497611347565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104d15781810151838201526020016104b9565b50505050905090810190601f1680156104fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561051857600080fd5b506104666004803603602081101561052f57600080fd5b50356113d5565b6105626004803603604081101561054c57600080fd5b506001600160a01b038135169060200135611435565b005b34801561057057600080fd5b506105626004803603602081101561058757600080fd5b50356001600160a01b03166115cb565b3480156105a357600080fd5b506104666116bc565b3480156105b857600080fd5b506105dc600480360360408110156105cf57600080fd5b50803590602001356116cb565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610618578181015183820152602001610600565b505050509050019250505060405180910390f35b34801561063857600080fd5b506106416117e3565b60408051918252519081900360200190f35b34801561065f57600080fd5b506106416117e9565b34801561067457600080fd5b506106416117ef565b34801561068957600080fd5b506106416117f5565b34801561069e57600080fd5b50610562600480360360208110156106b557600080fd5b50356117fb565b3480156106c857600080fd5b506105626118d9565b3480156106dd57600080fd5b50610562600480360360608110156106f457600080fd5b506001600160a01b038135811691602081013590911690604001356118f3565b34801561072057600080fd5b506106416004803603604081101561073757600080fd5b506001600160a01b038135169060200135611bac565b34801561075957600080fd5b506105626004803603602081101561077057600080fd5b810190602081018135600160201b81111561078a57600080fd5b82018360208201111561079c57600080fd5b803590602001918460018302840111600160201b831117156107bd57600080fd5b509092509050611c0a565b3480156107d457600080fd5b50610562600480360360208110156107eb57600080fd5b5035611c62565b3480156107fe57600080fd5b50610466611d04565b34801561081357600080fd5b506105626004803603604081101561082a57600080fd5b5080359060200135611d13565b6105626004803603608081101561084d57600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561088757600080fd5b82018360208201111561089957600080fd5b803590602001918460018302840111600160201b831117156108ba57600080fd5b509092509050611da0565b3480156108d157600080fd5b50610428612179565b3480156108e657600080fd5b50610562600480360360608110156108fd57600080fd5b506001600160a01b03813581169160208101359091169060400135612189565b34801561092957600080fd5b506106416004803603602081101561094057600080fd5b50356001600160a01b03166121a4565b34801561095c57600080fd5b506106416004803603602081101561097357600080fd5b50356121b6565b34801561098657600080fd5b50610641612201565b34801561099b57600080fd5b50610641600480360360208110156109b257600080fd5b50356001600160a01b0316612207565b3480156109ce57600080fd5b50610562600480360360208110156109e557600080fd5b810190602081018135600160201b8111156109ff57600080fd5b820183602082011115610a1157600080fd5b803590602001918460018302840111600160201b83111715610a3257600080fd5b509092509050612212565b348015610a4957600080fd5b50610641612265565b348015610a5e57600080fd5b5061046660048036036020811015610a7557600080fd5b503561226b565b348015610a8857600080fd5b5061042860048036036020811015610a9f57600080fd5b50356001600160a01b0316612286565b348015610abb57600080fd5b50610562600480360360c0811015610ad257600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610b1757600080fd5b820183602082011115610b2957600080fd5b803590602001918460018302840111600160201b83111715610b4a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122a6945050505050565b348015610b9757600080fd5b5061064160048036036020811015610bae57600080fd5b50356001600160a01b031661239d565b348015610bca57600080fd5b5061056261240c565b348015610bdf57600080fd5b5061064161249d565b348015610bf457600080fd5b5061056260048036036020811015610c0b57600080fd5b810190602081018135600160201b811115610c2557600080fd5b820183602082011115610c3757600080fd5b803590602001918460018302840111600160201b83111715610c5857600080fd5b5090925090506124a3565b348015610c6f57600080fd5b5061056260048036036040811015610c8657600080fd5b810190602081018135600160201b811115610ca057600080fd5b820183602082011115610cb257600080fd5b803590602001918460208302840111600160201b83111715610cd357600080fd5b919390929091602081019035600160201b811115610cf057600080fd5b820183602082011115610d0257600080fd5b803590602001918460208302840111600160201b83111715610d2357600080fd5b50909250905061255b565b348015610d3a57600080fd5b506105626126ec565b348015610d4f57600080fd5b5061056260048036036020811015610d6657600080fd5b50356126f4565b348015610d7957600080fd5b5061064160048036036040811015610d9057600080fd5b506001600160a01b0381358116916020013516612773565b348015610db457600080fd5b506104666127d7565b348015610dc957600080fd5b506104286127e7565b348015610dde57600080fd5b5061064161280d565b348015610df357600080fd5b50610641612831565b348015610e0857600080fd5b50610497612837565b348015610e1d57600080fd5b5061064160048036036020811015610e3457600080fd5b50356001600160a01b0316612a26565b348015610e5057600080fd5b5061042860048036036040811015610e6757600080fd5b50803590602001356001600160a01b0316612a90565b348015610e8957600080fd5b50610466612ab1565b348015610e9e57600080fd5b5061056260048036036020811015610eb557600080fd5b50356001600160a01b0316612ac0565b348015610ed157600080fd5b5061056260048036036040811015610ee857600080fd5b506001600160a01b0381351690602001351515612b9f565b348015610f0c57600080fd5b50610641612caa565b348015610f2157600080fd5b50610562612cb0565b348015610f3657600080fd5b5061064160048036036020811015610f4d57600080fd5b50356001600160a01b0316612da0565b348015610f6957600080fd5b50610641612e25565b348015610f7e57600080fd5b5061056260048036036080811015610f9557600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610fcf57600080fd5b820183602082011115610fe157600080fd5b803590602001918460018302840111600160201b8311171561100257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612e49945050505050565b34801561104f57600080fd5b506105626004803603604081101561106657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561109057600080fd5b8201836020820111156110a257600080fd5b803590602001918460018302840111600160201b831117156110c357600080fd5b509092509050612ffc565b3480156110da57600080fd5b50610562613117565b3480156110ef57600080fd5b506105626004803603602081101561110657600080fd5b50356001600160a01b03166131e6565b34801561112257600080fd5b506104976004803603602081101561113957600080fd5b50356132b5565b34801561114c57600080fd5b50610641613542565b34801561116157600080fd5b506106416004803603604081101561117857600080fd5b506001600160a01b0381358116916020013516613547565b34801561119c57600080fd5b506104666135f1565b3480156111b157600080fd5b50610428600480360360408110156111c857600080fd5b506001600160a01b0381358116916020013516613609565b3480156111ec57600080fd5b506105626004803603606081101561120357600080fd5b506001600160a01b038135169060208101359060400135613637565b34801561122b57600080fd5b506105626004803603602081101561124257600080fd5b50356001600160a01b03166139bd565b34801561125e57600080fd5b506105626004803603604081101561127557600080fd5b506001600160a01b038135169060200135613a0d565b34801561129757600080fd5b50610562600480360360408110156112ae57600080fd5b506001600160a01b038135169060200135613b67565b3480156112d057600080fd5b50610641600480360360408110156112e757600080fd5b506001600160a01b038135169060200135613c03565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b60a3818154811061132d57fe5b6000918252602090912001546001600160a01b0316905081565b60a4805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156113cd5780601f106113a2576101008083540402835291602001916113cd565b820191906000526020600020905b8154815290600101906020018083116113b057829003601f168201915b505050505081565b600081815260a760205260408120546001600160a01b03168061142f576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b92915050565b609a54600160a01b900460ff16611485576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806114908133612a90565b806114a057506114a08133613cac565b806114c85750600081815260a260205260409020546114c8906001600160a01b031633613609565b611516576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611563576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260a76020908152604080832080546001600160a01b0319166001600160a01b0388811691821790925560a2909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6115d36127d7565b6001600160a01b0316336001600160a01b031614806115fc575060a0546001600160a01b031633145b61164d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b03811661169a576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b60a080546001600160a01b0319166001600160a01b0392909216919091179055565b609b546001600160a01b031681565b60a354606090611718576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60a354829084820290600090828401111561173b575060a3548181039250611740565b508082015b60608360405190808252806020026020018201604052801561176c578160200160208202803883390190505b5090506000835b838110156117d65760a3818154811061178857fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106117b257fe5b6001600160a01b039092166020928302919091019091015260019182019101611773565b5090979650505050505050565b609d5481565b609c5481565b609f5481565b60a95481565b6118036127e7565b611842576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff16611892576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609d805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006118e433613ccd565b90506118f03382613dd4565b50565b609a54600160a01b900460ff16611943576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8261194d81612286565b61198e576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b816119998133612a90565b806119a957506119a98133613cac565b806119d15750600081815260a260205260409020546119d1906001600160a01b031633613609565b611a1f576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060a95410611a70576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611abd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611aca866000613c03565b6001600160a01b03808816600090815260a1602052604080822092891682528120825460018201549495509293909291611b079083908790613e59565b8254611b1d578354808455611b1d908a90613f7b565b428111611b41576001808501549084015583548355611b3c8989613f7b565b611b5e565b6001840154611b589042830363ffffffff61400316565b60018401555b42600185015560008455611b718861405d565b87896001600160a01b03168b6001600160a01b031660008051602061551483398151915260405160405180910390a450505050505050505050565b60008115611bfa576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611c0383612a26565b9392505050565b611c126127e7565b611c51576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b611c5d60a68383615342565b505050565b336000908152609960205260409020548111611cba576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260996020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b60a0546001600160a01b031681565b611d1b6127e7565b611d5a576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a160ab9190915560aa55565b609a54600160a01b900460ff16611df0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609f54609e5411611e38576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416611e85576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260a1602052604090208054611eba57611eac81614098565b611eba858260000154613f7b565b42816001015410611ee657609c546001820154611edc9163ffffffff61400316565b6001820155611ef1565b609c54420160018201555b609d54609b5460408051630cb175e360e01b81526001600160a01b03898116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015611f4a57600080fd5b505afa158015611f5e573d6000803e3d6000fd5b505050506040513d6040811015611f7457600080fd5b508051602090910151909350915080831115611f9257506000611f96565b8290035b821561200957609b5460408051633652466360e01b8152600481018690526024810185905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015611ff057600080fd5b505af1158015612004573d6000803e3d6000fd5b505050505b609b546001600160a01b031663939d9f1f826120248a612286565b61202f576000612031565b895b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561208057600080fd5b505af1158015612094573d6000803e3d6000fd5b505085546040519092506001600160a01b038b169150600090600080516020615514833981519152908290a4609a546001600160a01b03161561211e578089101561211b576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b50875b6000612129826140ad565b905061216d8989838a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061413b92505050565b50505050505050505050565b609a54600160a01b900460ff1681565b611c5d83838360405180602001604052806000815250612e49565b60996020526000908152604090205481565b6000609f5482106121fd576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b61271081565b600061142f82613ccd565b61221a6127e7565b612259576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b611c5d60a48383615342565b60aa5481565b60a2602052600090815260409020546001600160a01b031681565b6001600160a01b0316600090815260a16020526040902060010154421090565b600054610100900460ff16806122bf57506122bf6142f1565b806122cd575060005460ff16155b6123085760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015612333576000805460ff1961ff0019909116610100171660011790555b61233c876142f7565b612345856131e6565b61234d6143e8565b612359878786866143fd565b61236282614493565b61236a6144bf565b6123726126ec565b6123826380ac58cd60e01b6144d1565b8015612394576000805461ff00191690555b50505050505050565b60006001600160a01b0382166123ec576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6123f582612286565b612400576000612403565b60015b60ff1692915050565b6124146127e7565b612453576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6066546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606680546001600160a01b0319169055565b609e5481565b6124ab6127e7565b6124ea576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6124f660a58383615342565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125636127e7565b6125a2576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b60005b838110156126e55760008585838181106125bb57fe5b905060200201356001600160a01b0316905060008484848181106125db57fe5b60200291909101359150506001600160a01b038216612633576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260a16020526040902060018101548211612696576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b61269f81614098565b6126ad838260000154613f7b565b6001810182905580546040516001600160a01b03851690600090600080516020615514833981519152908290a45050506001016125a5565b5050505050565b6103e860aa55565b6126fc6127e7565b61273b576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a160a955565b6001600160a01b039190911660009081526099602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6066546001600160a01b03165b90565b6066546000906001600160a01b03166127fe614555565b6001600160a01b031614905090565b7fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f6881565b60a35490565b60a5546060906002600019610100600184161502019091160461299457609b60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156128a257600080fd5b505afa1580156128b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156128df57600080fd5b8101908080516040519392919084600160201b8211156128fe57600080fd5b90830190602082018581111561291357600080fd5b8251600160201b81118282018810171561292c57600080fd5b82525081516020918201929091019080838360005b83811015612959578181015183820152602001612941565b50505050905090810190601f1680156129865780820380516001836020036101000a031916815260200191505b5060405250505090506127e4565b60a5805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612a1a5780601f106129ef57610100808354040283529160200191612a1a565b820191906000526020600020905b8154815290600101906020018083116129fd57829003601f168201915b505050505090506127e4565b600081612a3281612286565b612a73576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a1602052604090205490565b600091825260a26020526040909120546001600160a01b0391821691161490565b609a546001600160a01b031681565b612ac86127e7565b612b07576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b80612b1181612286565b612b52576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260a160205260408082204260018201558054915190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79591a2505050565b609a54600160a01b900460ff16612bef576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612c3c576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b33600081815260a8602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b60ab5481565b612cb86127e7565b612cf7576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff1615612d46576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2609a54612d9d906001600160a01b031633612d988230613547565b614559565b33ff5b6001600160a01b038116600090815260a160205260408120600101548290612e05576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a1602052604090206001015490565b7f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f081565b609a54600160a01b900460ff16612e99576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612ea48133612a90565b80612eb45750612eb48133613cac565b80612edc5750600081815260a26020526040902054612edc906001600160a01b031633613609565b612f2a576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b600083815260a260205260409020546001600160a01b0316612f4b81612286565b612f8c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612f978686866118f3565b612fa3868686866145a6565b612ff4576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6130068333612773565b82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250506001600160a01b038216905061305b613055856146d9565b8461472a565b6001600160a01b0316146130aa576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038116600081815260996020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a2600061310b87613ccd565b90506123948782613dd4565b61311f6127e7565b61315e576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff166131ae576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a1609a805460ff60a01b19169055565b609a80546001600160a01b0319166001600160a01b038316908117909155158061327457506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561324657600080fd5b505afa15801561325a573d6000803e3d6000fd5b505050506040513d602081101561327057600080fd5b5051115b6118f0576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b600081815260a2602052604090205460609082906001600160a01b0316613311576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b60a6546060906002600019610100600184161502019091160461346e57609b60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561337c57600080fd5b505afa158015613390573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156133b957600080fd5b8101908080516040519392919084600160201b8211156133d857600080fd5b9083019060208201858111156133ed57600080fd5b8251600160201b81118282018810171561340657600080fd5b82525081516020918201929091019080838360005b8381101561343357818101518382015260200161341b565b50505050905090810190601f1680156134605780820380516001836020036101000a031916815260200191505b5060405250505090506134fc565b60a6805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156134f45780601f106134c9576101008083540402835291602001916134f4565b820191906000526020600020905b8154815290600101906020018083116134d757829003601f168201915b505050505090505b61353a61350830614818565b604051806040016040528060018152602001602f60f81b81525061352b87614994565b8492919063ffffffff614a5816565b949350505050565b600590565b60006001600160a01b03831661356857506001600160a01b0381163161142f565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156135be57600080fd5b505afa1580156135d2573d6000803e3d6000fd5b505050506040513d60208110156135e857600080fd5b5051905061142f565b731820a4b7618bde71dce8cdc73aab6c95905fad2481565b6001600160a01b03918216600090815260a86020908152604080832093909416825291909152205460ff1690565b609a54600160a01b900460ff16613687576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b816136928133612a90565b806136a257506136a28133613cac565b806136ca5750600081815260a260205260409020546136ca906001600160a01b031633613609565b613718576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060a95410613769576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b0384166137b6576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b600083815260a260205260409020546001600160a01b03166137d781612286565b613818576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03808216600090815260a1602052604080822092881682528120805460018401549192909142900381613852878a613c03565b905060006138668a8363ffffffff61400316565b9050828110156138845789935061387f8b826000613e59565b6138c8565b61388e8884613c03565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8554613908576138d786614098565b6138e18c86613f7b565b60405185906001600160a01b038e1690600090600080516020615514833981519152908290a45b61391485856001613e59565b848c6001600160a01b0316896001600160a01b031660008051602061551483398151915260405160405180910390a461395e888d8d604051806020016040528060008152506145a6565b6139af576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050505050505050565b6139c56127e7565b613a04576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6118f081614c0d565b613a156127d7565b6001600160a01b0316336001600160a01b03161480613a3e575060a0546001600160a01b031633145b613a8f576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000613a9b8330613547565b90506000821580613aab57508183115b15613aff5760008211613af8576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080613b02565b50815b60a0546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a460a054613b619085906001600160a01b031683614559565b50505050565b613b6f6127e7565b613bae576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b81613bb881612286565b613bf9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611c5d8383613dd4565b600082613c0f81612286565b613c50576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038416600090815260a160205260408120908085613c7d57428360010154039150613c81565b8591505b612710613c9960a95484614cae90919063ffffffff16565b81613ca057fe5b04979650505050505050565b600091825260a76020526040909120546001600160a01b0391821691161490565b600081613cd981612286565b613d1a576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038316600090815260a1602052604090206001810154609c5460ab544290920391820110613d5357609d549350613d74565b609c54609d54613d69908363ffffffff614cae16565b81613d7057fe5b0493505b60ab541580613d885750609c5460ab548201105b15613dcc576000612710613da960aa54609d54614cae90919063ffffffff16565b81613db057fe5b04905080851115613dc5578085039450613dca565b600094505b505b505050919050565b6001600160a01b038216600081815260a1602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115613e4f57609a54613e4f906001600160a01b03168484614559565b611c5d8383614d07565b600083815260a260205260409020546001600160a01b031680613eb6576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b038116600090815260a16020526040812060018101549091613ede84612286565b90508415613f21578015613f0657613efc828763ffffffff61400316565b6001840155613f1c565b613f16428763ffffffff61400316565b60018401555b613f37565b613f31828763ffffffff614e3716565b60018401555b604080518781528615156020820152815189927fa2ede7ad01668310f921fcf6084901d08af350838c2744a013153e4968a7559d928290030190a250505050505050565b600081815260a260205260409020546001600160a01b03838116911614613fff5760a38054600181019091557f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b170180546001600160a01b0384166001600160a01b03199182168117909255600083815260a260205260409020805490911690911790555b5050565b600082820183811015611c03576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081815260a760205260409020546001600160a01b0316156118f057600090815260a76020526040902080546001600160a01b0319169055565b80546118f057609f8054600101908190559055565b6000811561131b57609a546001600160a01b0316614114578134101561410d576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b503461131b565b609a546001600160a01b03166141328133308663ffffffff614e7916565b8291505061131b565b60a0546040805163555ddc6560e11b81526001600160a01b0390921660048301527f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156141c257600080fd5b505afa1580156141d6573d6000803e3d6000fd5b505050506040513d60208110156141ec57600080fd5b505190506001600160a01b038116156126e557604051638d0f092560e01b815233600482018181526001600160a01b03888116602485015287811660448501526064840187905260a060848501908152865160a4860152865191861694638d0f092594938b938b938b938b939260c490910190602085019080838360005b8381101561428257818101518382015260200161426a565b50505050905090810190601f1680156142af5780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156142d257600080fd5b505af11580156142e6573d6000803e3d6000fd5b505050505050505050565b303b1590565b600054610100900460ff168061431057506143106142f1565b8061431e575060005460ff16155b6143595760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015614384576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015613fff576000805461ff00191690555050565b609a805460ff60a01b1916600160a01b179055565b63bbf81e00831115614456576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b609b8054336001600160a01b03199182161790915560a080549091166001600160a01b039590951694909417909355609c91909155609d55609e55565b61449b614ed3565b80516144ae9060a49060208401906153bc565b506118f0635b5e139f60e01b6144d1565b6144cf63780e9d6360e01b6144d1565b565b6001600160e01b03198082161415614530576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b3390565b8015611c5d576001600160a01b03831661458b576145866001600160a01b0383168263ffffffff614f8416565b611c5d565b82613b616001600160a01b038216848463ffffffff61506a16565b60006145ba846001600160a01b03166150bc565b6145c65750600161353a565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614640578181015183820152602001614628565b50505050905090810190601f16801561466d5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561468f57600080fd5b505af11580156146a3573d6000803e3d6000fd5b505050506040513d60208110156146b957600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000815160411461473d5750600061142f565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115614783576000935050505061142f565b8060ff16601b1415801561479b57508060ff16601c14155b156147ac576000935050505061142f565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015614803573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b8160008151811061487c57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106148a557fe5b60200101906001600160f81b031916908160001a90535060005b601481101561498b578260048583600c01602081106148da57fe5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106148fa57fe5b602001015160f81c60f81b82826002026002018151811061491757fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061493e57fe5b825191901a600f1690811061494f57fe5b602001015160f81c60f81b82826002026003018151811061496c57fe5b60200101906001600160f81b031916908160001a9053506001016148bf565b50949350505050565b606081806149bb5750506040805180820190915260018152600360fc1b602082015261131b565b8260005b81156149d357600101600a820491506149bf565b6060816040519080825280601f01601f191660200182016040528015614a00576020820181803883390190505b50905060001982015b8415614a4e57600a850660300160f81b82828060019003935081518110614a2c57fe5b60200101906001600160f81b031916908160001a905350600a85049450614a09565b5095945050505050565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015614aa4576020820181803883390190505b509050806000805b8751811015614afd57878181518110614ac157fe5b602001015160f81c60f81b838380600101945081518110614ade57fe5b60200101906001600160f81b031916908160001a905350600101614aac565b5060005b8651811015614b5257868181518110614b1657fe5b602001015160f81c60f81b838380600101945081518110614b3357fe5b60200101906001600160f81b031916908160001a905350600101614b01565b5060005b8551811015614ba757858181518110614b6b57fe5b602001015160f81c60f81b838380600101945081518110614b8857fe5b60200101906001600160f81b031916908160001a905350600101614b56565b5060005b8451811015614bfc57848181518110614bc057fe5b602001015160f81c60f81b838380600101945081518110614bdd57fe5b60200101906001600160f81b031916908160001a905350600101614bab565b50909b9a5050505050505050505050565b6001600160a01b038116614c525760405162461bcd60e51b81526004018080602001828103825260268152602001806154456026913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b600082614cbd5750600061142f565b82820282848281614cca57fe5b0414611c035760405162461bcd60e51b81526004018080602001828103825260218152602001806154a56021913960400191505060405180910390fd5b60a0546040805163555ddc6560e11b81526001600160a01b0390921660048301527fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b158015614d8e57600080fd5b505afa158015614da2573d6000803e3d6000fd5b505050506040513d6020811015614db857600080fd5b505190506001600160a01b03811615611c5d576040805163c9877d7b60e01b81523360048201526001600160a01b0385811660248301526044820185905291519183169163c9877d7b9160648082019260009290919082900301818387803b158015614e2357600080fd5b505af1158015612394573d6000803e3d6000fd5b6000611c0383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506150f3565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613b6190859061518a565b600054610100900460ff1680614eec5750614eec6142f1565b80614efa575060005460ff16155b614f355760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015614f60576000805460ff1961ff0019909116610100171660011790555b614f706301ffc9a760e01b6144d1565b80156118f0576000805461ff001916905550565b3031811115614fda576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114615025576040519150601f19603f3d011682016040523d82523d6000602084013e61502a565b606091505b5050905080611c5d5760405162461bcd60e51b815260040180806020018281038252603a81526020018061546b603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611c5d90849061518a565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470811580159061353a5750141592915050565b600081848411156151825760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561514757818101518382015260200161512f565b50505050905090810190601f1680156151745780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61519c826001600160a01b03166150bc565b6151ed576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061522b5780518252601f19909201916020918201910161520c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461528d576040519150601f19603f3d011682016040523d82523d6000602084013e615292565b606091505b5091509150816152e9576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115613b615780806020019051602081101561530557600080fd5b5051613b615760405162461bcd60e51b815260040180806020018281038252602a815260200180615534602a913960400191505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153835782800160ff198235161785556153b0565b828001600101855582156153b0579182015b828111156153b0578235825591602001919060010190615395565b506121fd92915061542a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153fd57805160ff19168380011785556153b0565b828001600101855582156153b0579182015b828111156153b057825182559160200191906001019061540f565b6127e491905b808211156121fd576000815560010161543056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a7231582013b44e6afc5a7bb538a4b112863a2d1fc743d60c03c249977c5feaec0cbedecf64736f6c634300050c0032", - "deployedBytecode": "0x6080604052600436106103ef5760003560e01c806374b6c10611610208578063a843a4e711610118578063d1bbd49c116100ab578063f12c6b6e1161007a578063f12c6b6e146111e0578063f2fde38b1461121f578063f3fef3a314611252578063f7514bce1461128b578063fc42b58f146112c4576103ef565b8063d1bbd49c14611140578063d4fac45d14611155578063e7e2736e14611190578063e985e9c5146111a5576103ef565b8063b8968bb4116100e7578063b8968bb414611043578063c1c98d03146110ce578063c4d66de8146110e3578063c87b56dd14611116576103ef565b8063a843a4e714610f15578063abdf82ce14610f2a578063b3084f0814610f5d578063b88d4fde14610f72576103ef565b8063936d2aa41161019b578063994a8a711161016a578063994a8a7114610e445780639d76ea5814610e7d5780639f98d3cb14610e92578063a22cb46514610ec5578063a375cb0514610f00576103ef565b8063936d2aa414610dd257806393fd184414610de757806395d89b4114610dfc578063970aaeb714610e11576103ef565b80638577a6d5116101d75780638577a6d514610d435780638d0361fc14610d6d5780638da5cb5b14610da85780638f32d59b14610dbd576103ef565b806374b6c10614610bd3578063782a4ade14610be85780637c7c425314610c635780638129fc1c14610d2e576103ef565b806335576ad0116103035780634fd24d30116102965780636352211e116102655780636352211e14610a525780636d8ea5b414610a7c5780636eadde4314610aaf57806370a0823114610b8b578063715018a614610bbe576103ef565b80634fd24d301461097a57806352d6a8e41461098f578063550ef3a8146109c257806356e0d51f14610a3d576103ef565b80634136aa35116102d25780634136aa35146108c557806342842e0e146108da5780634bc5a1351461091d5780634f6ccce714610950576103ef565b806335576ad0146107c857806338af3eed146107f257806339f46986146108075780633f33133a14610837576103ef565b806310e56973116103865780631f1ec029116103555780631f1ec029146106925780632009dc65146106bc57806323b872dd146106d15780632f745c591461071457806330176e131461074d576103ef565b806310e569731461062c57806311a4c03a1461065357806318160ddd14610668578063183767da1461067d576103ef565b8063095ea7b3116103c2578063095ea7b3146105365780630aaffd2a146105645780630f15023b1461059757806310803b72146105ac576103ef565b806301ffc9a7146103f4578063025e7c271461043c57806306fdde0314610482578063081812fc1461050c575b600080fd5b34801561040057600080fd5b506104286004803603602081101561041757600080fd5b50356001600160e01b0319166112fd565b604080519115158252519081900360200190f35b34801561044857600080fd5b506104666004803603602081101561045f57600080fd5b5035611320565b604080516001600160a01b039092168252519081900360200190f35b34801561048e57600080fd5b50610497611347565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104d15781810151838201526020016104b9565b50505050905090810190601f1680156104fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561051857600080fd5b506104666004803603602081101561052f57600080fd5b50356113d5565b6105626004803603604081101561054c57600080fd5b506001600160a01b038135169060200135611435565b005b34801561057057600080fd5b506105626004803603602081101561058757600080fd5b50356001600160a01b03166115cb565b3480156105a357600080fd5b506104666116bc565b3480156105b857600080fd5b506105dc600480360360408110156105cf57600080fd5b50803590602001356116cb565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610618578181015183820152602001610600565b505050509050019250505060405180910390f35b34801561063857600080fd5b506106416117e3565b60408051918252519081900360200190f35b34801561065f57600080fd5b506106416117e9565b34801561067457600080fd5b506106416117ef565b34801561068957600080fd5b506106416117f5565b34801561069e57600080fd5b50610562600480360360208110156106b557600080fd5b50356117fb565b3480156106c857600080fd5b506105626118d9565b3480156106dd57600080fd5b50610562600480360360608110156106f457600080fd5b506001600160a01b038135811691602081013590911690604001356118f3565b34801561072057600080fd5b506106416004803603604081101561073757600080fd5b506001600160a01b038135169060200135611bac565b34801561075957600080fd5b506105626004803603602081101561077057600080fd5b810190602081018135600160201b81111561078a57600080fd5b82018360208201111561079c57600080fd5b803590602001918460018302840111600160201b831117156107bd57600080fd5b509092509050611c0a565b3480156107d457600080fd5b50610562600480360360208110156107eb57600080fd5b5035611c62565b3480156107fe57600080fd5b50610466611d04565b34801561081357600080fd5b506105626004803603604081101561082a57600080fd5b5080359060200135611d13565b6105626004803603608081101561084d57600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561088757600080fd5b82018360208201111561089957600080fd5b803590602001918460018302840111600160201b831117156108ba57600080fd5b509092509050611da0565b3480156108d157600080fd5b50610428612179565b3480156108e657600080fd5b50610562600480360360608110156108fd57600080fd5b506001600160a01b03813581169160208101359091169060400135612189565b34801561092957600080fd5b506106416004803603602081101561094057600080fd5b50356001600160a01b03166121a4565b34801561095c57600080fd5b506106416004803603602081101561097357600080fd5b50356121b6565b34801561098657600080fd5b50610641612201565b34801561099b57600080fd5b50610641600480360360208110156109b257600080fd5b50356001600160a01b0316612207565b3480156109ce57600080fd5b50610562600480360360208110156109e557600080fd5b810190602081018135600160201b8111156109ff57600080fd5b820183602082011115610a1157600080fd5b803590602001918460018302840111600160201b83111715610a3257600080fd5b509092509050612212565b348015610a4957600080fd5b50610641612265565b348015610a5e57600080fd5b5061046660048036036020811015610a7557600080fd5b503561226b565b348015610a8857600080fd5b5061042860048036036020811015610a9f57600080fd5b50356001600160a01b0316612286565b348015610abb57600080fd5b50610562600480360360c0811015610ad257600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610b1757600080fd5b820183602082011115610b2957600080fd5b803590602001918460018302840111600160201b83111715610b4a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122a6945050505050565b348015610b9757600080fd5b5061064160048036036020811015610bae57600080fd5b50356001600160a01b031661239d565b348015610bca57600080fd5b5061056261240c565b348015610bdf57600080fd5b5061064161249d565b348015610bf457600080fd5b5061056260048036036020811015610c0b57600080fd5b810190602081018135600160201b811115610c2557600080fd5b820183602082011115610c3757600080fd5b803590602001918460018302840111600160201b83111715610c5857600080fd5b5090925090506124a3565b348015610c6f57600080fd5b5061056260048036036040811015610c8657600080fd5b810190602081018135600160201b811115610ca057600080fd5b820183602082011115610cb257600080fd5b803590602001918460208302840111600160201b83111715610cd357600080fd5b919390929091602081019035600160201b811115610cf057600080fd5b820183602082011115610d0257600080fd5b803590602001918460208302840111600160201b83111715610d2357600080fd5b50909250905061255b565b348015610d3a57600080fd5b506105626126ec565b348015610d4f57600080fd5b5061056260048036036020811015610d6657600080fd5b50356126f4565b348015610d7957600080fd5b5061064160048036036040811015610d9057600080fd5b506001600160a01b0381358116916020013516612773565b348015610db457600080fd5b506104666127d7565b348015610dc957600080fd5b506104286127e7565b348015610dde57600080fd5b5061064161280d565b348015610df357600080fd5b50610641612831565b348015610e0857600080fd5b50610497612837565b348015610e1d57600080fd5b5061064160048036036020811015610e3457600080fd5b50356001600160a01b0316612a26565b348015610e5057600080fd5b5061042860048036036040811015610e6757600080fd5b50803590602001356001600160a01b0316612a90565b348015610e8957600080fd5b50610466612ab1565b348015610e9e57600080fd5b5061056260048036036020811015610eb557600080fd5b50356001600160a01b0316612ac0565b348015610ed157600080fd5b5061056260048036036040811015610ee857600080fd5b506001600160a01b0381351690602001351515612b9f565b348015610f0c57600080fd5b50610641612caa565b348015610f2157600080fd5b50610562612cb0565b348015610f3657600080fd5b5061064160048036036020811015610f4d57600080fd5b50356001600160a01b0316612da0565b348015610f6957600080fd5b50610641612e25565b348015610f7e57600080fd5b5061056260048036036080811015610f9557600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610fcf57600080fd5b820183602082011115610fe157600080fd5b803590602001918460018302840111600160201b8311171561100257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612e49945050505050565b34801561104f57600080fd5b506105626004803603604081101561106657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561109057600080fd5b8201836020820111156110a257600080fd5b803590602001918460018302840111600160201b831117156110c357600080fd5b509092509050612ffc565b3480156110da57600080fd5b50610562613117565b3480156110ef57600080fd5b506105626004803603602081101561110657600080fd5b50356001600160a01b03166131e6565b34801561112257600080fd5b506104976004803603602081101561113957600080fd5b50356132b5565b34801561114c57600080fd5b50610641613542565b34801561116157600080fd5b506106416004803603604081101561117857600080fd5b506001600160a01b0381358116916020013516613547565b34801561119c57600080fd5b506104666135f1565b3480156111b157600080fd5b50610428600480360360408110156111c857600080fd5b506001600160a01b0381358116916020013516613609565b3480156111ec57600080fd5b506105626004803603606081101561120357600080fd5b506001600160a01b038135169060208101359060400135613637565b34801561122b57600080fd5b506105626004803603602081101561124257600080fd5b50356001600160a01b03166139bd565b34801561125e57600080fd5b506105626004803603604081101561127557600080fd5b506001600160a01b038135169060200135613a0d565b34801561129757600080fd5b50610562600480360360408110156112ae57600080fd5b506001600160a01b038135169060200135613b67565b3480156112d057600080fd5b50610641600480360360408110156112e757600080fd5b506001600160a01b038135169060200135613c03565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b60a3818154811061132d57fe5b6000918252602090912001546001600160a01b0316905081565b60a4805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156113cd5780601f106113a2576101008083540402835291602001916113cd565b820191906000526020600020905b8154815290600101906020018083116113b057829003601f168201915b505050505081565b600081815260a760205260408120546001600160a01b03168061142f576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b92915050565b609a54600160a01b900460ff16611485576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806114908133612a90565b806114a057506114a08133613cac565b806114c85750600081815260a260205260409020546114c8906001600160a01b031633613609565b611516576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611563576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260a76020908152604080832080546001600160a01b0319166001600160a01b0388811691821790925560a2909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6115d36127d7565b6001600160a01b0316336001600160a01b031614806115fc575060a0546001600160a01b031633145b61164d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b03811661169a576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b60a080546001600160a01b0319166001600160a01b0392909216919091179055565b609b546001600160a01b031681565b60a354606090611718576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60a354829084820290600090828401111561173b575060a3548181039250611740565b508082015b60608360405190808252806020026020018201604052801561176c578160200160208202803883390190505b5090506000835b838110156117d65760a3818154811061178857fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106117b257fe5b6001600160a01b039092166020928302919091019091015260019182019101611773565b5090979650505050505050565b609d5481565b609c5481565b609f5481565b60a95481565b6118036127e7565b611842576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff16611892576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609d805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006118e433613ccd565b90506118f03382613dd4565b50565b609a54600160a01b900460ff16611943576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8261194d81612286565b61198e576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b816119998133612a90565b806119a957506119a98133613cac565b806119d15750600081815260a260205260409020546119d1906001600160a01b031633613609565b611a1f576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060a95410611a70576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611abd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611aca866000613c03565b6001600160a01b03808816600090815260a1602052604080822092891682528120825460018201549495509293909291611b079083908790613e59565b8254611b1d578354808455611b1d908a90613f7b565b428111611b41576001808501549084015583548355611b3c8989613f7b565b611b5e565b6001840154611b589042830363ffffffff61400316565b60018401555b42600185015560008455611b718861405d565b87896001600160a01b03168b6001600160a01b031660008051602061551483398151915260405160405180910390a450505050505050505050565b60008115611bfa576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611c0383612a26565b9392505050565b611c126127e7565b611c51576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b611c5d60a68383615342565b505050565b336000908152609960205260409020548111611cba576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260996020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b60a0546001600160a01b031681565b611d1b6127e7565b611d5a576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a160ab9190915560aa55565b609a54600160a01b900460ff16611df0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609f54609e5411611e38576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416611e85576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260a1602052604090208054611eba57611eac81614098565b611eba858260000154613f7b565b42816001015410611ee657609c546001820154611edc9163ffffffff61400316565b6001820155611ef1565b609c54420160018201555b609d54609b5460408051630cb175e360e01b81526001600160a01b03898116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015611f4a57600080fd5b505afa158015611f5e573d6000803e3d6000fd5b505050506040513d6040811015611f7457600080fd5b508051602090910151909350915080831115611f9257506000611f96565b8290035b821561200957609b5460408051633652466360e01b8152600481018690526024810185905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015611ff057600080fd5b505af1158015612004573d6000803e3d6000fd5b505050505b609b546001600160a01b031663939d9f1f826120248a612286565b61202f576000612031565b895b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561208057600080fd5b505af1158015612094573d6000803e3d6000fd5b505085546040519092506001600160a01b038b169150600090600080516020615514833981519152908290a4609a546001600160a01b03161561211e578089101561211b576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b50875b6000612129826140ad565b905061216d8989838a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061413b92505050565b50505050505050505050565b609a54600160a01b900460ff1681565b611c5d83838360405180602001604052806000815250612e49565b60996020526000908152604090205481565b6000609f5482106121fd576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b61271081565b600061142f82613ccd565b61221a6127e7565b612259576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b611c5d60a48383615342565b60aa5481565b60a2602052600090815260409020546001600160a01b031681565b6001600160a01b0316600090815260a16020526040902060010154421090565b600054610100900460ff16806122bf57506122bf6142f1565b806122cd575060005460ff16155b6123085760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015612333576000805460ff1961ff0019909116610100171660011790555b61233c876142f7565b612345856131e6565b61234d6143e8565b612359878786866143fd565b61236282614493565b61236a6144bf565b6123726126ec565b6123826380ac58cd60e01b6144d1565b8015612394576000805461ff00191690555b50505050505050565b60006001600160a01b0382166123ec576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6123f582612286565b612400576000612403565b60015b60ff1692915050565b6124146127e7565b612453576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6066546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606680546001600160a01b0319169055565b609e5481565b6124ab6127e7565b6124ea576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6124f660a58383615342565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125636127e7565b6125a2576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b60005b838110156126e55760008585838181106125bb57fe5b905060200201356001600160a01b0316905060008484848181106125db57fe5b60200291909101359150506001600160a01b038216612633576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260a16020526040902060018101548211612696576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b61269f81614098565b6126ad838260000154613f7b565b6001810182905580546040516001600160a01b03851690600090600080516020615514833981519152908290a45050506001016125a5565b5050505050565b6103e860aa55565b6126fc6127e7565b61273b576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a160a955565b6001600160a01b039190911660009081526099602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6066546001600160a01b03165b90565b6066546000906001600160a01b03166127fe614555565b6001600160a01b031614905090565b7fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f6881565b60a35490565b60a5546060906002600019610100600184161502019091160461299457609b60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156128a257600080fd5b505afa1580156128b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156128df57600080fd5b8101908080516040519392919084600160201b8211156128fe57600080fd5b90830190602082018581111561291357600080fd5b8251600160201b81118282018810171561292c57600080fd5b82525081516020918201929091019080838360005b83811015612959578181015183820152602001612941565b50505050905090810190601f1680156129865780820380516001836020036101000a031916815260200191505b5060405250505090506127e4565b60a5805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612a1a5780601f106129ef57610100808354040283529160200191612a1a565b820191906000526020600020905b8154815290600101906020018083116129fd57829003601f168201915b505050505090506127e4565b600081612a3281612286565b612a73576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a1602052604090205490565b600091825260a26020526040909120546001600160a01b0391821691161490565b609a546001600160a01b031681565b612ac86127e7565b612b07576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b80612b1181612286565b612b52576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260a160205260408082204260018201558054915190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79591a2505050565b609a54600160a01b900460ff16612bef576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612c3c576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b33600081815260a8602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b60ab5481565b612cb86127e7565b612cf7576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff1615612d46576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2609a54612d9d906001600160a01b031633612d988230613547565b614559565b33ff5b6001600160a01b038116600090815260a160205260408120600101548290612e05576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a1602052604090206001015490565b7f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f081565b609a54600160a01b900460ff16612e99576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612ea48133612a90565b80612eb45750612eb48133613cac565b80612edc5750600081815260a26020526040902054612edc906001600160a01b031633613609565b612f2a576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b600083815260a260205260409020546001600160a01b0316612f4b81612286565b612f8c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612f978686866118f3565b612fa3868686866145a6565b612ff4576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6130068333612773565b82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250506001600160a01b038216905061305b613055856146d9565b8461472a565b6001600160a01b0316146130aa576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038116600081815260996020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a2600061310b87613ccd565b90506123948782613dd4565b61311f6127e7565b61315e576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff166131ae576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a1609a805460ff60a01b19169055565b609a80546001600160a01b0319166001600160a01b038316908117909155158061327457506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561324657600080fd5b505afa15801561325a573d6000803e3d6000fd5b505050506040513d602081101561327057600080fd5b5051115b6118f0576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b600081815260a2602052604090205460609082906001600160a01b0316613311576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b60a6546060906002600019610100600184161502019091160461346e57609b60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561337c57600080fd5b505afa158015613390573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156133b957600080fd5b8101908080516040519392919084600160201b8211156133d857600080fd5b9083019060208201858111156133ed57600080fd5b8251600160201b81118282018810171561340657600080fd5b82525081516020918201929091019080838360005b8381101561343357818101518382015260200161341b565b50505050905090810190601f1680156134605780820380516001836020036101000a031916815260200191505b5060405250505090506134fc565b60a6805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156134f45780601f106134c9576101008083540402835291602001916134f4565b820191906000526020600020905b8154815290600101906020018083116134d757829003601f168201915b505050505090505b61353a61350830614818565b604051806040016040528060018152602001602f60f81b81525061352b87614994565b8492919063ffffffff614a5816565b949350505050565b600590565b60006001600160a01b03831661356857506001600160a01b0381163161142f565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156135be57600080fd5b505afa1580156135d2573d6000803e3d6000fd5b505050506040513d60208110156135e857600080fd5b5051905061142f565b731820a4b7618bde71dce8cdc73aab6c95905fad2481565b6001600160a01b03918216600090815260a86020908152604080832093909416825291909152205460ff1690565b609a54600160a01b900460ff16613687576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b816136928133612a90565b806136a257506136a28133613cac565b806136ca5750600081815260a260205260409020546136ca906001600160a01b031633613609565b613718576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060a95410613769576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b0384166137b6576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b600083815260a260205260409020546001600160a01b03166137d781612286565b613818576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03808216600090815260a1602052604080822092881682528120805460018401549192909142900381613852878a613c03565b905060006138668a8363ffffffff61400316565b9050828110156138845789935061387f8b826000613e59565b6138c8565b61388e8884613c03565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8554613908576138d786614098565b6138e18c86613f7b565b60405185906001600160a01b038e1690600090600080516020615514833981519152908290a45b61391485856001613e59565b848c6001600160a01b0316896001600160a01b031660008051602061551483398151915260405160405180910390a461395e888d8d604051806020016040528060008152506145a6565b6139af576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050505050505050565b6139c56127e7565b613a04576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b6118f081614c0d565b613a156127d7565b6001600160a01b0316336001600160a01b03161480613a3e575060a0546001600160a01b031633145b613a8f576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000613a9b8330613547565b90506000821580613aab57508183115b15613aff5760008211613af8576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080613b02565b50815b60a0546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a460a054613b619085906001600160a01b031683614559565b50505050565b613b6f6127e7565b613bae576040805162461bcd60e51b815260206004820181905260248201526000805160206154c6833981519152604482015290519081900360640190fd5b81613bb881612286565b613bf9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611c5d8383613dd4565b600082613c0f81612286565b613c50576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038416600090815260a160205260408120908085613c7d57428360010154039150613c81565b8591505b612710613c9960a95484614cae90919063ffffffff16565b81613ca057fe5b04979650505050505050565b600091825260a76020526040909120546001600160a01b0391821691161490565b600081613cd981612286565b613d1a576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038316600090815260a1602052604090206001810154609c5460ab544290920391820110613d5357609d549350613d74565b609c54609d54613d69908363ffffffff614cae16565b81613d7057fe5b0493505b60ab541580613d885750609c5460ab548201105b15613dcc576000612710613da960aa54609d54614cae90919063ffffffff16565b81613db057fe5b04905080851115613dc5578085039450613dca565b600094505b505b505050919050565b6001600160a01b038216600081815260a1602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115613e4f57609a54613e4f906001600160a01b03168484614559565b611c5d8383614d07565b600083815260a260205260409020546001600160a01b031680613eb6576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b038116600090815260a16020526040812060018101549091613ede84612286565b90508415613f21578015613f0657613efc828763ffffffff61400316565b6001840155613f1c565b613f16428763ffffffff61400316565b60018401555b613f37565b613f31828763ffffffff614e3716565b60018401555b604080518781528615156020820152815189927fa2ede7ad01668310f921fcf6084901d08af350838c2744a013153e4968a7559d928290030190a250505050505050565b600081815260a260205260409020546001600160a01b03838116911614613fff5760a38054600181019091557f60859188cffe297f44dde29f2d2865634621f26215049caeb304ccba566a8b170180546001600160a01b0384166001600160a01b03199182168117909255600083815260a260205260409020805490911690911790555b5050565b600082820183811015611c03576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081815260a760205260409020546001600160a01b0316156118f057600090815260a76020526040902080546001600160a01b0319169055565b80546118f057609f8054600101908190559055565b6000811561131b57609a546001600160a01b0316614114578134101561410d576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b503461131b565b609a546001600160a01b03166141328133308663ffffffff614e7916565b8291505061131b565b60a0546040805163555ddc6560e11b81526001600160a01b0390921660048301527f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156141c257600080fd5b505afa1580156141d6573d6000803e3d6000fd5b505050506040513d60208110156141ec57600080fd5b505190506001600160a01b038116156126e557604051638d0f092560e01b815233600482018181526001600160a01b03888116602485015287811660448501526064840187905260a060848501908152865160a4860152865191861694638d0f092594938b938b938b938b939260c490910190602085019080838360005b8381101561428257818101518382015260200161426a565b50505050905090810190601f1680156142af5780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156142d257600080fd5b505af11580156142e6573d6000803e3d6000fd5b505050505050505050565b303b1590565b600054610100900460ff168061431057506143106142f1565b8061431e575060005460ff16155b6143595760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015614384576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015613fff576000805461ff00191690555050565b609a805460ff60a01b1916600160a01b179055565b63bbf81e00831115614456576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b609b8054336001600160a01b03199182161790915560a080549091166001600160a01b039590951694909417909355609c91909155609d55609e55565b61449b614ed3565b80516144ae9060a49060208401906153bc565b506118f0635b5e139f60e01b6144d1565b6144cf63780e9d6360e01b6144d1565b565b6001600160e01b03198082161415614530576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b3390565b8015611c5d576001600160a01b03831661458b576145866001600160a01b0383168263ffffffff614f8416565b611c5d565b82613b616001600160a01b038216848463ffffffff61506a16565b60006145ba846001600160a01b03166150bc565b6145c65750600161353a565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614640578181015183820152602001614628565b50505050905090810190601f16801561466d5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561468f57600080fd5b505af11580156146a3573d6000803e3d6000fd5b505050506040513d60208110156146b957600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000815160411461473d5750600061142f565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115614783576000935050505061142f565b8060ff16601b1415801561479b57508060ff16601c14155b156147ac576000935050505061142f565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015614803573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b8160008151811061487c57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106148a557fe5b60200101906001600160f81b031916908160001a90535060005b601481101561498b578260048583600c01602081106148da57fe5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106148fa57fe5b602001015160f81c60f81b82826002026002018151811061491757fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061493e57fe5b825191901a600f1690811061494f57fe5b602001015160f81c60f81b82826002026003018151811061496c57fe5b60200101906001600160f81b031916908160001a9053506001016148bf565b50949350505050565b606081806149bb5750506040805180820190915260018152600360fc1b602082015261131b565b8260005b81156149d357600101600a820491506149bf565b6060816040519080825280601f01601f191660200182016040528015614a00576020820181803883390190505b50905060001982015b8415614a4e57600a850660300160f81b82828060019003935081518110614a2c57fe5b60200101906001600160f81b031916908160001a905350600a85049450614a09565b5095945050505050565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015614aa4576020820181803883390190505b509050806000805b8751811015614afd57878181518110614ac157fe5b602001015160f81c60f81b838380600101945081518110614ade57fe5b60200101906001600160f81b031916908160001a905350600101614aac565b5060005b8651811015614b5257868181518110614b1657fe5b602001015160f81c60f81b838380600101945081518110614b3357fe5b60200101906001600160f81b031916908160001a905350600101614b01565b5060005b8551811015614ba757858181518110614b6b57fe5b602001015160f81c60f81b838380600101945081518110614b8857fe5b60200101906001600160f81b031916908160001a905350600101614b56565b5060005b8451811015614bfc57848181518110614bc057fe5b602001015160f81c60f81b838380600101945081518110614bdd57fe5b60200101906001600160f81b031916908160001a905350600101614bab565b50909b9a5050505050505050505050565b6001600160a01b038116614c525760405162461bcd60e51b81526004018080602001828103825260268152602001806154456026913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b600082614cbd5750600061142f565b82820282848281614cca57fe5b0414611c035760405162461bcd60e51b81526004018080602001828103825260218152602001806154a56021913960400191505060405180910390fd5b60a0546040805163555ddc6560e11b81526001600160a01b0390921660048301527fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b158015614d8e57600080fd5b505afa158015614da2573d6000803e3d6000fd5b505050506040513d6020811015614db857600080fd5b505190506001600160a01b03811615611c5d576040805163c9877d7b60e01b81523360048201526001600160a01b0385811660248301526044820185905291519183169163c9877d7b9160648082019260009290919082900301818387803b158015614e2357600080fd5b505af1158015612394573d6000803e3d6000fd5b6000611c0383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506150f3565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613b6190859061518a565b600054610100900460ff1680614eec5750614eec6142f1565b80614efa575060005460ff16155b614f355760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e6602e913960400191505060405180910390fd5b600054610100900460ff16158015614f60576000805460ff1961ff0019909116610100171660011790555b614f706301ffc9a760e01b6144d1565b80156118f0576000805461ff001916905550565b3031811115614fda576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114615025576040519150601f19603f3d011682016040523d82523d6000602084013e61502a565b606091505b5050905080611c5d5760405162461bcd60e51b815260040180806020018281038252603a81526020018061546b603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611c5d90849061518a565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470811580159061353a5750141592915050565b600081848411156151825760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561514757818101518382015260200161512f565b50505050905090810190601f1680156151745780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61519c826001600160a01b03166150bc565b6151ed576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061522b5780518252601f19909201916020918201910161520c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461528d576040519150601f19603f3d011682016040523d82523d6000602084013e615292565b606091505b5091509150816152e9576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115613b615780806020019051602081101561530557600080fd5b5051613b615760405162461bcd60e51b815260040180806020018281038252602a815260200180615534602a913960400191505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153835782800160ff198235161785556153b0565b828001600101855582156153b0579182015b828111156153b0578235825591602001919060010190615395565b506121fd92915061542a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106153fd57805160ff19168380011785556153b0565b828001600101855582156153b0579182015b828111156153b057825182559160200191906001019061540f565b6127e491905b808211156121fd576000815560010161543056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a7231582013b44e6afc5a7bb538a4b112863a2d1fc743d60c03c249977c5feaec0cbedecf64736f6c634300050c0032", - "compiler": { - "name": "solc", - "version": "0.5.12+commit.7709ece9.Emscripten.clang" - }, - "schemaVersion": "3.0.19", - "updatedAt": "2019-12-05T19:29:02.406Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV6.json b/packages/contracts/src/abis/PublicLock/PublicLockV6.json deleted file mode 100644 index 9dc24ab3f83..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV6.json +++ /dev/null @@ -1,1687 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "Destroy", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keyOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextAvailableNonce", - "type": "uint256" - } - ], - "name": "NonceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "oldTokenAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "PricingChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_timeAdded", - "type": "bool" - } - ], - "name": "TimestampChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BASIS_POINTS_DEN", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CANCEL_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_s", - "type": "bytes32" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "destroyLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "erc1820", - "outputs": [ - { - "internalType": "contract IERC1820Registry", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "expireKeyFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "freeTrialLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "fullRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_page", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_time", - "type": "uint256" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address[]", - "name": "_recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_expirationTimestamps", - "type": "uint256[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_nextAvailableNonce", - "type": "uint256" - } - ], - "name": "invalidateOffchainApproval", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isLockManager", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyCancelInterfaceId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "keyOwnerToNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keySoldInterfaceId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchase", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timeShared", - "type": "uint256" - } - ], - "name": "shareKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "internalType": "contract IUnlock", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - } - ], - "name": "updateKeyPricing", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x60806040526159e4806100136000396000f3fe60806040526004361061041b5760003560e01c80637c7c42531161021e578063abdf82ce11610123578063d4fac45d116100ab578063f12c6b6e1161007a578063f12c6b6e14611275578063f2fde38b146112b4578063f3fef3a3146112e7578063f7514bce14611320578063fc42b58f146113595761041b565b8063d4fac45d146111d5578063e7e2736e14611210578063e985e9c514611225578063f0ba6040146112605761041b565b8063c4d66de8116100f2578063c4d66de8146110e8578063c87b56dd1461111b578063ca51773114611145578063d1bbd49c1461118d578063d2503485146111a25761041b565b8063abdf82ce14610fba578063b3084f0814610fed578063b88d4fde14611002578063c1c98d03146110d35761041b565b8063970aaeb7116101a6578063a22cb46511610175578063a22cb46514610ee9578063a2e4cd2e14610f24578063a375cb0514610f5d578063a843a4e714610f72578063aae4b8f714610f875761041b565b8063970aaeb714610e35578063994a8a7114610e685780639d76ea5814610ea15780639f98d3cb14610eb65761041b565b80638da5cb5b116101ed5780638da5cb5b14610dcc5780638f32d59b14610de1578063936d2aa414610df657806393fd184414610e0b57806395d89b4114610e205761041b565b80637c7c425314610c875780638129fc1c14610d525780638577a6d514610d675780638d0361fc14610d915761041b565b806339f469861161032457806356e0d51f116102ac57806370a082311161027b57806370a0823114610b9a578063715018a614610bcd57806373fca6ea14610be257806374b6c10614610bf7578063782a4ade14610c0c5761041b565b806356e0d51f14610a4c5780636352211e14610a615780636d8ea5b414610a8b5780636eadde4314610abe5761041b565b80634bc5a135116102f35780634bc5a1351461092c5780634f6ccce71461095f5780634fd24d301461098957806352d6a8e41461099e578063550ef3a8146109d15761041b565b806339f46986146108165780633f33133a146108465780634136aa35146108d457806342842e0e146108e95761041b565b806311a4c03a116103a757806323b872dd1161037657806323b872dd146106e05780632f745c591461072357806330176e131461075c57806335576ad0146107d757806338af3eed146108015761041b565b806311a4c03a1461068c57806318160ddd146106a1578063183767da146106b65780632009dc65146106cb5761041b565b8063095ea7b3116103ee578063095ea7b3146105625780630aaffd2a1461059d5780630f15023b146105d057806310803b72146105e557806310e56973146106655761041b565b806301ffc9a714610420578063025e7c271461046857806306fdde03146104ae578063081812fc14610538575b600080fd5b34801561042c57600080fd5b506104546004803603602081101561044357600080fd5b50356001600160e01b031916611392565b604080519115158252519081900360200190f35b34801561047457600080fd5b506104926004803603602081101561048b57600080fd5b50356113b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104ba57600080fd5b506104c36113dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104fd5781810151838201526020016104e5565b50505050905090810190601f16801561052a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054457600080fd5b506104926004803603602081101561055b57600080fd5b503561146a565b34801561056e57600080fd5b5061059b6004803603604081101561058557600080fd5b506001600160a01b0381351690602001356114ca565b005b3480156105a957600080fd5b5061059b600480360360208110156105c057600080fd5b50356001600160a01b0316611660565b3480156105dc57600080fd5b50610492611751565b3480156105f157600080fd5b506106156004803603604081101561060857600080fd5b5080359060200135611760565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610651578181015183820152602001610639565b505050509050019250505060405180910390f35b34801561067157600080fd5b5061067a611878565b60408051918252519081900360200190f35b34801561069857600080fd5b5061067a61187e565b3480156106ad57600080fd5b5061067a611884565b3480156106c257600080fd5b5061067a61188b565b3480156106d757600080fd5b5061059b611891565b3480156106ec57600080fd5b5061059b6004803603606081101561070357600080fd5b506001600160a01b038135811691602081013590911690604001356118ab565b34801561072f57600080fd5b5061067a6004803603604081101561074657600080fd5b506001600160a01b038135169060200135611b64565b34801561076857600080fd5b5061059b6004803603602081101561077f57600080fd5b810190602081018135600160201b81111561079957600080fd5b8201836020820111156107ab57600080fd5b803590602001918460018302840111600160201b831117156107cc57600080fd5b509092509050611bc2565b3480156107e357600080fd5b5061059b600480360360208110156107fa57600080fd5b5035611c1a565b34801561080d57600080fd5b50610492611cbc565b34801561082257600080fd5b5061059b6004803603604081101561083957600080fd5b5080359060200135611ccb565b61059b6004803603608081101561085c57600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561089657600080fd5b8201836020820111156108a857600080fd5b803590602001918460018302840111600160201b831117156108c957600080fd5b509092509050611d58565b3480156108e057600080fd5b50610454612131565b3480156108f557600080fd5b5061059b6004803603606081101561090c57600080fd5b506001600160a01b03813581169160208101359091169060400135612141565b34801561093857600080fd5b5061067a6004803603602081101561094f57600080fd5b50356001600160a01b031661215c565b34801561096b57600080fd5b5061067a6004803603602081101561098257600080fd5b503561216e565b34801561099557600080fd5b5061067a6121b9565b3480156109aa57600080fd5b5061067a600480360360208110156109c157600080fd5b50356001600160a01b03166121bf565b3480156109dd57600080fd5b5061059b600480360360208110156109f457600080fd5b810190602081018135600160201b811115610a0e57600080fd5b820183602082011115610a2057600080fd5b803590602001918460018302840111600160201b83111715610a4157600080fd5b5090925090506121ca565b348015610a5857600080fd5b5061067a61221d565b348015610a6d57600080fd5b5061049260048036036020811015610a8457600080fd5b5035612223565b348015610a9757600080fd5b5061045460048036036020811015610aae57600080fd5b50356001600160a01b0316612299565b348015610aca57600080fd5b5061059b600480360360c0811015610ae157600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610b2657600080fd5b820183602082011115610b3857600080fd5b803590602001918460018302840111600160201b83111715610b5957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122b9945050505050565b348015610ba657600080fd5b5061067a60048036036020811015610bbd57600080fd5b50356001600160a01b03166123b9565b348015610bd957600080fd5b5061059b612428565b348015610bee57600080fd5b5061067a6124b9565b348015610c0357600080fd5b5061067a6124d4565b348015610c1857600080fd5b5061059b60048036036020811015610c2f57600080fd5b810190602081018135600160201b811115610c4957600080fd5b820183602082011115610c5b57600080fd5b803590602001918460018302840111600160201b83111715610c7c57600080fd5b5090925090506124da565b348015610c9357600080fd5b5061059b60048036036040811015610caa57600080fd5b810190602081018135600160201b811115610cc457600080fd5b820183602082011115610cd657600080fd5b803590602001918460208302840111600160201b83111715610cf757600080fd5b919390929091602081019035600160201b811115610d1457600080fd5b820183602082011115610d2657600080fd5b803590602001918460208302840111600160201b83111715610d4757600080fd5b509092509050612592565b348015610d5e57600080fd5b5061059b612723565b348015610d7357600080fd5b5061059b60048036036020811015610d8a57600080fd5b50356127d4565b348015610d9d57600080fd5b5061067a60048036036040811015610db457600080fd5b506001600160a01b0381358116916020013516612853565b348015610dd857600080fd5b506104926128dc565b348015610ded57600080fd5b506104546128eb565b348015610e0257600080fd5b5061067a612911565b348015610e1757600080fd5b5061067a612935565b348015610e2c57600080fd5b506104c361293b565b348015610e4157600080fd5b5061067a60048036036020811015610e5857600080fd5b50356001600160a01b0316612b2a565b348015610e7457600080fd5b5061045460048036036040811015610e8b57600080fd5b50803590602001356001600160a01b0316612b94565b348015610ead57600080fd5b50610492612bb5565b348015610ec257600080fd5b5061059b60048036036020811015610ed957600080fd5b50356001600160a01b0316612bc4565b348015610ef557600080fd5b5061059b60048036036040811015610f0c57600080fd5b506001600160a01b0381351690602001351515612ca3565b348015610f3057600080fd5b5061059b60048036036040811015610f4757600080fd5b50803590602001356001600160a01b0316612dae565b348015610f6957600080fd5b5061067a612f7d565b348015610f7e57600080fd5b5061059b612f83565b348015610f9357600080fd5b5061045460048036036020811015610faa57600080fd5b50356001600160a01b0316613072565b348015610fc657600080fd5b5061067a60048036036020811015610fdd57600080fd5b50356001600160a01b0316613085565b348015610ff957600080fd5b5061067a61310a565b34801561100e57600080fd5b5061059b6004803603608081101561102557600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561105f57600080fd5b82018360208201111561107157600080fd5b803590602001918460018302840111600160201b8311171561109257600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061312e945050505050565b3480156110df57600080fd5b5061059b6132e1565b3480156110f457600080fd5b5061059b6004803603602081101561110b57600080fd5b50356001600160a01b03166133b0565b34801561112757600080fd5b506104c36004803603602081101561113e57600080fd5b50356134a2565b34801561115157600080fd5b5061059b6004803603608081101561116857600080fd5b506001600160a01b038135169060ff602082013516906040810135906060013561372f565b34801561119957600080fd5b5061067a613872565b3480156111ae57600080fd5b5061059b600480360360208110156111c557600080fd5b50356001600160a01b0316613877565b3480156111e157600080fd5b5061067a600480360360408110156111f857600080fd5b506001600160a01b0381358116916020013516613906565b34801561121c57600080fd5b506104926139b0565b34801561123157600080fd5b506104546004803603604081101561124857600080fd5b506001600160a01b03813581169160200135166139c8565b34801561126c57600080fd5b5061059b6139f6565b34801561128157600080fd5b5061059b6004803603606081101561129857600080fd5b506001600160a01b038135169060208101359060400135613a34565b3480156112c057600080fd5b5061059b600480360360208110156112d757600080fd5b50356001600160a01b0316613dba565b3480156112f357600080fd5b5061059b6004803603604081101561130a57600080fd5b506001600160a01b038135169060200135613e0a565b34801561132c57600080fd5b5061059b6004803603604081101561134357600080fd5b506001600160a01b038135169060200135613f64565b34801561136557600080fd5b5061067a6004803603604081101561137c57600080fd5b506001600160a01b038135169060200135614000565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b60a481815481106113c257fe5b6000918252602090912001546001600160a01b0316905081565b60a5805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156114625780601f1061143757610100808354040283529160200191611462565b820191906000526020600020905b81548152906001019060200180831161144557829003601f168201915b505050505081565b600081815260a860205260408120546001600160a01b0316806114c4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b92915050565b609a54600160a01b900460ff1661151a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806115258133612b94565b80611535575061153581336140a9565b8061155d5750600081815260a3602052604090205461155d906001600160a01b0316336139c8565b6115ab576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b03841614156115f8576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260a86020908152604080832080546001600160a01b0319166001600160a01b0388811691821790925560a3909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6116686128dc565b6001600160a01b0316336001600160a01b03161480611691575060a1546001600160a01b031633145b6116e2576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b03811661172f576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b60a180546001600160a01b0319166001600160a01b0392909216919091179055565b609c546001600160a01b031681565b60a4546060906117ad576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60a45482908482029060009082840111156117d0575060a45481810392506117d5565b508082015b606083604051908082528060200260200182016040528015611801578160200160208202803883390190505b5090506000835b8381101561186b5760a4818154811061181d57fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061184757fe5b6001600160a01b039092166020928302919091019091015260019182019101611808565b5090979650505050505050565b609e5481565b609d5481565b60a0545b90565b60aa5481565b600061189c336140ca565b90506118a833826141d1565b50565b609a54600160a01b900460ff166118fb576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8261190581612299565b611946576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b816119518133612b94565b80611961575061196181336140a9565b806119895750600081815260a36020526040902054611989906001600160a01b0316336139c8565b6119d7576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060aa5410611a28576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611a75576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611a82866000614000565b6001600160a01b03808816600090815260a2602052604080822092891682528120825460018201549495509293909291611abf9083908790614256565b8254611ad5578354808455611ad5908a90614378565b428111611af9576001808501549084015583548355611af48989614378565b611b16565b6001840154611b109042830363ffffffff6143ff16565b60018401555b42600185015560008455611b2988614459565b87896001600160a01b03168b6001600160a01b031660008051602061596683398151915260405160405180910390a450505050505050505050565b60008115611bb2576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611bbb83612b2a565b9392505050565b611bca6128eb565b611c09576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b611c1560a783836156f1565b505050565b336000908152609960205260409020548111611c72576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260996020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b60a1546001600160a01b031681565b611cd36128eb565b611d12576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a160ac9190915560ab55565b609a54600160a01b900460ff16611da8576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b60a054609f5411611df0576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416611e3d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260a2602052604090208054611e7257611e6481614494565b611e72858260000154614378565b42816001015410611e9e57609d546001820154611e949163ffffffff6143ff16565b6001820155611ea9565b609d54420160018201555b609e54609c5460408051630cb175e360e01b81526001600160a01b03898116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015611f0257600080fd5b505afa158015611f16573d6000803e3d6000fd5b505050506040513d6040811015611f2c57600080fd5b508051602090910151909350915080831115611f4a57506000611f4e565b8290035b8215611fc157609c5460408051633652466360e01b8152600481018690526024810185905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015611fa857600080fd5b505af1158015611fbc573d6000803e3d6000fd5b505050505b609c546001600160a01b031663939d9f1f82611fdc8a612299565b611fe7576000611fe9565b895b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561203857600080fd5b505af115801561204c573d6000803e3d6000fd5b505085546040519092506001600160a01b038b169150600090600080516020615966833981519152908290a4609a546001600160a01b0316156120d657808910156120d3576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b50875b60006120e1826144a9565b90506121258989838a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061453792505050565b50505050505050505050565b609a54600160a01b900460ff1681565b611c158383836040518060200160405280600081525061312e565b60996020526000908152604090205481565b600060a05482106121b5576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b61271081565b60006114c4826140ca565b6121d26128eb565b612211576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b611c1560a583836156f1565b60ab5481565b600081815260a3602052604081205482906001600160a01b031661227c576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b5050600090815260a360205260409020546001600160a01b031690565b6001600160a01b0316600090815260a26020526040902060010154421090565b600054610100900460ff16806122d257506122d26146ed565b806122e0575060005460ff16155b61231b5760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff16158015612346576000805460ff1961ff0019909116610100171660011790555b61234f876133b0565b612358856146f3565b6123606147c2565b61236c878786866147d7565b6123758261486d565b61237d614899565b6123856148ab565b61238e876148b3565b61239e6380ac58cd60e01b6148d1565b80156123b0576000805461ff00191690555b50505050505050565b60006001600160a01b038216612408576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61241182612299565b61241c57600061241f565b60015b60ff1692915050565b6124306128eb565b61246f576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6066546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606680546001600160a01b0319169055565b6040518060256157f482396025019050604051809103902081565b609f5481565b6124e26128eb565b612521576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b61252d60a683836156f1565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b61259a6128eb565b6125d9576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b60005b8381101561271c5760008585838181106125f257fe5b905060200201356001600160a01b03169050600084848481811061261257fe5b60200291909101359150506001600160a01b03821661266a576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260a260205260409020600181015482116126cd576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b6126d681614494565b6126e4838260000154614378565b6001810182905580546040516001600160a01b03851690600090600080516020615966833981519152908290a45050506001016125dc565b5050505050565b600054610100900460ff168061273c575061273c6146ed565b8061274a575060005460ff16155b6127855760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff161580156127b0576000805460ff1961ff0019909116610100171660011790555b6127c06301ffc9a760e01b6148d1565b80156118a8576000805461ff001916905550565b6127dc6128eb565b61281b576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a160aa55565b60003060405180806157f460259139604080519182900360250182206001600160a01b03881660009081526099602090815290839020546bffffffffffffffffffffffff19606097881b811683870152603486019390935260548501529487901b1660748301528051606881840301815260889092019052805192019190912091505092915050565b6066546001600160a01b031690565b6066546000906001600160a01b0316612902614955565b6001600160a01b031614905090565b7fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f6881565b60a45490565b60a65460609060026000196101006001841615020190911604612a9857609c60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156129a657600080fd5b505afa1580156129ba573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156129e357600080fd5b8101908080516040519392919084600160201b821115612a0257600080fd5b908301906020820185811115612a1757600080fd5b8251600160201b811182820188101715612a3057600080fd5b82525081516020918201929091019080838360005b83811015612a5d578181015183820152602001612a45565b50505050905090810190601f168015612a8a5780820380516001836020036101000a031916815260200191505b506040525050509050611888565b60a6805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612b1e5780601f10612af357610100808354040283529160200191612b1e565b820191906000526020600020905b815481529060010190602001808311612b0157829003601f168201915b50505050509050611888565b600081612b3681612299565b612b77576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a2602052604090205490565b600091825260a36020526040909120546001600160a01b0391821691161490565b609a546001600160a01b031681565b612bcc6128eb565b612c0b576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b80612c1581612299565b612c56576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260a260205260408082204260018201558054915190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79591a2505050565b609a54600160a01b900460ff16612cf3576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612d40576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b33600081815260a9602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612db733613072565b612df25760405162461bcd60e51b815260040180806020018281038252603b81526020018061583f603b913960400191505060405180910390fd5b609a54600160a01b900460ff16612e42576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609e54609a546001600160a01b039081169083161580612ec657506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612e9857600080fd5b505afa158015612eac573d6000803e3d6000fd5b505050506040513d6020811015612ec257600080fd5b5051115b612f07576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b609e849055609a80546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b60ac5481565b612f8b6128eb565b612fca576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff1615613019576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b60408051478152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2609a5461306f906001600160a01b03163361306a8230613906565b614959565b33ff5b60006114c4609b8363ffffffff6149a616565b6001600160a01b038116600090815260a2602052604081206001015482906130ea576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a2602052604090206001015490565b7f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f081565b609a54600160a01b900460ff1661317e576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b816131898133612b94565b80613199575061319981336140a9565b806131c15750600081815260a360205260409020546131c1906001600160a01b0316336139c8565b61320f576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b600083815260a360205260409020546001600160a01b031661323081612299565b613271576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b61327c8686866118ab565b61328886868686614a0d565b6132d9576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6132e96128eb565b613328576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff16613378576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a1609a805460ff60a01b19169055565b600054610100900460ff16806133c957506133c96146ed565b806133d7575060005460ff16155b6134125760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff1615801561343d576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801561349e576000805461ff00191690555b5050565b600081815260a3602052604090205460609082906001600160a01b03166134fe576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b60a7546060906002600019610100600184161502019091160461365b57609c60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561356957600080fd5b505afa15801561357d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156135a657600080fd5b8101908080516040519392919084600160201b8211156135c557600080fd5b9083019060208201858111156135da57600080fd5b8251600160201b8111828201881017156135f357600080fd5b82525081516020918201929091019080838360005b83811015613620578181015183820152602001613608565b50505050905090810190601f16801561364d5780820380516001836020036101000a031916815260200191505b5060405250505090506136e9565b60a7805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156136e15780601f106136b6576101008083540402835291602001916136e1565b820191906000526020600020905b8154815290600101906020018083116136c457829003601f168201915b505050505090505b6137276136f530614b40565b604051806040016040528060018152602001602f60f81b81525061371887614cbc565b8492919063ffffffff614d8016565b949350505050565b6137398433612853565b84848484836001600160a01b0316600161375287614f35565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156137ac573d6000803e3d6000fd5b505050602060405103516001600160a01b031614613805576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260996020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006138668a6140ca565b90506121258a826141d1565b600690565b61387f6128eb565b6138be576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6138cf609b8263ffffffff614f8616565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b60006001600160a01b03831661392757506001600160a01b038116316114c4565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561397d57600080fd5b505afa158015613991573d6000803e3d6000fd5b505050506040513d60208110156139a757600080fd5b505190506114c4565b731820a4b7618bde71dce8cdc73aab6c95905fad2481565b6001600160a01b03918216600090815260a96020908152604080832093909416825291909152205460ff1690565b613a07609b3363ffffffff61500716565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b609a54600160a01b900460ff16613a84576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613a8f8133612b94565b80613a9f5750613a9f81336140a9565b80613ac75750600081815260a36020526040902054613ac7906001600160a01b0316336139c8565b613b15576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060aa5410613b66576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613bb3576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b600083815260a360205260409020546001600160a01b0316613bd481612299565b613c15576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03808216600090815260a2602052604080822092881682528120805460018401549192909142900381613c4f878a614000565b90506000613c638a8363ffffffff6143ff16565b905082811015613c8157899350613c7c8b826000614256565b613cc5565b613c8b8884614000565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8554613d0557613cd486614494565b613cde8c86614378565b60405185906001600160a01b038e1690600090600080516020615966833981519152908290a45b613d1185856001614256565b848c6001600160a01b0316896001600160a01b031660008051602061596683398151915260405160405180910390a4613d5b888d8d60405180602001604052806000815250614a0d565b613dac576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050505050505050565b613dc26128eb565b613e01576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6118a88161506e565b613e126128dc565b6001600160a01b0316336001600160a01b03161480613e3b575060a1546001600160a01b031633145b613e8c576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000613e988330613906565b90506000821580613ea857508183115b15613efc5760008211613ef5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080613eff565b50815b60a1546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a460a154613f5e9085906001600160a01b031683614959565b50505050565b613f6c6128eb565b613fab576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b81613fb581612299565b613ff6576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611c1583836141d1565b60008261400c81612299565b61404d576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038416600090815260a26020526040812090808561407a5742836001015403915061407e565b8591505b61271061409660aa548461510f90919063ffffffff16565b8161409d57fe5b04979650505050505050565b600091825260a86020526040909120546001600160a01b0391821691161490565b6000816140d681612299565b614117576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038316600090815260a2602052604090206001810154609d5460ac54429092039182011061415057609e549350614171565b609d54609e54614166908363ffffffff61510f16565b8161416d57fe5b0493505b60ac5415806141855750609d5460ac548201105b156141c95760006127106141a660ab54609e5461510f90919063ffffffff16565b816141ad57fe5b049050808511156141c25780850394506141c7565b600094505b505b505050919050565b6001600160a01b038216600081815260a2602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a4426001820155811561424c57609a5461424c906001600160a01b03168484614959565b611c158383615168565b600083815260a360205260409020546001600160a01b0316806142b3576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b038116600090815260a260205260408120600181015490916142db84612299565b9050841561431e578015614303576142f9828763ffffffff6143ff16565b6001840155614319565b614313428763ffffffff6143ff16565b60018401555b614334565b61432e828763ffffffff61529816565b60018401555b604080518781528615156020820152815189927fa2ede7ad01668310f921fcf6084901d08af350838c2744a013153e4968a7559d928290030190a250505050505050565b600081815260a360205260409020546001600160a01b0383811691161461349e5760a48054600181019091557fe434dc35da084cf8d7e8186688ea2dacb53db7003d427af3abf351bd9d0a4e8d0180546001600160a01b0384166001600160a01b03199182168117909255600083815260a360205260409020805490911690911790555050565b600082820183811015611bbb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081815260a860205260409020546001600160a01b0316156118a857600090815260a86020526040902080546001600160a01b0319169055565b80546118a85760a08054600101908190559055565b600081156113b057609a546001600160a01b03166145105781341015614509576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b50346113b0565b609a546001600160a01b031661452e8133308663ffffffff6152da16565b829150506113b0565b60a1546040805163555ddc6560e11b81526001600160a01b0390921660048301527f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156145be57600080fd5b505afa1580156145d2573d6000803e3d6000fd5b505050506040513d60208110156145e857600080fd5b505190506001600160a01b0381161561271c57604051638d0f092560e01b815233600482018181526001600160a01b03888116602485015287811660448501526064840187905260a060848501908152865160a4860152865191861694638d0f092594938b938b938b938b939260c490910190602085019080838360005b8381101561467e578181015183820152602001614666565b50505050905090810190601f1680156146ab5780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156146ce57600080fd5b505af11580156146e2573d6000803e3d6000fd5b505050505050505050565b303b1590565b609a80546001600160a01b0319166001600160a01b038316908117909155158061478157506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475357600080fd5b505afa158015614767573d6000803e3d6000fd5b505050506040513d602081101561477d57600080fd5b5051115b6118a8576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b609a805460ff60a01b1916600160a01b179055565b63bbf81e00831115614830576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b609c8054336001600160a01b03199182161790915560a180549091166001600160a01b039590951694909417909355609d91909155609e55609f55565b614875612723565b80516148889060a590602084019061576b565b506118a8635b5e139f60e01b6148d1565b6148a963780e9d6360e01b6148d1565b565b6103e860ab55565b6148bc81613072565b6118a8576118a8609b8263ffffffff614f8616565b6001600160e01b03198082161415614930576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b3390565b8015611c15576001600160a01b03831661498b576149866001600160a01b0383168263ffffffff61533416565b611c15565b82613f5e6001600160a01b038216848463ffffffff61541916565b60006001600160a01b0382166149ed5760405162461bcd60e51b81526004018080602001828103825260228152602001806159166022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000614a21846001600160a01b031661546b565b614a2d57506001613727565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614aa7578181015183820152602001614a8f565b50505050905090810190601f168015614ad45780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614af657600080fd5b505af1158015614b0a573d6000803e3d6000fd5b505050506040513d6020811015614b2057600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b81600081518110614ba457fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614bcd57fe5b60200101906001600160f81b031916908160001a90535060005b6014811015614cb3578260048583600c0160208110614c0257fe5b1a60f81b6001600160f81b031916901c60f81c60ff1681518110614c2257fe5b602001015160f81c60f81b828260020260020181518110614c3f57fe5b60200101906001600160f81b031916908160001a905350828482600c0160208110614c6657fe5b825191901a600f16908110614c7757fe5b602001015160f81c60f81b828260020260030181518110614c9457fe5b60200101906001600160f81b031916908160001a905350600101614be7565b50949350505050565b60608180614ce35750506040805180820190915260018152600360fc1b60208201526113b0565b8260005b8115614cfb57600101600a82049150614ce7565b6060816040519080825280601f01601f191660200182016040528015614d28576020820181803883390190505b50905060001982015b8415614d7657600a850660300160f81b82828060019003935081518110614d5457fe5b60200101906001600160f81b031916908160001a905350600a85049450614d31565b5095945050505050565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015614dcc576020820181803883390190505b509050806000805b8751811015614e2557878181518110614de957fe5b602001015160f81c60f81b838380600101945081518110614e0657fe5b60200101906001600160f81b031916908160001a905350600101614dd4565b5060005b8651811015614e7a57868181518110614e3e57fe5b602001015160f81c60f81b838380600101945081518110614e5b57fe5b60200101906001600160f81b031916908160001a905350600101614e29565b5060005b8551811015614ecf57858181518110614e9357fe5b602001015160f81c60f81b838380600101945081518110614eb057fe5b60200101906001600160f81b031916908160001a905350600101614e7e565b5060005b8451811015614f2457848181518110614ee857fe5b602001015160f81c60f81b838380600101945081518110614f0557fe5b60200101906001600160f81b031916908160001a905350600101614ed3565b50909b9a5050505050505050505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b614f9082826149a6565b15614fe2576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b61501182826149a6565b61504c5760405162461bcd60e51b81526004018080602001828103825260218152602001806158b46021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6001600160a01b0381166150b35760405162461bcd60e51b81526004018080602001828103825260268152602001806158196026913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b60008261511e575060006114c4565b8282028284828161512b57fe5b0414611bbb5760405162461bcd60e51b81526004018080602001828103825260218152602001806158d56021913960400191505060405180910390fd5b60a1546040805163555ddc6560e11b81526001600160a01b0390921660048301527fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156151ef57600080fd5b505afa158015615203573d6000803e3d6000fd5b505050506040513d602081101561521957600080fd5b505190506001600160a01b03811615611c15576040805163c9877d7b60e01b81523360048201526001600160a01b0385811660248301526044820185905291519183169163c9877d7b9160648082019260009290919082900301818387803b15801561528457600080fd5b505af11580156123b0573d6000803e3d6000fd5b6000611bbb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506154a2565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613f5e908590615539565b80471015615389576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146153d4576040519150601f19603f3d011682016040523d82523d6000602084013e6153d9565b606091505b5050905080611c155760405162461bcd60e51b815260040180806020018281038252603a81526020018061587a603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611c15908490615539565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906137275750141592915050565b600081848411156155315760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156154f65781810151838201526020016154de565b50505050905090810190601f1680156155235780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61554b826001600160a01b031661546b565b61559c576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106155da5780518252601f1990920191602091820191016155bb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461563c576040519150601f19603f3d011682016040523d82523d6000602084013e615641565b606091505b509150915081615698576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115613f5e578080602001905160208110156156b457600080fd5b5051613f5e5760405162461bcd60e51b815260040180806020018281038252602a815260200180615986602a913960400191505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157325782800160ff1982351617855561575f565b8280016001018555821561575f579182015b8281111561575f578235825591602001919060010190615744565b506121b59291506157d9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157ac57805160ff191683800117855561575f565b8280016001018555821561575f579182015b8281111561575f5782518255916020019190600101906157be565b61188891905b808211156121b557600081556001016157df56fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158200699dda614bcab2e903ef2411b51464fc64ec2c573008b8f0d5cc966a4a6001164736f6c634300050e0032", - "deployedBytecode": "0x60806040526004361061041b5760003560e01c80637c7c42531161021e578063abdf82ce11610123578063d4fac45d116100ab578063f12c6b6e1161007a578063f12c6b6e14611275578063f2fde38b146112b4578063f3fef3a3146112e7578063f7514bce14611320578063fc42b58f146113595761041b565b8063d4fac45d146111d5578063e7e2736e14611210578063e985e9c514611225578063f0ba6040146112605761041b565b8063c4d66de8116100f2578063c4d66de8146110e8578063c87b56dd1461111b578063ca51773114611145578063d1bbd49c1461118d578063d2503485146111a25761041b565b8063abdf82ce14610fba578063b3084f0814610fed578063b88d4fde14611002578063c1c98d03146110d35761041b565b8063970aaeb7116101a6578063a22cb46511610175578063a22cb46514610ee9578063a2e4cd2e14610f24578063a375cb0514610f5d578063a843a4e714610f72578063aae4b8f714610f875761041b565b8063970aaeb714610e35578063994a8a7114610e685780639d76ea5814610ea15780639f98d3cb14610eb65761041b565b80638da5cb5b116101ed5780638da5cb5b14610dcc5780638f32d59b14610de1578063936d2aa414610df657806393fd184414610e0b57806395d89b4114610e205761041b565b80637c7c425314610c875780638129fc1c14610d525780638577a6d514610d675780638d0361fc14610d915761041b565b806339f469861161032457806356e0d51f116102ac57806370a082311161027b57806370a0823114610b9a578063715018a614610bcd57806373fca6ea14610be257806374b6c10614610bf7578063782a4ade14610c0c5761041b565b806356e0d51f14610a4c5780636352211e14610a615780636d8ea5b414610a8b5780636eadde4314610abe5761041b565b80634bc5a135116102f35780634bc5a1351461092c5780634f6ccce71461095f5780634fd24d301461098957806352d6a8e41461099e578063550ef3a8146109d15761041b565b806339f46986146108165780633f33133a146108465780634136aa35146108d457806342842e0e146108e95761041b565b806311a4c03a116103a757806323b872dd1161037657806323b872dd146106e05780632f745c591461072357806330176e131461075c57806335576ad0146107d757806338af3eed146108015761041b565b806311a4c03a1461068c57806318160ddd146106a1578063183767da146106b65780632009dc65146106cb5761041b565b8063095ea7b3116103ee578063095ea7b3146105625780630aaffd2a1461059d5780630f15023b146105d057806310803b72146105e557806310e56973146106655761041b565b806301ffc9a714610420578063025e7c271461046857806306fdde03146104ae578063081812fc14610538575b600080fd5b34801561042c57600080fd5b506104546004803603602081101561044357600080fd5b50356001600160e01b031916611392565b604080519115158252519081900360200190f35b34801561047457600080fd5b506104926004803603602081101561048b57600080fd5b50356113b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104ba57600080fd5b506104c36113dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104fd5781810151838201526020016104e5565b50505050905090810190601f16801561052a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054457600080fd5b506104926004803603602081101561055b57600080fd5b503561146a565b34801561056e57600080fd5b5061059b6004803603604081101561058557600080fd5b506001600160a01b0381351690602001356114ca565b005b3480156105a957600080fd5b5061059b600480360360208110156105c057600080fd5b50356001600160a01b0316611660565b3480156105dc57600080fd5b50610492611751565b3480156105f157600080fd5b506106156004803603604081101561060857600080fd5b5080359060200135611760565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610651578181015183820152602001610639565b505050509050019250505060405180910390f35b34801561067157600080fd5b5061067a611878565b60408051918252519081900360200190f35b34801561069857600080fd5b5061067a61187e565b3480156106ad57600080fd5b5061067a611884565b3480156106c257600080fd5b5061067a61188b565b3480156106d757600080fd5b5061059b611891565b3480156106ec57600080fd5b5061059b6004803603606081101561070357600080fd5b506001600160a01b038135811691602081013590911690604001356118ab565b34801561072f57600080fd5b5061067a6004803603604081101561074657600080fd5b506001600160a01b038135169060200135611b64565b34801561076857600080fd5b5061059b6004803603602081101561077f57600080fd5b810190602081018135600160201b81111561079957600080fd5b8201836020820111156107ab57600080fd5b803590602001918460018302840111600160201b831117156107cc57600080fd5b509092509050611bc2565b3480156107e357600080fd5b5061059b600480360360208110156107fa57600080fd5b5035611c1a565b34801561080d57600080fd5b50610492611cbc565b34801561082257600080fd5b5061059b6004803603604081101561083957600080fd5b5080359060200135611ccb565b61059b6004803603608081101561085c57600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561089657600080fd5b8201836020820111156108a857600080fd5b803590602001918460018302840111600160201b831117156108c957600080fd5b509092509050611d58565b3480156108e057600080fd5b50610454612131565b3480156108f557600080fd5b5061059b6004803603606081101561090c57600080fd5b506001600160a01b03813581169160208101359091169060400135612141565b34801561093857600080fd5b5061067a6004803603602081101561094f57600080fd5b50356001600160a01b031661215c565b34801561096b57600080fd5b5061067a6004803603602081101561098257600080fd5b503561216e565b34801561099557600080fd5b5061067a6121b9565b3480156109aa57600080fd5b5061067a600480360360208110156109c157600080fd5b50356001600160a01b03166121bf565b3480156109dd57600080fd5b5061059b600480360360208110156109f457600080fd5b810190602081018135600160201b811115610a0e57600080fd5b820183602082011115610a2057600080fd5b803590602001918460018302840111600160201b83111715610a4157600080fd5b5090925090506121ca565b348015610a5857600080fd5b5061067a61221d565b348015610a6d57600080fd5b5061049260048036036020811015610a8457600080fd5b5035612223565b348015610a9757600080fd5b5061045460048036036020811015610aae57600080fd5b50356001600160a01b0316612299565b348015610aca57600080fd5b5061059b600480360360c0811015610ae157600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610b2657600080fd5b820183602082011115610b3857600080fd5b803590602001918460018302840111600160201b83111715610b5957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122b9945050505050565b348015610ba657600080fd5b5061067a60048036036020811015610bbd57600080fd5b50356001600160a01b03166123b9565b348015610bd957600080fd5b5061059b612428565b348015610bee57600080fd5b5061067a6124b9565b348015610c0357600080fd5b5061067a6124d4565b348015610c1857600080fd5b5061059b60048036036020811015610c2f57600080fd5b810190602081018135600160201b811115610c4957600080fd5b820183602082011115610c5b57600080fd5b803590602001918460018302840111600160201b83111715610c7c57600080fd5b5090925090506124da565b348015610c9357600080fd5b5061059b60048036036040811015610caa57600080fd5b810190602081018135600160201b811115610cc457600080fd5b820183602082011115610cd657600080fd5b803590602001918460208302840111600160201b83111715610cf757600080fd5b919390929091602081019035600160201b811115610d1457600080fd5b820183602082011115610d2657600080fd5b803590602001918460208302840111600160201b83111715610d4757600080fd5b509092509050612592565b348015610d5e57600080fd5b5061059b612723565b348015610d7357600080fd5b5061059b60048036036020811015610d8a57600080fd5b50356127d4565b348015610d9d57600080fd5b5061067a60048036036040811015610db457600080fd5b506001600160a01b0381358116916020013516612853565b348015610dd857600080fd5b506104926128dc565b348015610ded57600080fd5b506104546128eb565b348015610e0257600080fd5b5061067a612911565b348015610e1757600080fd5b5061067a612935565b348015610e2c57600080fd5b506104c361293b565b348015610e4157600080fd5b5061067a60048036036020811015610e5857600080fd5b50356001600160a01b0316612b2a565b348015610e7457600080fd5b5061045460048036036040811015610e8b57600080fd5b50803590602001356001600160a01b0316612b94565b348015610ead57600080fd5b50610492612bb5565b348015610ec257600080fd5b5061059b60048036036020811015610ed957600080fd5b50356001600160a01b0316612bc4565b348015610ef557600080fd5b5061059b60048036036040811015610f0c57600080fd5b506001600160a01b0381351690602001351515612ca3565b348015610f3057600080fd5b5061059b60048036036040811015610f4757600080fd5b50803590602001356001600160a01b0316612dae565b348015610f6957600080fd5b5061067a612f7d565b348015610f7e57600080fd5b5061059b612f83565b348015610f9357600080fd5b5061045460048036036020811015610faa57600080fd5b50356001600160a01b0316613072565b348015610fc657600080fd5b5061067a60048036036020811015610fdd57600080fd5b50356001600160a01b0316613085565b348015610ff957600080fd5b5061067a61310a565b34801561100e57600080fd5b5061059b6004803603608081101561102557600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561105f57600080fd5b82018360208201111561107157600080fd5b803590602001918460018302840111600160201b8311171561109257600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061312e945050505050565b3480156110df57600080fd5b5061059b6132e1565b3480156110f457600080fd5b5061059b6004803603602081101561110b57600080fd5b50356001600160a01b03166133b0565b34801561112757600080fd5b506104c36004803603602081101561113e57600080fd5b50356134a2565b34801561115157600080fd5b5061059b6004803603608081101561116857600080fd5b506001600160a01b038135169060ff602082013516906040810135906060013561372f565b34801561119957600080fd5b5061067a613872565b3480156111ae57600080fd5b5061059b600480360360208110156111c557600080fd5b50356001600160a01b0316613877565b3480156111e157600080fd5b5061067a600480360360408110156111f857600080fd5b506001600160a01b0381358116916020013516613906565b34801561121c57600080fd5b506104926139b0565b34801561123157600080fd5b506104546004803603604081101561124857600080fd5b506001600160a01b03813581169160200135166139c8565b34801561126c57600080fd5b5061059b6139f6565b34801561128157600080fd5b5061059b6004803603606081101561129857600080fd5b506001600160a01b038135169060208101359060400135613a34565b3480156112c057600080fd5b5061059b600480360360208110156112d757600080fd5b50356001600160a01b0316613dba565b3480156112f357600080fd5b5061059b6004803603604081101561130a57600080fd5b506001600160a01b038135169060200135613e0a565b34801561132c57600080fd5b5061059b6004803603604081101561134357600080fd5b506001600160a01b038135169060200135613f64565b34801561136557600080fd5b5061067a6004803603604081101561137c57600080fd5b506001600160a01b038135169060200135614000565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b60a481815481106113c257fe5b6000918252602090912001546001600160a01b0316905081565b60a5805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156114625780601f1061143757610100808354040283529160200191611462565b820191906000526020600020905b81548152906001019060200180831161144557829003601f168201915b505050505081565b600081815260a860205260408120546001600160a01b0316806114c4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b92915050565b609a54600160a01b900460ff1661151a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806115258133612b94565b80611535575061153581336140a9565b8061155d5750600081815260a3602052604090205461155d906001600160a01b0316336139c8565b6115ab576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b03841614156115f8576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260a86020908152604080832080546001600160a01b0319166001600160a01b0388811691821790925560a3909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6116686128dc565b6001600160a01b0316336001600160a01b03161480611691575060a1546001600160a01b031633145b6116e2576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b03811661172f576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b60a180546001600160a01b0319166001600160a01b0392909216919091179055565b609c546001600160a01b031681565b60a4546060906117ad576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60a45482908482029060009082840111156117d0575060a45481810392506117d5565b508082015b606083604051908082528060200260200182016040528015611801578160200160208202803883390190505b5090506000835b8381101561186b5760a4818154811061181d57fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061184757fe5b6001600160a01b039092166020928302919091019091015260019182019101611808565b5090979650505050505050565b609e5481565b609d5481565b60a0545b90565b60aa5481565b600061189c336140ca565b90506118a833826141d1565b50565b609a54600160a01b900460ff166118fb576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8261190581612299565b611946576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b816119518133612b94565b80611961575061196181336140a9565b806119895750600081815260a36020526040902054611989906001600160a01b0316336139c8565b6119d7576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060aa5410611a28576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611a75576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611a82866000614000565b6001600160a01b03808816600090815260a2602052604080822092891682528120825460018201549495509293909291611abf9083908790614256565b8254611ad5578354808455611ad5908a90614378565b428111611af9576001808501549084015583548355611af48989614378565b611b16565b6001840154611b109042830363ffffffff6143ff16565b60018401555b42600185015560008455611b2988614459565b87896001600160a01b03168b6001600160a01b031660008051602061596683398151915260405160405180910390a450505050505050505050565b60008115611bb2576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611bbb83612b2a565b9392505050565b611bca6128eb565b611c09576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b611c1560a783836156f1565b505050565b336000908152609960205260409020548111611c72576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260996020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b60a1546001600160a01b031681565b611cd36128eb565b611d12576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a160ac9190915560ab55565b609a54600160a01b900460ff16611da8576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b60a054609f5411611df0576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416611e3d576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260a2602052604090208054611e7257611e6481614494565b611e72858260000154614378565b42816001015410611e9e57609d546001820154611e949163ffffffff6143ff16565b6001820155611ea9565b609d54420160018201555b609e54609c5460408051630cb175e360e01b81526001600160a01b03898116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015611f0257600080fd5b505afa158015611f16573d6000803e3d6000fd5b505050506040513d6040811015611f2c57600080fd5b508051602090910151909350915080831115611f4a57506000611f4e565b8290035b8215611fc157609c5460408051633652466360e01b8152600481018690526024810185905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015611fa857600080fd5b505af1158015611fbc573d6000803e3d6000fd5b505050505b609c546001600160a01b031663939d9f1f82611fdc8a612299565b611fe7576000611fe9565b895b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561203857600080fd5b505af115801561204c573d6000803e3d6000fd5b505085546040519092506001600160a01b038b169150600090600080516020615966833981519152908290a4609a546001600160a01b0316156120d657808910156120d3576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b50875b60006120e1826144a9565b90506121258989838a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061453792505050565b50505050505050505050565b609a54600160a01b900460ff1681565b611c158383836040518060200160405280600081525061312e565b60996020526000908152604090205481565b600060a05482106121b5576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b61271081565b60006114c4826140ca565b6121d26128eb565b612211576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b611c1560a583836156f1565b60ab5481565b600081815260a3602052604081205482906001600160a01b031661227c576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b5050600090815260a360205260409020546001600160a01b031690565b6001600160a01b0316600090815260a26020526040902060010154421090565b600054610100900460ff16806122d257506122d26146ed565b806122e0575060005460ff16155b61231b5760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff16158015612346576000805460ff1961ff0019909116610100171660011790555b61234f876133b0565b612358856146f3565b6123606147c2565b61236c878786866147d7565b6123758261486d565b61237d614899565b6123856148ab565b61238e876148b3565b61239e6380ac58cd60e01b6148d1565b80156123b0576000805461ff00191690555b50505050505050565b60006001600160a01b038216612408576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b61241182612299565b61241c57600061241f565b60015b60ff1692915050565b6124306128eb565b61246f576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6066546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606680546001600160a01b0319169055565b6040518060256157f482396025019050604051809103902081565b609f5481565b6124e26128eb565b612521576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b61252d60a683836156f1565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b61259a6128eb565b6125d9576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b60005b8381101561271c5760008585838181106125f257fe5b905060200201356001600160a01b03169050600084848481811061261257fe5b60200291909101359150506001600160a01b03821661266a576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038216600090815260a260205260409020600181015482116126cd576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b6126d681614494565b6126e4838260000154614378565b6001810182905580546040516001600160a01b03851690600090600080516020615966833981519152908290a45050506001016125dc565b5050505050565b600054610100900460ff168061273c575061273c6146ed565b8061274a575060005460ff16155b6127855760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff161580156127b0576000805460ff1961ff0019909116610100171660011790555b6127c06301ffc9a760e01b6148d1565b80156118a8576000805461ff001916905550565b6127dc6128eb565b61281b576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a160aa55565b60003060405180806157f460259139604080519182900360250182206001600160a01b03881660009081526099602090815290839020546bffffffffffffffffffffffff19606097881b811683870152603486019390935260548501529487901b1660748301528051606881840301815260889092019052805192019190912091505092915050565b6066546001600160a01b031690565b6066546000906001600160a01b0316612902614955565b6001600160a01b031614905090565b7fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f6881565b60a45490565b60a65460609060026000196101006001841615020190911604612a9857609c60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156129a657600080fd5b505afa1580156129ba573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156129e357600080fd5b8101908080516040519392919084600160201b821115612a0257600080fd5b908301906020820185811115612a1757600080fd5b8251600160201b811182820188101715612a3057600080fd5b82525081516020918201929091019080838360005b83811015612a5d578181015183820152602001612a45565b50505050905090810190601f168015612a8a5780820380516001836020036101000a031916815260200191505b506040525050509050611888565b60a6805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612b1e5780601f10612af357610100808354040283529160200191612b1e565b820191906000526020600020905b815481529060010190602001808311612b0157829003601f168201915b50505050509050611888565b600081612b3681612299565b612b77576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a2602052604090205490565b600091825260a36020526040909120546001600160a01b0391821691161490565b609a546001600160a01b031681565b612bcc6128eb565b612c0b576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b80612c1581612299565b612c56576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260a260205260408082204260018201558054915190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79591a2505050565b609a54600160a01b900460ff16612cf3576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612d40576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b33600081815260a9602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612db733613072565b612df25760405162461bcd60e51b815260040180806020018281038252603b81526020018061583f603b913960400191505060405180910390fd5b609a54600160a01b900460ff16612e42576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b609e54609a546001600160a01b039081169083161580612ec657506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612e9857600080fd5b505afa158015612eac573d6000803e3d6000fd5b505050506040513d6020811015612ec257600080fd5b5051115b612f07576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b609e849055609a80546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b60ac5481565b612f8b6128eb565b612fca576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff1615613019576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b60408051478152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2609a5461306f906001600160a01b03163361306a8230613906565b614959565b33ff5b60006114c4609b8363ffffffff6149a616565b6001600160a01b038116600090815260a2602052604081206001015482906130ea576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b0316600090815260a2602052604090206001015490565b7f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f081565b609a54600160a01b900460ff1661317e576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b816131898133612b94565b80613199575061319981336140a9565b806131c15750600081815260a360205260409020546131c1906001600160a01b0316336139c8565b61320f576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b600083815260a360205260409020546001600160a01b031661323081612299565b613271576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b61327c8686866118ab565b61328886868686614a0d565b6132d9576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6132e96128eb565b613328576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b609a54600160a01b900460ff16613378576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a1609a805460ff60a01b19169055565b600054610100900460ff16806133c957506133c96146ed565b806133d7575060005460ff16155b6134125760405162461bcd60e51b815260040180806020018281038252602e815260200180615938602e913960400191505060405180910390fd5b600054610100900460ff1615801561343d576000805460ff1961ff0019909116610100171660011790555b606680546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801561349e576000805461ff00191690555b5050565b600081815260a3602052604090205460609082906001600160a01b03166134fe576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b60a7546060906002600019610100600184161502019091160461365b57609c60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561356957600080fd5b505afa15801561357d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156135a657600080fd5b8101908080516040519392919084600160201b8211156135c557600080fd5b9083019060208201858111156135da57600080fd5b8251600160201b8111828201881017156135f357600080fd5b82525081516020918201929091019080838360005b83811015613620578181015183820152602001613608565b50505050905090810190601f16801561364d5780820380516001836020036101000a031916815260200191505b5060405250505090506136e9565b60a7805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156136e15780601f106136b6576101008083540402835291602001916136e1565b820191906000526020600020905b8154815290600101906020018083116136c457829003601f168201915b505050505090505b6137276136f530614b40565b604051806040016040528060018152602001602f60f81b81525061371887614cbc565b8492919063ffffffff614d8016565b949350505050565b6137398433612853565b84848484836001600160a01b0316600161375287614f35565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156137ac573d6000803e3d6000fd5b505050602060405103516001600160a01b031614613805576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260996020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006138668a6140ca565b90506121258a826141d1565b600690565b61387f6128eb565b6138be576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6138cf609b8263ffffffff614f8616565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b60006001600160a01b03831661392757506001600160a01b038116316114c4565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561397d57600080fd5b505afa158015613991573d6000803e3d6000fd5b505050506040513d60208110156139a757600080fd5b505190506114c4565b731820a4b7618bde71dce8cdc73aab6c95905fad2481565b6001600160a01b03918216600090815260a96020908152604080832093909416825291909152205460ff1690565b613a07609b3363ffffffff61500716565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b609a54600160a01b900460ff16613a84576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613a8f8133612b94565b80613a9f5750613a9f81336140a9565b80613ac75750600081815260a36020526040902054613ac7906001600160a01b0316336139c8565b613b15576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b61271060aa5410613b66576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613bb3576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b600083815260a360205260409020546001600160a01b0316613bd481612299565b613c15576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03808216600090815260a2602052604080822092881682528120805460018401549192909142900381613c4f878a614000565b90506000613c638a8363ffffffff6143ff16565b905082811015613c8157899350613c7c8b826000614256565b613cc5565b613c8b8884614000565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8554613d0557613cd486614494565b613cde8c86614378565b60405185906001600160a01b038e1690600090600080516020615966833981519152908290a45b613d1185856001614256565b848c6001600160a01b0316896001600160a01b031660008051602061596683398151915260405160405180910390a4613d5b888d8d60405180602001604052806000815250614a0d565b613dac576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050505050505050565b613dc26128eb565b613e01576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b6118a88161506e565b613e126128dc565b6001600160a01b0316336001600160a01b03161480613e3b575060a1546001600160a01b031633145b613e8c576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000613e988330613906565b90506000821580613ea857508183115b15613efc5760008211613ef5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080613eff565b50815b60a1546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a460a154613f5e9085906001600160a01b031683614959565b50505050565b613f6c6128eb565b613fab576040805162461bcd60e51b815260206004820181905260248201526000805160206158f6833981519152604482015290519081900360640190fd5b81613fb581612299565b613ff6576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611c1583836141d1565b60008261400c81612299565b61404d576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038416600090815260a26020526040812090808561407a5742836001015403915061407e565b8591505b61271061409660aa548461510f90919063ffffffff16565b8161409d57fe5b04979650505050505050565b600091825260a86020526040909120546001600160a01b0391821691161490565b6000816140d681612299565b614117576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b038316600090815260a2602052604090206001810154609d5460ac54429092039182011061415057609e549350614171565b609d54609e54614166908363ffffffff61510f16565b8161416d57fe5b0493505b60ac5415806141855750609d5460ac548201105b156141c95760006127106141a660ab54609e5461510f90919063ffffffff16565b816141ad57fe5b049050808511156141c25780850394506141c7565b600094505b505b505050919050565b6001600160a01b038216600081815260a2602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a4426001820155811561424c57609a5461424c906001600160a01b03168484614959565b611c158383615168565b600083815260a360205260409020546001600160a01b0316806142b3576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b038116600090815260a260205260408120600181015490916142db84612299565b9050841561431e578015614303576142f9828763ffffffff6143ff16565b6001840155614319565b614313428763ffffffff6143ff16565b60018401555b614334565b61432e828763ffffffff61529816565b60018401555b604080518781528615156020820152815189927fa2ede7ad01668310f921fcf6084901d08af350838c2744a013153e4968a7559d928290030190a250505050505050565b600081815260a360205260409020546001600160a01b0383811691161461349e5760a48054600181019091557fe434dc35da084cf8d7e8186688ea2dacb53db7003d427af3abf351bd9d0a4e8d0180546001600160a01b0384166001600160a01b03199182168117909255600083815260a360205260409020805490911690911790555050565b600082820183811015611bbb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081815260a860205260409020546001600160a01b0316156118a857600090815260a86020526040902080546001600160a01b0319169055565b80546118a85760a08054600101908190559055565b600081156113b057609a546001600160a01b03166145105781341015614509576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b50346113b0565b609a546001600160a01b031661452e8133308663ffffffff6152da16565b829150506113b0565b60a1546040805163555ddc6560e11b81526001600160a01b0390921660048301527f4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156145be57600080fd5b505afa1580156145d2573d6000803e3d6000fd5b505050506040513d60208110156145e857600080fd5b505190506001600160a01b0381161561271c57604051638d0f092560e01b815233600482018181526001600160a01b03888116602485015287811660448501526064840187905260a060848501908152865160a4860152865191861694638d0f092594938b938b938b938b939260c490910190602085019080838360005b8381101561467e578181015183820152602001614666565b50505050905090810190601f1680156146ab5780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b1580156146ce57600080fd5b505af11580156146e2573d6000803e3d6000fd5b505050505050505050565b303b1590565b609a80546001600160a01b0319166001600160a01b038316908117909155158061478157506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561475357600080fd5b505afa158015614767573d6000803e3d6000fd5b505050506040513d602081101561477d57600080fd5b5051115b6118a8576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b609a805460ff60a01b1916600160a01b179055565b63bbf81e00831115614830576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b609c8054336001600160a01b03199182161790915560a180549091166001600160a01b039590951694909417909355609d91909155609e55609f55565b614875612723565b80516148889060a590602084019061576b565b506118a8635b5e139f60e01b6148d1565b6148a963780e9d6360e01b6148d1565b565b6103e860ab55565b6148bc81613072565b6118a8576118a8609b8263ffffffff614f8616565b6001600160e01b03198082161415614930576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b3390565b8015611c15576001600160a01b03831661498b576149866001600160a01b0383168263ffffffff61533416565b611c15565b82613f5e6001600160a01b038216848463ffffffff61541916565b60006001600160a01b0382166149ed5760405162461bcd60e51b81526004018080602001828103825260228152602001806159166022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000614a21846001600160a01b031661546b565b614a2d57506001613727565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614aa7578181015183820152602001614a8f565b50505050905090810190601f168015614ad45780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614af657600080fd5b505af1158015614b0a573d6000803e3d6000fd5b505050506040513d6020811015614b2057600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b81600081518110614ba457fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614bcd57fe5b60200101906001600160f81b031916908160001a90535060005b6014811015614cb3578260048583600c0160208110614c0257fe5b1a60f81b6001600160f81b031916901c60f81c60ff1681518110614c2257fe5b602001015160f81c60f81b828260020260020181518110614c3f57fe5b60200101906001600160f81b031916908160001a905350828482600c0160208110614c6657fe5b825191901a600f16908110614c7757fe5b602001015160f81c60f81b828260020260030181518110614c9457fe5b60200101906001600160f81b031916908160001a905350600101614be7565b50949350505050565b60608180614ce35750506040805180820190915260018152600360fc1b60208201526113b0565b8260005b8115614cfb57600101600a82049150614ce7565b6060816040519080825280601f01601f191660200182016040528015614d28576020820181803883390190505b50905060001982015b8415614d7657600a850660300160f81b82828060019003935081518110614d5457fe5b60200101906001600160f81b031916908160001a905350600a85049450614d31565b5095945050505050565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015614dcc576020820181803883390190505b509050806000805b8751811015614e2557878181518110614de957fe5b602001015160f81c60f81b838380600101945081518110614e0657fe5b60200101906001600160f81b031916908160001a905350600101614dd4565b5060005b8651811015614e7a57868181518110614e3e57fe5b602001015160f81c60f81b838380600101945081518110614e5b57fe5b60200101906001600160f81b031916908160001a905350600101614e29565b5060005b8551811015614ecf57858181518110614e9357fe5b602001015160f81c60f81b838380600101945081518110614eb057fe5b60200101906001600160f81b031916908160001a905350600101614e7e565b5060005b8451811015614f2457848181518110614ee857fe5b602001015160f81c60f81b838380600101945081518110614f0557fe5b60200101906001600160f81b031916908160001a905350600101614ed3565b50909b9a5050505050505050505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b614f9082826149a6565b15614fe2576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b61501182826149a6565b61504c5760405162461bcd60e51b81526004018080602001828103825260218152602001806158b46021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6001600160a01b0381166150b35760405162461bcd60e51b81526004018080602001828103825260268152602001806158196026913960400191505060405180910390fd5b6066546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606680546001600160a01b0319166001600160a01b0392909216919091179055565b60008261511e575060006114c4565b8282028284828161512b57fe5b0414611bbb5760405162461bcd60e51b81526004018080602001828103825260218152602001806158d56021913960400191505060405180910390fd5b60a1546040805163555ddc6560e11b81526001600160a01b0390921660048301527fd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68602483015251600091731820a4b7618bde71dce8cdc73aab6c95905fad249163aabbb8ca91604480820192602092909190829003018186803b1580156151ef57600080fd5b505afa158015615203573d6000803e3d6000fd5b505050506040513d602081101561521957600080fd5b505190506001600160a01b03811615611c15576040805163c9877d7b60e01b81523360048201526001600160a01b0385811660248301526044820185905291519183169163c9877d7b9160648082019260009290919082900301818387803b15801561528457600080fd5b505af11580156123b0573d6000803e3d6000fd5b6000611bbb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506154a2565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052613f5e908590615539565b80471015615389576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146153d4576040519150601f19603f3d011682016040523d82523d6000602084013e6153d9565b606091505b5050905080611c155760405162461bcd60e51b815260040180806020018281038252603a81526020018061587a603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611c15908490615539565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906137275750141592915050565b600081848411156155315760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156154f65781810151838201526020016154de565b50505050905090810190601f1680156155235780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61554b826001600160a01b031661546b565b61559c576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106155da5780518252601f1990920191602091820191016155bb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461563c576040519150601f19603f3d011682016040523d82523d6000602084013e615641565b606091505b509150915081615698576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115613f5e578080602001905160208110156156b457600080fd5b5051613f5e5760405162461bcd60e51b815260040180806020018281038252602a815260200180615986602a913960400191505060405180910390fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157325782800160ff1982351617855561575f565b8280016001018555821561575f579182015b8281111561575f578235825591602001919060010190615744565b506121b59291506157d9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157ac57805160ff191683800117855561575f565b8280016001018555821561575f579182015b8281111561575f5782518255916020019190600101906157be565b61188891905b808211156121b557600081556001016157df56fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158200699dda614bcab2e903ef2411b51464fc64ec2c573008b8f0d5cc966a4a6001164736f6c634300050e0032", - "compiler": { - "name": "solc", - "version": "0.5.14+commit.01f1aaa4.Emscripten.clang" - }, - "schemaVersion": "3.0.20", - "updatedAt": "2020-01-15T23:36:50.899Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV7.json b/packages/contracts/src/abis/PublicLock/PublicLockV7.json deleted file mode 100644 index 8a42f40b879..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV7.json +++ /dev/null @@ -1,1739 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_timeAdded", - "type": "bool" - } - ], - "name": "ExpirationChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "_newManager", - "type": "address" - } - ], - "name": "KeyManagerChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keyManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextAvailableNonce", - "type": "uint256" - } - ], - "name": "NonceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "oldTokenAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "PricingChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newExpiration", - "type": "uint256" - } - ], - "name": "RenewKeyPurchase", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addKeyGranter", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "expireAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "freeTrialLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - }, - { - "internalType": "address", - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_page", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_time", - "type": "uint256" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address[]", - "name": "_recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_expirationTimestamps", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "_keyManagers", - "type": "address[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_nextAvailableNonce", - "type": "uint256" - } - ], - "name": "invalidateOffchainApproval", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isKeyGranter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isLockManager", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "keyManagerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "keyManagerToNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "onKeyCancelHook", - "outputs": [ - { - "internalType": "contract ILockKeyCancelHook", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "onKeyPurchaseHook", - "outputs": [ - { - "internalType": "contract ILockKeyPurchaseHook", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchase", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchasePriceFor", - "outputs": [ - { - "internalType": "uint256", - "name": "minKeyPrice", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_granter", - "type": "address" - } - ], - "name": "revokeKeyGranter", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_onKeyPurchaseHook", - "type": "address" - }, - { - "internalType": "address", - "name": "_onKeyCancelHook", - "type": "address" - } - ], - "name": "setEventHooks", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - } - ], - "name": "setKeyManagerOf", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timeShared", - "type": "uint256" - } - ], - "name": "shareKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "internalType": "contract IUnlock", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - } - ], - "name": "updateKeyPricing", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_lockCreator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50615a3c80620000216000396000f3fe6080604052600436106103fa5760003560e01c80636eadde4311610213578063aae4b8f711610123578063d2503485116100ab578063f0ba60401161007a578063f0ba60401461137d578063f12c6b6e14611392578063f3fef3a3146113d1578063fc42b58f1461140a578063fe72e4c114611443576103fa565b8063d2503485146112aa578063d32bfb6c146112dd578063d4fac45d14611307578063e985e9c514611342576103fa565b8063b2e0f6e7116100f2578063b2e0f6e714611137578063b88d4fde14611185578063c1c98d0314611256578063c87b56dd1461126b578063d1bbd49c14611295576103fa565b8063aae4b8f71461105d578063abdf82ce14611090578063ad0e0a4d146110c3578063b11d7ec1146110fe576103fa565b806393fd1844116101a6578063994a8a7111610175578063994a8a7114610f865780639d76ea5814610fbf578063a22cb46514610fd4578063a2e4cd2e1461100f578063a375cb0514611048576103fa565b806393fd184414610ef057806395d89b4114610f05578063970aaeb714610f1a57806397aa390a14610f4d576103fa565b80638129fc1c116101e25780638129fc1c14610d5b57806381a3c94314610d705780638577a6d514610e8b5780638d0361fc14610eb5576103fa565b80636eadde4314610bbc57806370a0823114610c9857806374b6c10614610ccb578063782a4ade14610ce0576103fa565b80632f745c591161030e5780634d025fed116102a1578063550ef3a811610270578063550ef3a814610a9c578063564aa99d14610b1757806356e0d51f14610b4a5780636352211e14610b5f5780636d8ea5b414610b89576103fa565b80634d025fed146109e25780634f6ccce714610a0c57806352b0f63814610a3657806352d6a8e414610a69576103fa565b806339f46986116102dd57806339f46986146108cc5780633f33133a146108fc5780634136aa351461098a57806342842e0e1461099f576103fa565b80632f745c59146107d957806330176e131461081257806335576ad01461088d57806338af3eed146108b7576103fa565b806310803b7211610391578063183767da11610360578063183767da14610724578063217751bc1461073957806323b872dd1461074e5780632af9162a146107915780632d33dd5b146107c4576103fa565b806310803b721461066557806310e56973146106e557806311a4c03a146106fa57806318160ddd1461070f576103fa565b8063095ea7b3116103cd578063095ea7b31461053e578063097ba333146105775780630aaffd2a1461061d5780630f15023b14610650576103fa565b806301ffc9a7146103fc578063025e7c271461044457806306fdde031461048a578063081812fc14610514575b005b34801561040857600080fd5b506104306004803603602081101561041f57600080fd5b50356001600160e01b031916611476565b604080519115158252519081900360200190f35b34801561045057600080fd5b5061046e6004803603602081101561046757600080fd5b5035611499565b604080516001600160a01b039092168252519081900360200190f35b34801561049657600080fd5b5061049f6114c0565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561052057600080fd5b5061046e6004803603602081101561053757600080fd5b503561154e565b34801561054a57600080fd5b506103fa6004803603604081101561056157600080fd5b506001600160a01b0381351690602001356115c4565b34801561058357600080fd5b5061060b6004803603606081101561059a57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105cd57600080fd5b8201836020820111156105df57600080fd5b803590602001918460018302840111600160201b8311171561060057600080fd5b50909250905061174b565b60408051918252519081900360200190f35b34801561062957600080fd5b506103fa6004803603602081101561064057600080fd5b50356001600160a01b031661179a565b34801561065c57600080fd5b5061046e611877565b34801561067157600080fd5b506106956004803603604081101561068857600080fd5b5080359060200135611886565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106d15781810151838201526020016106b9565b505050509050019250505060405180910390f35b3480156106f157600080fd5b5061060b6119a0565b34801561070657600080fd5b5061060b6119a6565b34801561071b57600080fd5b5061060b6119ac565b34801561073057600080fd5b5061060b6119b3565b34801561074557600080fd5b5061046e6119b9565b34801561075a57600080fd5b506103fa6004803603606081101561077157600080fd5b506001600160a01b038135811691602081013590911690604001356119c8565b34801561079d57600080fd5b506103fa600480360360208110156107b457600080fd5b50356001600160a01b0316611cc7565b3480156107d057600080fd5b5061046e611d53565b3480156107e557600080fd5b5061060b600480360360408110156107fc57600080fd5b506001600160a01b038135169060200135611d62565b34801561081e57600080fd5b506103fa6004803603602081101561083557600080fd5b810190602081018135600160201b81111561084f57600080fd5b82018360208201111561086157600080fd5b803590602001918460018302840111600160201b8311171561088257600080fd5b509092509050611dc0565b34801561089957600080fd5b506103fa600480360360208110156108b057600080fd5b5035611e15565b3480156108c357600080fd5b5061046e611eb7565b3480156108d857600080fd5b506103fa600480360360408110156108ef57600080fd5b5080359060200135611ec6565b6103fa6004803603608081101561091257600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561094c57600080fd5b82018360208201111561095e57600080fd5b803590602001918460018302840111600160201b8311171561097f57600080fd5b509092509050611f50565b34801561099657600080fd5b50610430612462565b3480156109ab57600080fd5b506103fa600480360360608110156109c257600080fd5b506001600160a01b03813581169160208101359091169060400135612472565b3480156109ee57600080fd5b5061046e60048036036020811015610a0557600080fd5b503561248d565b348015610a1857600080fd5b5061060b60048036036020811015610a2f57600080fd5b50356124a8565b348015610a4257600080fd5b5061043060048036036020811015610a5957600080fd5b50356001600160a01b03166124f3565b348015610a7557600080fd5b5061060b60048036036020811015610a8c57600080fd5b50356001600160a01b0316612506565b348015610aa857600080fd5b506103fa60048036036020811015610abf57600080fd5b810190602081018135600160201b811115610ad957600080fd5b820183602082011115610aeb57600080fd5b803590602001918460018302840111600160201b83111715610b0c57600080fd5b509092509050612511565b348015610b2357600080fd5b506103fa60048036036020811015610b3a57600080fd5b50356001600160a01b0316612561565b348015610b5657600080fd5b5061060b6125ed565b348015610b6b57600080fd5b5061046e60048036036020811015610b8257600080fd5b50356125f3565b348015610b9557600080fd5b5061043060048036036020811015610bac57600080fd5b50356001600160a01b0316612669565b348015610bc857600080fd5b506103fa600480360360c0811015610bdf57600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610c2457600080fd5b820183602082011115610c3657600080fd5b803590602001918460018302840111600160201b83111715610c5757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612689945050505050565b348015610ca457600080fd5b5061060b60048036036020811015610cbb57600080fd5b50356001600160a01b0316612789565b348015610cd757600080fd5b5061060b6127f8565b348015610cec57600080fd5b506103fa60048036036020811015610d0357600080fd5b810190602081018135600160201b811115610d1d57600080fd5b820183602082011115610d2f57600080fd5b803590602001918460018302840111600160201b83111715610d5057600080fd5b5090925090506127fe565b348015610d6757600080fd5b506103fa6128b3565b348015610d7c57600080fd5b506103fa60048036036060811015610d9357600080fd5b810190602081018135600160201b811115610dad57600080fd5b820183602082011115610dbf57600080fd5b803590602001918460208302840111600160201b83111715610de057600080fd5b919390929091602081019035600160201b811115610dfd57600080fd5b820183602082011115610e0f57600080fd5b803590602001918460208302840111600160201b83111715610e3057600080fd5b919390929091602081019035600160201b811115610e4d57600080fd5b820183602082011115610e5f57600080fd5b803590602001918460208302840111600160201b83111715610e8057600080fd5b509092509050612965565b348015610e9757600080fd5b506103fa60048036036020811015610eae57600080fd5b5035612b72565b348015610ec157600080fd5b5061060b60048036036040811015610ed857600080fd5b506001600160a01b0381358116916020013516612bee565b348015610efc57600080fd5b5061060b612c79565b348015610f1157600080fd5b5061049f612c7f565b348015610f2657600080fd5b5061060b60048036036020811015610f3d57600080fd5b50356001600160a01b0316612e6e565b348015610f5957600080fd5b506103fa60048036036040811015610f7057600080fd5b506001600160a01b038135169060200135612e89565b348015610f9257600080fd5b5061043060048036036040811015610fa957600080fd5b50803590602001356001600160a01b0316612f22565b348015610fcb57600080fd5b5061046e612f43565b348015610fe057600080fd5b506103fa60048036036040811015610ff757600080fd5b506001600160a01b0381351690602001351515612f52565b34801561101b57600080fd5b506103fa6004803603604081101561103257600080fd5b50803590602001356001600160a01b031661305d565b34801561105457600080fd5b5061060b61322c565b34801561106957600080fd5b506104306004803603602081101561108057600080fd5b50356001600160a01b0316613232565b34801561109c57600080fd5b5061060b600480360360208110156110b357600080fd5b50356001600160a01b0316613245565b3480156110cf57600080fd5b506103fa600480360360408110156110e657600080fd5b506001600160a01b0381358116916020013516613263565b34801561110a57600080fd5b506103fa6004803603604081101561112157600080fd5b50803590602001356001600160a01b03166133bd565b34801561114357600080fd5b506103fa600480360360a081101561115a57600080fd5b506001600160a01b038135169060ff602082013516906040810135906060810135906080013561348a565b34801561119157600080fd5b506103fa600480360360808110156111a857600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111e257600080fd5b8201836020820111156111f457600080fd5b803590602001918460018302840111600160201b8311171561121557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506135da945050505050565b34801561126257600080fd5b506103fa613648565b34801561127757600080fd5b5061049f6004803603602081101561128e57600080fd5b5035613714565b3480156112a157600080fd5b5061060b6139a1565b3480156112b657600080fd5b506103fa600480360360208110156112cd57600080fd5b50356001600160a01b03166139a6565b3480156112e957600080fd5b506103fa6004803603602081101561130057600080fd5b5035613a32565b34801561131357600080fd5b5061060b6004803603604081101561132a57600080fd5b506001600160a01b0381358116916020013516613ad8565b34801561134e57600080fd5b506104306004803603604081101561136557600080fd5b506001600160a01b0381358116916020013516613b82565b34801561138957600080fd5b506103fa613c17565b34801561139e57600080fd5b506103fa600480360360608110156113b557600080fd5b506001600160a01b038135169060208101359060400135613c55565b3480156113dd57600080fd5b506103fa600480360360408110156113f457600080fd5b506001600160a01b038135169060200135613fdb565b34801561141657600080fd5b5061060b6004803603604081101561142d57600080fd5b506001600160a01b03813516906020013561411c565b34801561144f57600080fd5b5061060b6004803603602081101561146657600080fd5b50356001600160a01b03166141c5565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b607481815481106114a657fe5b6000918252602090912001546001600160a01b0316905081565b6078805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115465780601f1061151b57610100808354040283529160200191611546565b820191906000526020600020905b81548152906001019060200180831161152957829003601f168201915b505050505081565b60008181526073602052604081205482906001600160a01b03166115a7576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607660205260409020546001600160a01b031690565b606954600160a01b900460ff16611614576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8061161f81336141d7565b8061162f575061162f8133614239565b806116575750600081815260736020526040902054611657906001600160a01b031633613b82565b611696576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b336001600160a01b03841614156116e3576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260766020908152604080832080546001600160a01b0319166001600160a01b038881169182179092556073909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061178e858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061425a92505050565b50909695505050505050565b606f546001600160a01b03163314806117b757506117b733613232565b611808576040805162461bcd60e51b815260206004820152601f60248201527f4f4e4c595f42454e45464943494152595f4f525f4c4f434b4d414e4147455200604482015290519081900360640190fd5b6001600160a01b038116611855576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606f80546001600160a01b0319166001600160a01b0392909216919091179055565b606a546001600160a01b031681565b6074546060906118d3576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60745482908482029060009082840111156118f6575060745481810392506118fb565b508082015b606083604051908082528060200260200182016040528015611927578160200160208202803883390190505b5090506000835b83811015611991576074818154811061194357fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061196d57fe5b6001600160a01b03909216602092830291909101909101526001918201910161192e565b50909450505050505b92915050565b606c5481565b606b5481565b606e545b90565b607b5481565b6071546001600160a01b031681565b606954600160a01b900460ff16611a18576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611a2281612669565b611a63576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611a6e81336141d7565b80611a7e5750611a7e8133614239565b80611aa65750600081815260736020526040902054611aa6906001600160a01b031633613b82565b611ae5576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b611aef8386612f22565b611b40576040805162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e455200000000604482015290519081900360640190fd5b612710607b5410611b91576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611bde576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611beb86600061411c565b6001600160a01b03808816600090815260726020526040808220928916825281206001810154939450919290611c249088908690614466565b8154611c4057868255611c378888614588565b611c4087614610565b428111611c6e5760018084015490830155868255611c5f87600061464b565b611c698888614588565b611c8b565b6001830154611c859042830363ffffffff6146cd16565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d16916000805160206159be83398151915291a4505050505050505050565b611cd033613232565b611d0b5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611d1c60678263ffffffff61472716565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6070546001600160a01b031681565b60008115611db0576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611db983612e6e565b9392505050565b611dc933613232565b611e045760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611e10607a8383615727565b505050565b336000908152606860205260409020548111611e6d576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260686020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b606f546001600160a01b031681565b611ecf33613232565b611f0a5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a1607d91909155607c55565b606954600160a01b900460ff16611fa0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606e54606d5411611fe8576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416612035576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260726020526040812080549091816120a55761205f8361478e565b8254915061206d8783614588565b50606b5442016001830181905560405182906001600160a01b038916906000906000805160206159be833981519152908290a461216d565b428360010154111561211557606b5460018401546120c89163ffffffff6146cd16565b600184018190556040805182815290519192506001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9181900360200190a261216d565b50606b5442016001830181905561212d82600061464b565b6040805182815290516001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d919081900360200190a25b60008060006121b38a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061425a92505050565b91945092509050811561222d57606a5460408051633652466360e01b8152600481018590526024810184905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b15801561221457600080fd5b505af1158015612228573d6000803e3d6000fd5b505050505b606a546001600160a01b031663939d9f1f846122488c612669565b612253576000612255565b8b5b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b1580156122a457600080fd5b505af11580156122b8573d6000803e3d6000fd5b5050606954600092506001600160a01b03161590506122f857506069548b906001600160a01b03166122f28133308563ffffffff6147a316565b506122fb565b50345b83811015612345576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b6070546001600160a01b03161561245457607060009054906101000a90046001600160a01b03166001600160a01b03166398499657338d8d8d8d8a886040518863ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f82011690508083019250505098505050505050505050600060405180830381600087803b15801561243b57600080fd5b505af115801561244f573d6000803e3d6000fd5b505050505b505050505050505050505050565b606954600160a01b900460ff1681565b611e10838383604051806020016040528060008152506135da565b6075602052600090815260409020546001600160a01b031681565b6000606e5482106124ef576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b600061199a60678363ffffffff6147fd16565b600061199a82614864565b61251a33613232565b6125555760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611e1060788383615727565b61256a33613232565b6125a55760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6125b660678263ffffffff61496b16565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b607c5481565b60008181526073602052604081205482906001600160a01b031661264c576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607360205260409020546001600160a01b031690565b6001600160a01b0316600090815260726020526040902060010154421090565b600054610100900460ff16806126a257506126a26149ec565b806126b0575060005460ff16155b6126eb5760405162461bcd60e51b815260040180806020018281038252602e815260200180615990602e913960400191505060405180910390fd5b600054610100900460ff16158015612716576000805460ff1961ff0019909116610100171660011790555b61271f856149f2565b612727614ac1565b61273387878686614ad6565b61273c82614b6c565b612744614b98565b61274c614baa565b61275587614bb2565b61275e87614bd0565b61276e6380ac58cd60e01b614bee565b8015612780576000805461ff00191690555b50505050505050565b60006001600160a01b0382166127d8576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6127e182612669565b6127ec5760006127ef565b60015b60ff1692915050565b606d5481565b61280733613232565b6128425760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b61284e60798383615727565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b600054610100900460ff16806128cc57506128cc6149ec565b806128da575060005460ff16155b6129155760405162461bcd60e51b815260040180806020018281038252602e815260200180615990602e913960400191505060405180910390fd5b600054610100900460ff16158015612940576000805460ff1961ff0019909116610100171660011790555b6129506301ffc9a760e01b614bee565b8015612962576000805461ff00191690555b50565b61296e336124f3565b8061297d575061297d33613232565b6129b85760405162461bcd60e51b81526004018080602001828103825260488152602001806158e46048913960600191505060405180910390fd5b60005b858110156127805760008787838181106129d157fe5b905060200201356001600160a01b0316905060008686848181106129f157fe5b9050602002013590506000858585818110612a0857fe5b905060200201356001600160a01b0316905060006001600160a01b0316836001600160a01b03161415612a74576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038316600090815260726020526040902060018101548311612ad7576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b805480612af457612ae78261478e565b508054612af48582614588565b612afe818461464b565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b038716906000906000805160206159be833981519152908290a45050600190930192506129bb915050565b612b7b33613232565b612bb65760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a1607b55565b600030604051808061582a60259139604080519182900360250182206001600160a01b03881660009081526068602081815291849020546bffffffffffffffffffffffff19606098891b811684880152603487019490945260548601529588901b90911660748401528151808403909501855260889092019052825192019190912091505092915050565b60745490565b60795460609060026000196101006001841615020190911604612ddc57606a60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b158015612cea57600080fd5b505afa158015612cfe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d2757600080fd5b8101908080516040519392919084600160201b821115612d4657600080fd5b908301906020820185811115612d5b57600080fd5b8251600160201b811182820188101715612d7457600080fd5b82525081516020918201929091019080838360005b83811015612da1578181015183820152602001612d89565b50505050905090810190601f168015612dce5780820380516001836020036101000a031916815260200191505b5060405250505090506119b0565b6079805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612e625780601f10612e3757610100808354040283529160200191612e62565b820191906000526020600020905b815481529060010190602001808311612e4557829003601f168201915b505050505090506119b0565b6001600160a01b031660009081526072602052604090205490565b612e9233613232565b612ecd5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b81612ed781612669565b612f18576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e108383614c72565b600091825260736020526040909120546001600160a01b0391821691161490565b6069546001600160a01b031681565b606954600160a01b900460ff16612fa2576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612fef576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526077602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b61306633613232565b6130a15760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b606954600160a01b900460ff166130f1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606c546069546001600160a01b03908116908316158061317557506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561314757600080fd5b505afa15801561315b573d6000803e3d6000fd5b505050506040513d602081101561317157600080fd5b5051115b6131b6576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b606c849055606980546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b607d5481565b600061199a60668363ffffffff6147fd16565b6001600160a01b031660009081526072602052604090206001015490565b61326c33613232565b6132a75760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6001600160a01b03821615806132ca57506132ca826001600160a01b0316614d6d565b61331b576040805162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b0000000000000000604482015290519081900360640190fd5b6001600160a01b038116158061333e575061333e816001600160a01b0316614d6d565b61338f576040805162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b000000000000604482015290519081900360640190fd5b607080546001600160a01b039384166001600160a01b03199182161790915560718054929093169116179055565b60008281526073602052604090205482906001600160a01b0316613416576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b61342083336141d7565b8061342f575061342f33613232565b613480576040805162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f55504441544500604482015290519081900360640190fd5b611e10838361464b565b6134948533612bee565b85858585836001600160a01b031660016134ad87614da4565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613507573d6000803e3d6000fd5b505050602060405103516001600160a01b031614613560576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260686020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006135c1876125f3565b905060006135ce82614864565b90506124548282614c72565b6135e58484846119c8565b6135f184848484614df5565b613642576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b50505050565b61365133613232565b61368c5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b606954600160a01b900460ff166136dc576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16069805460ff60a01b19169055565b60008181526073602052604090205460609082906001600160a01b0316613770576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607a54606090600260001961010060018416150201909116046138cd57606a60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b1580156137db57600080fd5b505afa1580156137ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561381857600080fd5b8101908080516040519392919084600160201b82111561383757600080fd5b90830190602082018581111561384c57600080fd5b8251600160201b81118282018810171561386557600080fd5b82525081516020918201929091019080838360005b8381101561389257818101518382015260200161387a565b50505050905090810190601f1680156138bf5780820380516001836020036101000a031916815260200191505b50604052505050905061395b565b607a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156139535780601f1061392857610100808354040283529160200191613953565b820191906000526020600020905b81548152906001019060200180831161393657829003601f168201915b505050505090505b61399961396730614f28565b604051806040016040528060018152602001602f60f81b81525061398a876150a4565b8492919063ffffffff61516816565b949350505050565b600790565b6139af33613232565b6139ea5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6139fb60668263ffffffff61496b16565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b80613a3d81336141d7565b80613a4d5750613a4d8133614239565b80613a755750600081815260736020526040902054613a75906001600160a01b031633613b82565b613ab4576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b6000613abf836125f3565b90506000613acc82614864565b90506136428282614c72565b60006001600160a01b038316613af957506001600160a01b0381163161199a565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613b4f57600080fd5b505afa158015613b63573d6000803e3d6000fd5b505050506040513d6020811015613b7957600080fd5b5051905061199a565b6001600160a01b038083166000908152607260209081526040808320548084526075909252822054919290911680613be5575050506001600160a01b0380831660009081526077602090815260408083209385168352929052205460ff1661199a565b6001600160a01b0390811660009081526077602090815260408083209387168352929052205460ff16915061199a9050565b613c2860663363ffffffff61472716565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b606954600160a01b900460ff16613ca5576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613cb081336141d7565b80613cc05750613cc08133614239565b80613ce85750600081815260736020526040902054613ce8906001600160a01b031633613b82565b613d27576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b612710607b5410613d78576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613dc5576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000838152607360205260409020546001600160a01b0316613de681612669565b613e27576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0380821660009081526072602052604080822092881682528120805460018401549192909142900381613e61878a61411c565b90506000613e758a8363ffffffff6146cd16565b905082811015613e9357899350613e8e8b826000614466565b613ed7565b613e9d888461411c565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b84613f1e57613ee58661478e565b85549450613ef38c86614588565b60405185906001600160a01b038e16906000906000805160206159be833981519152908290a4613f34565b42866001015411613f3457613f3485600061464b565b613f4085856001614466565b848c6001600160a01b0316896001600160a01b03166000805160206159be83398151915260405160405180910390a4613f8a888d8d60405180602001604052806000815250614df5565b612454576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b613fe433613232565b80613ff95750606f546001600160a01b031633145b61404a576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b60006140568330613ad8565b9050600082158061406657508183115b156140ba57600082116140b3576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b50806140bd565b50815b606f546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a4606f546136429085906001600160a01b0316836152b9565b60008261412881612669565b614169576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03841660009081526072602052604081209080856141965742836001015403915061419a565b8591505b6127106141b2607b548461530690919063ffffffff16565b816141b957fe5b04979650505050505050565b60686020526000908152604090205481565b6000828152607560205260408120546001600160a01b038381169116148061422457506000838152607560205260409020546001600160a01b031615801561422457506142248383612f22565b156142315750600161199a565b50600061199a565b600091825260766020526040909120546001600160a01b0391821691161490565b607054600090819081906001600160a01b03161561436e5760705460405163221c1fd160e01b815233600482018181526001600160a01b038a811660248501528981166044850152608060648501908152895160848601528951919095169463221c1fd1948c938c938c93919260a40190602085019080838360005b838110156142ee5781810151838201526020016142d6565b50505050905090810190601f16801561431b5780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d602081101561436557600080fd5b50519250614374565b606c5492505b821561445d57606a5460408051630cb175e360e01b81526001600160a01b038981166004830152602482018790528251931692630cb175e392604480840193919291829003018186803b1580156143ca57600080fd5b505afa1580156143de573d6000803e3d6000fd5b505050506040513d60408110156143f457600080fd5b508051602090910151909250905082821115614457576040805162461bcd60e51b815260206004820152601c60248201527f494e56414c49445f444953434f554e545f46524f4d5f554e4c4f434b00000000604482015290519081900360640190fd5b81830392505b93509350939050565b6000838152607360205260409020546001600160a01b0316806144c3576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b0381166000908152607260205260408120600181015490916144eb84612669565b9050841561452e57801561451357614509828763ffffffff6146cd16565b6001840155614529565b614523428763ffffffff6146cd16565b60018401555b614544565b61453e828763ffffffff61535f16565b60018401555b604080518781528615156020820152815189927fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3928290030190a250505050505050565b6000818152607360205260409020546001600160a01b0383811691161461460c5760748054600181019091557f19a0b39aa25ac793b5f6e9a0534364cc0b3fd1ea9b651e79c7f50a59d48ef8130180546001600160a01b0384166001600160a01b031991821681179092556000838152607360205260409020805490911690911790555b5050565b6000818152607660205260409020546001600160a01b03161561296257600090815260766020526040902080546001600160a01b0319169055565b6000828152607560205260409020546001600160a01b0382811691161461460c57600082815260756020526040902080546001600160a01b0319166001600160a01b03831617905561469c82614610565b60405160009083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e3908390a35050565b600082820183811015611db9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b61473182826147fd565b61476c5760405162461bcd60e51b815260040180806020018281038252602181526020018061592c6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b805461296257606e8054600101908190559055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526136429085906153a1565b60006001600160a01b0382166148445760405162461bcd60e51b815260040180806020018281038252602281526020018061596e6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b60008161487081612669565b6148b1576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526072602052604090206001810154606b54607d5442909203918201106148ea57606c54935061490b565b606b54606c54614900908363ffffffff61530616565b8161490757fe5b0493505b607d54158061491f5750606b54607d548201105b15614963576000612710614940607c54606c5461530690919063ffffffff16565b8161494757fe5b0490508085111561495c578085039450614961565b600094505b505b505050919050565b61497582826147fd565b156149c7576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b303b1590565b606980546001600160a01b0319166001600160a01b0383169081179091551580614a8057506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a5257600080fd5b505afa158015614a66573d6000803e3d6000fd5b505050506040513d6020811015614a7c57600080fd5b5051115b612962576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b6069805460ff60a01b1916600160a01b179055565b63bbf81e00831115614b2f576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606a8054336001600160a01b031991821617909155606f80549091166001600160a01b039590951694909417909355606b91909155606c55606d55565b614b746128b3565b8051614b879060789060208401906157a1565b50612962635b5e139f60e01b614bee565b614ba863780e9d6360e01b614bee565b565b6103e8607c55565b614bbb81613232565b6129625761296260668263ffffffff61496b16565b614bd9816124f3565b6129625761296260678263ffffffff61496b16565b6001600160e01b03198082161415614c4d576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6001600160a01b03821660008181526072602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115614ced57606954614ced906001600160a01b031684846152b9565b6071546001600160a01b031615611e10576071546040805163b499b6c560e01b81523360048201526001600160a01b038681166024830152604482018690529151919092169163b499b6c591606480830192600092919082900301818387803b158015614d5957600080fd5b505af1158015612780573d6000803e3d6000fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906139995750141592915050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000614e09846001600160a01b0316614d6d565b614e1557506001613999565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614e8f578181015183820152602001614e77565b50505050905090810190601f168015614ebc5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614ede57600080fd5b505af1158015614ef2573d6000803e3d6000fd5b505050506040513d6020811015614f0857600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b81600081518110614f8c57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614fb557fe5b60200101906001600160f81b031916908160001a90535060005b601481101561509b578260048583600c0160208110614fea57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061500a57fe5b602001015160f81c60f81b82826002026002018151811061502757fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061504e57fe5b825191901a600f1690811061505f57fe5b602001015160f81c60f81b82826002026003018151811061507c57fe5b60200101906001600160f81b031916908160001a905350600101614fcf565b50949350505050565b606081806150cb5750506040805180820190915260018152600360fc1b6020820152611494565b8260005b81156150e357600101600a820491506150cf565b6060816040519080825280601f01601f191660200182016040528015615110576020820181803883390190505b50905060001982015b841561515e57600a850660300160f81b8282806001900393508151811061513c57fe5b60200101906001600160f81b031916908160001a905350600a85049450615119565b5095945050505050565b6060848484846040516020018085805190602001908083835b602083106151a05780518252601f199092019160209182019101615181565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106151e85780518252601f1990920191602091820191016151c9565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106152305780518252601f199092019160209182019101615211565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106152785780518252601f199092019160209182019101615259565b6001836020036101000a0380198251168184511680821785525050505050509050019450505050506040516020818303038152906040529050949350505050565b8015611e10576001600160a01b0383166152eb576152e66001600160a01b0383168263ffffffff61555916565b611e10565b826136426001600160a01b038216848463ffffffff61563e16565b6000826153155750600061199a565b8282028284828161532257fe5b0414611db95760405162461bcd60e51b815260040180806020018281038252602181526020018061594d6021913960400191505060405180910390fd5b6000611db983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615690565b6153b3826001600160a01b0316614d6d565b615404576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106154425780518252601f199092019160209182019101615423565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146154a4576040519150601f19603f3d011682016040523d82523d6000602084013e6154a9565b606091505b509150915081615500576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156136425780806020019051602081101561551c57600080fd5b50516136425760405162461bcd60e51b815260040180806020018281038252602a8152602001806159de602a913960400191505060405180910390fd5b804710156155ae576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146155f9576040519150601f19603f3d011682016040523d82523d6000602084013e6155fe565b606091505b5050905080611e105760405162461bcd60e51b815260040180806020018281038252603a81526020018061588a603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611e109084906153a1565b6000818484111561571f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156156e45781810151838201526020016156cc565b50505050905090810190601f1680156157115780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157685782800160ff19823516178555615795565b82800160010185558215615795579182015b8281111561579557823582559160200191906001019061577a565b506124ef92915061580f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157e257805160ff1916838001178555615795565b82800160010185558215615795579182015b828111156157955782518255916020019190600101906157f4565b6119b091905b808211156124ef576000815560010161581556fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f4e4c595f4b45595f4d414e414745525f4f525f415050524f564544000000004d6978696e4b65794772616e7465723a2063616c6c657220646f6573206e6f74206861766520746865204b65794772616e746572206f72204c6f636b4d616e6167657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820e6570f8bf01717c6b35e17be321624c59c8f788bfa8f0a41b0287b41cb66eac564736f6c63430005110032", - "deployedBytecode": "0x6080604052600436106103fa5760003560e01c80636eadde4311610213578063aae4b8f711610123578063d2503485116100ab578063f0ba60401161007a578063f0ba60401461137d578063f12c6b6e14611392578063f3fef3a3146113d1578063fc42b58f1461140a578063fe72e4c114611443576103fa565b8063d2503485146112aa578063d32bfb6c146112dd578063d4fac45d14611307578063e985e9c514611342576103fa565b8063b2e0f6e7116100f2578063b2e0f6e714611137578063b88d4fde14611185578063c1c98d0314611256578063c87b56dd1461126b578063d1bbd49c14611295576103fa565b8063aae4b8f71461105d578063abdf82ce14611090578063ad0e0a4d146110c3578063b11d7ec1146110fe576103fa565b806393fd1844116101a6578063994a8a7111610175578063994a8a7114610f865780639d76ea5814610fbf578063a22cb46514610fd4578063a2e4cd2e1461100f578063a375cb0514611048576103fa565b806393fd184414610ef057806395d89b4114610f05578063970aaeb714610f1a57806397aa390a14610f4d576103fa565b80638129fc1c116101e25780638129fc1c14610d5b57806381a3c94314610d705780638577a6d514610e8b5780638d0361fc14610eb5576103fa565b80636eadde4314610bbc57806370a0823114610c9857806374b6c10614610ccb578063782a4ade14610ce0576103fa565b80632f745c591161030e5780634d025fed116102a1578063550ef3a811610270578063550ef3a814610a9c578063564aa99d14610b1757806356e0d51f14610b4a5780636352211e14610b5f5780636d8ea5b414610b89576103fa565b80634d025fed146109e25780634f6ccce714610a0c57806352b0f63814610a3657806352d6a8e414610a69576103fa565b806339f46986116102dd57806339f46986146108cc5780633f33133a146108fc5780634136aa351461098a57806342842e0e1461099f576103fa565b80632f745c59146107d957806330176e131461081257806335576ad01461088d57806338af3eed146108b7576103fa565b806310803b7211610391578063183767da11610360578063183767da14610724578063217751bc1461073957806323b872dd1461074e5780632af9162a146107915780632d33dd5b146107c4576103fa565b806310803b721461066557806310e56973146106e557806311a4c03a146106fa57806318160ddd1461070f576103fa565b8063095ea7b3116103cd578063095ea7b31461053e578063097ba333146105775780630aaffd2a1461061d5780630f15023b14610650576103fa565b806301ffc9a7146103fc578063025e7c271461044457806306fdde031461048a578063081812fc14610514575b005b34801561040857600080fd5b506104306004803603602081101561041f57600080fd5b50356001600160e01b031916611476565b604080519115158252519081900360200190f35b34801561045057600080fd5b5061046e6004803603602081101561046757600080fd5b5035611499565b604080516001600160a01b039092168252519081900360200190f35b34801561049657600080fd5b5061049f6114c0565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561052057600080fd5b5061046e6004803603602081101561053757600080fd5b503561154e565b34801561054a57600080fd5b506103fa6004803603604081101561056157600080fd5b506001600160a01b0381351690602001356115c4565b34801561058357600080fd5b5061060b6004803603606081101561059a57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105cd57600080fd5b8201836020820111156105df57600080fd5b803590602001918460018302840111600160201b8311171561060057600080fd5b50909250905061174b565b60408051918252519081900360200190f35b34801561062957600080fd5b506103fa6004803603602081101561064057600080fd5b50356001600160a01b031661179a565b34801561065c57600080fd5b5061046e611877565b34801561067157600080fd5b506106956004803603604081101561068857600080fd5b5080359060200135611886565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106d15781810151838201526020016106b9565b505050509050019250505060405180910390f35b3480156106f157600080fd5b5061060b6119a0565b34801561070657600080fd5b5061060b6119a6565b34801561071b57600080fd5b5061060b6119ac565b34801561073057600080fd5b5061060b6119b3565b34801561074557600080fd5b5061046e6119b9565b34801561075a57600080fd5b506103fa6004803603606081101561077157600080fd5b506001600160a01b038135811691602081013590911690604001356119c8565b34801561079d57600080fd5b506103fa600480360360208110156107b457600080fd5b50356001600160a01b0316611cc7565b3480156107d057600080fd5b5061046e611d53565b3480156107e557600080fd5b5061060b600480360360408110156107fc57600080fd5b506001600160a01b038135169060200135611d62565b34801561081e57600080fd5b506103fa6004803603602081101561083557600080fd5b810190602081018135600160201b81111561084f57600080fd5b82018360208201111561086157600080fd5b803590602001918460018302840111600160201b8311171561088257600080fd5b509092509050611dc0565b34801561089957600080fd5b506103fa600480360360208110156108b057600080fd5b5035611e15565b3480156108c357600080fd5b5061046e611eb7565b3480156108d857600080fd5b506103fa600480360360408110156108ef57600080fd5b5080359060200135611ec6565b6103fa6004803603608081101561091257600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561094c57600080fd5b82018360208201111561095e57600080fd5b803590602001918460018302840111600160201b8311171561097f57600080fd5b509092509050611f50565b34801561099657600080fd5b50610430612462565b3480156109ab57600080fd5b506103fa600480360360608110156109c257600080fd5b506001600160a01b03813581169160208101359091169060400135612472565b3480156109ee57600080fd5b5061046e60048036036020811015610a0557600080fd5b503561248d565b348015610a1857600080fd5b5061060b60048036036020811015610a2f57600080fd5b50356124a8565b348015610a4257600080fd5b5061043060048036036020811015610a5957600080fd5b50356001600160a01b03166124f3565b348015610a7557600080fd5b5061060b60048036036020811015610a8c57600080fd5b50356001600160a01b0316612506565b348015610aa857600080fd5b506103fa60048036036020811015610abf57600080fd5b810190602081018135600160201b811115610ad957600080fd5b820183602082011115610aeb57600080fd5b803590602001918460018302840111600160201b83111715610b0c57600080fd5b509092509050612511565b348015610b2357600080fd5b506103fa60048036036020811015610b3a57600080fd5b50356001600160a01b0316612561565b348015610b5657600080fd5b5061060b6125ed565b348015610b6b57600080fd5b5061046e60048036036020811015610b8257600080fd5b50356125f3565b348015610b9557600080fd5b5061043060048036036020811015610bac57600080fd5b50356001600160a01b0316612669565b348015610bc857600080fd5b506103fa600480360360c0811015610bdf57600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610c2457600080fd5b820183602082011115610c3657600080fd5b803590602001918460018302840111600160201b83111715610c5757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612689945050505050565b348015610ca457600080fd5b5061060b60048036036020811015610cbb57600080fd5b50356001600160a01b0316612789565b348015610cd757600080fd5b5061060b6127f8565b348015610cec57600080fd5b506103fa60048036036020811015610d0357600080fd5b810190602081018135600160201b811115610d1d57600080fd5b820183602082011115610d2f57600080fd5b803590602001918460018302840111600160201b83111715610d5057600080fd5b5090925090506127fe565b348015610d6757600080fd5b506103fa6128b3565b348015610d7c57600080fd5b506103fa60048036036060811015610d9357600080fd5b810190602081018135600160201b811115610dad57600080fd5b820183602082011115610dbf57600080fd5b803590602001918460208302840111600160201b83111715610de057600080fd5b919390929091602081019035600160201b811115610dfd57600080fd5b820183602082011115610e0f57600080fd5b803590602001918460208302840111600160201b83111715610e3057600080fd5b919390929091602081019035600160201b811115610e4d57600080fd5b820183602082011115610e5f57600080fd5b803590602001918460208302840111600160201b83111715610e8057600080fd5b509092509050612965565b348015610e9757600080fd5b506103fa60048036036020811015610eae57600080fd5b5035612b72565b348015610ec157600080fd5b5061060b60048036036040811015610ed857600080fd5b506001600160a01b0381358116916020013516612bee565b348015610efc57600080fd5b5061060b612c79565b348015610f1157600080fd5b5061049f612c7f565b348015610f2657600080fd5b5061060b60048036036020811015610f3d57600080fd5b50356001600160a01b0316612e6e565b348015610f5957600080fd5b506103fa60048036036040811015610f7057600080fd5b506001600160a01b038135169060200135612e89565b348015610f9257600080fd5b5061043060048036036040811015610fa957600080fd5b50803590602001356001600160a01b0316612f22565b348015610fcb57600080fd5b5061046e612f43565b348015610fe057600080fd5b506103fa60048036036040811015610ff757600080fd5b506001600160a01b0381351690602001351515612f52565b34801561101b57600080fd5b506103fa6004803603604081101561103257600080fd5b50803590602001356001600160a01b031661305d565b34801561105457600080fd5b5061060b61322c565b34801561106957600080fd5b506104306004803603602081101561108057600080fd5b50356001600160a01b0316613232565b34801561109c57600080fd5b5061060b600480360360208110156110b357600080fd5b50356001600160a01b0316613245565b3480156110cf57600080fd5b506103fa600480360360408110156110e657600080fd5b506001600160a01b0381358116916020013516613263565b34801561110a57600080fd5b506103fa6004803603604081101561112157600080fd5b50803590602001356001600160a01b03166133bd565b34801561114357600080fd5b506103fa600480360360a081101561115a57600080fd5b506001600160a01b038135169060ff602082013516906040810135906060810135906080013561348a565b34801561119157600080fd5b506103fa600480360360808110156111a857600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111e257600080fd5b8201836020820111156111f457600080fd5b803590602001918460018302840111600160201b8311171561121557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506135da945050505050565b34801561126257600080fd5b506103fa613648565b34801561127757600080fd5b5061049f6004803603602081101561128e57600080fd5b5035613714565b3480156112a157600080fd5b5061060b6139a1565b3480156112b657600080fd5b506103fa600480360360208110156112cd57600080fd5b50356001600160a01b03166139a6565b3480156112e957600080fd5b506103fa6004803603602081101561130057600080fd5b5035613a32565b34801561131357600080fd5b5061060b6004803603604081101561132a57600080fd5b506001600160a01b0381358116916020013516613ad8565b34801561134e57600080fd5b506104306004803603604081101561136557600080fd5b506001600160a01b0381358116916020013516613b82565b34801561138957600080fd5b506103fa613c17565b34801561139e57600080fd5b506103fa600480360360608110156113b557600080fd5b506001600160a01b038135169060208101359060400135613c55565b3480156113dd57600080fd5b506103fa600480360360408110156113f457600080fd5b506001600160a01b038135169060200135613fdb565b34801561141657600080fd5b5061060b6004803603604081101561142d57600080fd5b506001600160a01b03813516906020013561411c565b34801561144f57600080fd5b5061060b6004803603602081101561146657600080fd5b50356001600160a01b03166141c5565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b607481815481106114a657fe5b6000918252602090912001546001600160a01b0316905081565b6078805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115465780601f1061151b57610100808354040283529160200191611546565b820191906000526020600020905b81548152906001019060200180831161152957829003601f168201915b505050505081565b60008181526073602052604081205482906001600160a01b03166115a7576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607660205260409020546001600160a01b031690565b606954600160a01b900460ff16611614576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b8061161f81336141d7565b8061162f575061162f8133614239565b806116575750600081815260736020526040902054611657906001600160a01b031633613b82565b611696576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b336001600160a01b03841614156116e3576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260766020908152604080832080546001600160a01b0319166001600160a01b038881169182179092556073909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600061178e858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061425a92505050565b50909695505050505050565b606f546001600160a01b03163314806117b757506117b733613232565b611808576040805162461bcd60e51b815260206004820152601f60248201527f4f4e4c595f42454e45464943494152595f4f525f4c4f434b4d414e4147455200604482015290519081900360640190fd5b6001600160a01b038116611855576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606f80546001600160a01b0319166001600160a01b0392909216919091179055565b606a546001600160a01b031681565b6074546060906118d3576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b60745482908482029060009082840111156118f6575060745481810392506118fb565b508082015b606083604051908082528060200260200182016040528015611927578160200160208202803883390190505b5090506000835b83811015611991576074818154811061194357fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061196d57fe5b6001600160a01b03909216602092830291909101909101526001918201910161192e565b50909450505050505b92915050565b606c5481565b606b5481565b606e545b90565b607b5481565b6071546001600160a01b031681565b606954600160a01b900460ff16611a18576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611a2281612669565b611a63576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611a6e81336141d7565b80611a7e5750611a7e8133614239565b80611aa65750600081815260736020526040902054611aa6906001600160a01b031633613b82565b611ae5576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b611aef8386612f22565b611b40576040805162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e455200000000604482015290519081900360640190fd5b612710607b5410611b91576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611bde576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611beb86600061411c565b6001600160a01b03808816600090815260726020526040808220928916825281206001810154939450919290611c249088908690614466565b8154611c4057868255611c378888614588565b611c4087614610565b428111611c6e5760018084015490830155868255611c5f87600061464b565b611c698888614588565b611c8b565b6001830154611c859042830363ffffffff6146cd16565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d16916000805160206159be83398151915291a4505050505050505050565b611cd033613232565b611d0b5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611d1c60678263ffffffff61472716565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6070546001600160a01b031681565b60008115611db0576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611db983612e6e565b9392505050565b611dc933613232565b611e045760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611e10607a8383615727565b505050565b336000908152606860205260409020548111611e6d576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260686020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b606f546001600160a01b031681565b611ecf33613232565b611f0a5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a1607d91909155607c55565b606954600160a01b900460ff16611fa0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606e54606d5411611fe8576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416612035576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260726020526040812080549091816120a55761205f8361478e565b8254915061206d8783614588565b50606b5442016001830181905560405182906001600160a01b038916906000906000805160206159be833981519152908290a461216d565b428360010154111561211557606b5460018401546120c89163ffffffff6146cd16565b600184018190556040805182815290519192506001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9181900360200190a261216d565b50606b5442016001830181905561212d82600061464b565b6040805182815290516001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d919081900360200190a25b60008060006121b38a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061425a92505050565b91945092509050811561222d57606a5460408051633652466360e01b8152600481018590526024810184905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b15801561221457600080fd5b505af1158015612228573d6000803e3d6000fd5b505050505b606a546001600160a01b031663939d9f1f846122488c612669565b612253576000612255565b8b5b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b1580156122a457600080fd5b505af11580156122b8573d6000803e3d6000fd5b5050606954600092506001600160a01b03161590506122f857506069548b906001600160a01b03166122f28133308563ffffffff6147a316565b506122fb565b50345b83811015612345576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b6070546001600160a01b03161561245457607060009054906101000a90046001600160a01b03166001600160a01b03166398499657338d8d8d8d8a886040518863ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f82011690508083019250505098505050505050505050600060405180830381600087803b15801561243b57600080fd5b505af115801561244f573d6000803e3d6000fd5b505050505b505050505050505050505050565b606954600160a01b900460ff1681565b611e10838383604051806020016040528060008152506135da565b6075602052600090815260409020546001600160a01b031681565b6000606e5482106124ef576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b600061199a60678363ffffffff6147fd16565b600061199a82614864565b61251a33613232565b6125555760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b611e1060788383615727565b61256a33613232565b6125a55760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6125b660678263ffffffff61496b16565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b607c5481565b60008181526073602052604081205482906001600160a01b031661264c576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607360205260409020546001600160a01b031690565b6001600160a01b0316600090815260726020526040902060010154421090565b600054610100900460ff16806126a257506126a26149ec565b806126b0575060005460ff16155b6126eb5760405162461bcd60e51b815260040180806020018281038252602e815260200180615990602e913960400191505060405180910390fd5b600054610100900460ff16158015612716576000805460ff1961ff0019909116610100171660011790555b61271f856149f2565b612727614ac1565b61273387878686614ad6565b61273c82614b6c565b612744614b98565b61274c614baa565b61275587614bb2565b61275e87614bd0565b61276e6380ac58cd60e01b614bee565b8015612780576000805461ff00191690555b50505050505050565b60006001600160a01b0382166127d8576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6127e182612669565b6127ec5760006127ef565b60015b60ff1692915050565b606d5481565b61280733613232565b6128425760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b61284e60798383615727565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b600054610100900460ff16806128cc57506128cc6149ec565b806128da575060005460ff16155b6129155760405162461bcd60e51b815260040180806020018281038252602e815260200180615990602e913960400191505060405180910390fd5b600054610100900460ff16158015612940576000805460ff1961ff0019909116610100171660011790555b6129506301ffc9a760e01b614bee565b8015612962576000805461ff00191690555b50565b61296e336124f3565b8061297d575061297d33613232565b6129b85760405162461bcd60e51b81526004018080602001828103825260488152602001806158e46048913960600191505060405180910390fd5b60005b858110156127805760008787838181106129d157fe5b905060200201356001600160a01b0316905060008686848181106129f157fe5b9050602002013590506000858585818110612a0857fe5b905060200201356001600160a01b0316905060006001600160a01b0316836001600160a01b03161415612a74576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038316600090815260726020526040902060018101548311612ad7576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b805480612af457612ae78261478e565b508054612af48582614588565b612afe818461464b565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b038716906000906000805160206159be833981519152908290a45050600190930192506129bb915050565b612b7b33613232565b612bb65760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a1607b55565b600030604051808061582a60259139604080519182900360250182206001600160a01b03881660009081526068602081815291849020546bffffffffffffffffffffffff19606098891b811684880152603487019490945260548601529588901b90911660748401528151808403909501855260889092019052825192019190912091505092915050565b60745490565b60795460609060026000196101006001841615020190911604612ddc57606a60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b158015612cea57600080fd5b505afa158015612cfe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d2757600080fd5b8101908080516040519392919084600160201b821115612d4657600080fd5b908301906020820185811115612d5b57600080fd5b8251600160201b811182820188101715612d7457600080fd5b82525081516020918201929091019080838360005b83811015612da1578181015183820152602001612d89565b50505050905090810190601f168015612dce5780820380516001836020036101000a031916815260200191505b5060405250505090506119b0565b6079805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612e625780601f10612e3757610100808354040283529160200191612e62565b820191906000526020600020905b815481529060010190602001808311612e4557829003601f168201915b505050505090506119b0565b6001600160a01b031660009081526072602052604090205490565b612e9233613232565b612ecd5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b81612ed781612669565b612f18576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e108383614c72565b600091825260736020526040909120546001600160a01b0391821691161490565b6069546001600160a01b031681565b606954600160a01b900460ff16612fa2576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612fef576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526077602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b61306633613232565b6130a15760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b606954600160a01b900460ff166130f1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606c546069546001600160a01b03908116908316158061317557506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561314757600080fd5b505afa15801561315b573d6000803e3d6000fd5b505050506040513d602081101561317157600080fd5b5051115b6131b6576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b606c849055606980546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b607d5481565b600061199a60668363ffffffff6147fd16565b6001600160a01b031660009081526072602052604090206001015490565b61326c33613232565b6132a75760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6001600160a01b03821615806132ca57506132ca826001600160a01b0316614d6d565b61331b576040805162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b0000000000000000604482015290519081900360640190fd5b6001600160a01b038116158061333e575061333e816001600160a01b0316614d6d565b61338f576040805162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b000000000000604482015290519081900360640190fd5b607080546001600160a01b039384166001600160a01b03199182161790915560718054929093169116179055565b60008281526073602052604090205482906001600160a01b0316613416576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b61342083336141d7565b8061342f575061342f33613232565b613480576040805162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f55504441544500604482015290519081900360640190fd5b611e10838361464b565b6134948533612bee565b85858585836001600160a01b031660016134ad87614da4565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613507573d6000803e3d6000fd5b505050602060405103516001600160a01b031614613560576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260686020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006135c1876125f3565b905060006135ce82614864565b90506124548282614c72565b6135e58484846119c8565b6135f184848484614df5565b613642576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b50505050565b61365133613232565b61368c5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b606954600160a01b900460ff166136dc576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16069805460ff60a01b19169055565b60008181526073602052604090205460609082906001600160a01b0316613770576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607a54606090600260001961010060018416150201909116046138cd57606a60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b1580156137db57600080fd5b505afa1580156137ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561381857600080fd5b8101908080516040519392919084600160201b82111561383757600080fd5b90830190602082018581111561384c57600080fd5b8251600160201b81118282018810171561386557600080fd5b82525081516020918201929091019080838360005b8381101561389257818101518382015260200161387a565b50505050905090810190601f1680156138bf5780820380516001836020036101000a031916815260200191505b50604052505050905061395b565b607a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156139535780601f1061392857610100808354040283529160200191613953565b820191906000526020600020905b81548152906001019060200180831161393657829003601f168201915b505050505090505b61399961396730614f28565b604051806040016040528060018152602001602f60f81b81525061398a876150a4565b8492919063ffffffff61516816565b949350505050565b600790565b6139af33613232565b6139ea5760405162461bcd60e51b815260040180806020018281038252603b81526020018061584f603b913960400191505060405180910390fd5b6139fb60668263ffffffff61496b16565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b80613a3d81336141d7565b80613a4d5750613a4d8133614239565b80613a755750600081815260736020526040902054613a75906001600160a01b031633613b82565b613ab4576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b6000613abf836125f3565b90506000613acc82614864565b90506136428282614c72565b60006001600160a01b038316613af957506001600160a01b0381163161199a565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613b4f57600080fd5b505afa158015613b63573d6000803e3d6000fd5b505050506040513d6020811015613b7957600080fd5b5051905061199a565b6001600160a01b038083166000908152607260209081526040808320548084526075909252822054919290911680613be5575050506001600160a01b0380831660009081526077602090815260408083209385168352929052205460ff1661199a565b6001600160a01b0390811660009081526077602090815260408083209387168352929052205460ff16915061199a9050565b613c2860663363ffffffff61472716565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b606954600160a01b900460ff16613ca5576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613cb081336141d7565b80613cc05750613cc08133614239565b80613ce85750600081815260736020526040902054613ce8906001600160a01b031633613b82565b613d27576040805162461bcd60e51b815260206004820152601c60248201526000805160206158c4833981519152604482015290519081900360640190fd5b612710607b5410613d78576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613dc5576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000838152607360205260409020546001600160a01b0316613de681612669565b613e27576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0380821660009081526072602052604080822092881682528120805460018401549192909142900381613e61878a61411c565b90506000613e758a8363ffffffff6146cd16565b905082811015613e9357899350613e8e8b826000614466565b613ed7565b613e9d888461411c565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b84613f1e57613ee58661478e565b85549450613ef38c86614588565b60405185906001600160a01b038e16906000906000805160206159be833981519152908290a4613f34565b42866001015411613f3457613f3485600061464b565b613f4085856001614466565b848c6001600160a01b0316896001600160a01b03166000805160206159be83398151915260405160405180910390a4613f8a888d8d60405180602001604052806000815250614df5565b612454576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b613fe433613232565b80613ff95750606f546001600160a01b031633145b61404a576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b60006140568330613ad8565b9050600082158061406657508183115b156140ba57600082116140b3576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b50806140bd565b50815b606f546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a4606f546136429085906001600160a01b0316836152b9565b60008261412881612669565b614169576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03841660009081526072602052604081209080856141965742836001015403915061419a565b8591505b6127106141b2607b548461530690919063ffffffff16565b816141b957fe5b04979650505050505050565b60686020526000908152604090205481565b6000828152607560205260408120546001600160a01b038381169116148061422457506000838152607560205260409020546001600160a01b031615801561422457506142248383612f22565b156142315750600161199a565b50600061199a565b600091825260766020526040909120546001600160a01b0391821691161490565b607054600090819081906001600160a01b03161561436e5760705460405163221c1fd160e01b815233600482018181526001600160a01b038a811660248501528981166044850152608060648501908152895160848601528951919095169463221c1fd1948c938c938c93919260a40190602085019080838360005b838110156142ee5781810151838201526020016142d6565b50505050905090810190601f16801561431b5780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561433b57600080fd5b505afa15801561434f573d6000803e3d6000fd5b505050506040513d602081101561436557600080fd5b50519250614374565b606c5492505b821561445d57606a5460408051630cb175e360e01b81526001600160a01b038981166004830152602482018790528251931692630cb175e392604480840193919291829003018186803b1580156143ca57600080fd5b505afa1580156143de573d6000803e3d6000fd5b505050506040513d60408110156143f457600080fd5b508051602090910151909250905082821115614457576040805162461bcd60e51b815260206004820152601c60248201527f494e56414c49445f444953434f554e545f46524f4d5f554e4c4f434b00000000604482015290519081900360640190fd5b81830392505b93509350939050565b6000838152607360205260409020546001600160a01b0316806144c3576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b0381166000908152607260205260408120600181015490916144eb84612669565b9050841561452e57801561451357614509828763ffffffff6146cd16565b6001840155614529565b614523428763ffffffff6146cd16565b60018401555b614544565b61453e828763ffffffff61535f16565b60018401555b604080518781528615156020820152815189927fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3928290030190a250505050505050565b6000818152607360205260409020546001600160a01b0383811691161461460c5760748054600181019091557f19a0b39aa25ac793b5f6e9a0534364cc0b3fd1ea9b651e79c7f50a59d48ef8130180546001600160a01b0384166001600160a01b031991821681179092556000838152607360205260409020805490911690911790555b5050565b6000818152607660205260409020546001600160a01b03161561296257600090815260766020526040902080546001600160a01b0319169055565b6000828152607560205260409020546001600160a01b0382811691161461460c57600082815260756020526040902080546001600160a01b0319166001600160a01b03831617905561469c82614610565b60405160009083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e3908390a35050565b600082820183811015611db9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b61473182826147fd565b61476c5760405162461bcd60e51b815260040180806020018281038252602181526020018061592c6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b805461296257606e8054600101908190559055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526136429085906153a1565b60006001600160a01b0382166148445760405162461bcd60e51b815260040180806020018281038252602281526020018061596e6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b60008161487081612669565b6148b1576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526072602052604090206001810154606b54607d5442909203918201106148ea57606c54935061490b565b606b54606c54614900908363ffffffff61530616565b8161490757fe5b0493505b607d54158061491f5750606b54607d548201105b15614963576000612710614940607c54606c5461530690919063ffffffff16565b8161494757fe5b0490508085111561495c578085039450614961565b600094505b505b505050919050565b61497582826147fd565b156149c7576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b303b1590565b606980546001600160a01b0319166001600160a01b0383169081179091551580614a8057506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614a5257600080fd5b505afa158015614a66573d6000803e3d6000fd5b505050506040513d6020811015614a7c57600080fd5b5051115b612962576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b6069805460ff60a01b1916600160a01b179055565b63bbf81e00831115614b2f576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606a8054336001600160a01b031991821617909155606f80549091166001600160a01b039590951694909417909355606b91909155606c55606d55565b614b746128b3565b8051614b879060789060208401906157a1565b50612962635b5e139f60e01b614bee565b614ba863780e9d6360e01b614bee565b565b6103e8607c55565b614bbb81613232565b6129625761296260668263ffffffff61496b16565b614bd9816124f3565b6129625761296260678263ffffffff61496b16565b6001600160e01b03198082161415614c4d576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6001600160a01b03821660008181526072602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115614ced57606954614ced906001600160a01b031684846152b9565b6071546001600160a01b031615611e10576071546040805163b499b6c560e01b81523360048201526001600160a01b038681166024830152604482018690529151919092169163b499b6c591606480830192600092919082900301818387803b158015614d5957600080fd5b505af1158015612780573d6000803e3d6000fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906139995750141592915050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000614e09846001600160a01b0316614d6d565b614e1557506001613999565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614e8f578181015183820152602001614e77565b50505050905090810190601f168015614ebc5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614ede57600080fd5b505af1158015614ef2573d6000803e3d6000fd5b505050506040513d6020811015614f0857600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b81600081518110614f8c57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110614fb557fe5b60200101906001600160f81b031916908160001a90535060005b601481101561509b578260048583600c0160208110614fea57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061500a57fe5b602001015160f81c60f81b82826002026002018151811061502757fe5b60200101906001600160f81b031916908160001a905350828482600c016020811061504e57fe5b825191901a600f1690811061505f57fe5b602001015160f81c60f81b82826002026003018151811061507c57fe5b60200101906001600160f81b031916908160001a905350600101614fcf565b50949350505050565b606081806150cb5750506040805180820190915260018152600360fc1b6020820152611494565b8260005b81156150e357600101600a820491506150cf565b6060816040519080825280601f01601f191660200182016040528015615110576020820181803883390190505b50905060001982015b841561515e57600a850660300160f81b8282806001900393508151811061513c57fe5b60200101906001600160f81b031916908160001a905350600a85049450615119565b5095945050505050565b6060848484846040516020018085805190602001908083835b602083106151a05780518252601f199092019160209182019101615181565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106151e85780518252601f1990920191602091820191016151c9565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106152305780518252601f199092019160209182019101615211565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106152785780518252601f199092019160209182019101615259565b6001836020036101000a0380198251168184511680821785525050505050509050019450505050506040516020818303038152906040529050949350505050565b8015611e10576001600160a01b0383166152eb576152e66001600160a01b0383168263ffffffff61555916565b611e10565b826136426001600160a01b038216848463ffffffff61563e16565b6000826153155750600061199a565b8282028284828161532257fe5b0414611db95760405162461bcd60e51b815260040180806020018281038252602181526020018061594d6021913960400191505060405180910390fd5b6000611db983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615690565b6153b3826001600160a01b0316614d6d565b615404576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106154425780518252601f199092019160209182019101615423565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146154a4576040519150601f19603f3d011682016040523d82523d6000602084013e6154a9565b606091505b509150915081615500576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156136425780806020019051602081101561551c57600080fd5b50516136425760405162461bcd60e51b815260040180806020018281038252602a8152602001806159de602a913960400191505060405180910390fd5b804710156155ae576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146155f9576040519150601f19603f3d011682016040523d82523d6000602084013e6155fe565b606091505b5050905080611e105760405162461bcd60e51b815260040180806020018281038252603a81526020018061588a603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611e109084906153a1565b6000818484111561571f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156156e45781810151838201526020016156cc565b50505050905090810190601f1680156157115780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157685782800160ff19823516178555615795565b82800160010185558215615795579182015b8281111561579557823582559160200191906001019061577a565b506124ef92915061580f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106157e257805160ff1916838001178555615795565b82800160010185558215615795579182015b828111156157955782518255916020019190600101906157f4565b6119b091905b808211156124ef576000815560010161581556fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f4e4c595f4b45595f4d414e414745525f4f525f415050524f564544000000004d6978696e4b65794772616e7465723a2063616c6c657220646f6573206e6f74206861766520746865204b65794772616e746572206f72204c6f636b4d616e6167657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820e6570f8bf01717c6b35e17be321624c59c8f788bfa8f0a41b0287b41cb66eac564736f6c63430005110032", - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13.Emscripten.clang" - }, - "schemaVersion": "3.0.23", - "updatedAt": "2020-03-26T17:11:58.385Z" -} diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV8.json b/packages/contracts/src/abis/PublicLock/PublicLockV8.json deleted file mode 100644 index 5ce93c7d56b..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV8.json +++ /dev/null @@ -1,1791 +0,0 @@ -{ - "contractName": "PublicLock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_timeAdded", - "type": "bool" - } - ], - "name": "ExpirationChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "_newManager", - "type": "address" - } - ], - "name": "KeyManagerChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keyManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextAvailableNonce", - "type": "uint256" - } - ], - "name": "NonceChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "oldTokenAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "PricingChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newExpiration", - "type": "uint256" - } - ], - "name": "RenewKeyPurchase", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addKeyGranter", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "approveBeneficiary", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "cancelAndRefund", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "cancelAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "disableLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "expireAndRefundFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "freeTrialLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - }, - { - "internalType": "address", - "name": "_txSender", - "type": "address" - } - ], - "name": "getCancelAndRefundApprovalHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "approvalHash", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_page", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_pageSize", - "type": "uint256" - } - ], - "name": "getOwnersByPage", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_time", - "type": "uint256" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address[]", - "name": "_recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_expirationTimestamps", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "_keyManagers", - "type": "address[]" - } - ], - "name": "grantKeys", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_nextAvailableNonce", - "type": "uint256" - } - ], - "name": "invalidateOffchainApproval", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isKeyGranter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "isKeyOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isLockManager", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "keyManagerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "keyManagerToNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "onKeyCancelHook", - "outputs": [ - { - "internalType": "contract ILockKeyCancelHook", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "onKeyPurchaseHook", - "outputs": [ - { - "internalType": "contract ILockKeyPurchaseHook", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchase", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchasePriceFor", - "outputs": [ - { - "internalType": "uint256", - "name": "minKeyPrice", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "refundPenaltyBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceLockManager", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_granter", - "type": "address" - } - ], - "name": "revokeKeyGranter", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_onKeyPurchaseHook", - "type": "address" - }, - { - "internalType": "address", - "name": "_onKeyCancelHook", - "type": "address" - } - ], - "name": "setEventHooks", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - } - ], - "name": "setKeyManagerOf", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timeShared", - "type": "uint256" - } - ], - "name": "shareKey", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transferFeeBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "internalType": "contract IUnlock", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - } - ], - "name": "updateKeyPricing", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_lockCreator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50615b5a80620000216000396000f3fe6080604052600436106104105760003560e01c806370a082311161021e578063abdf82ce11610123578063d2503485116100ab578063f0ba60401161007a578063f0ba604014611405578063f12c6b6e1461141a578063f3fef3a314611459578063fc42b58f14611492578063fe72e4c1146114cb57610410565b8063d250348514611332578063d32bfb6c14611365578063d4fac45d1461138f578063e985e9c5146113ca57610410565b8063b585a6d5116100f2578063b585a6d5146111d4578063b88d4fde1461120d578063c1c98d03146112de578063c87b56dd146112f3578063d1bbd49c1461131d57610410565b8063abdf82ce146110df578063ad0e0a4d14611112578063b11d7ec11461114d578063b2e0f6e71461118657610410565b8063970aaeb7116101a6578063a22cb46511610175578063a22cb46514610fea578063a2e4cd2e14611025578063a375cb051461105e578063a9059cbb14611073578063aae4b8f7146110ac57610410565b8063970aaeb714610f3057806397aa390a14610f63578063994a8a7114610f9c5780639d76ea5814610fd557610410565b806381a3c943116101ed57806381a3c94314610d865780638577a6d514610ea15780638d0361fc14610ecb57806393fd184414610f0657806395d89b4114610f1b57610410565b806370a0823114610cae57806374b6c10614610ce1578063782a4ade14610cf65780638129fc1c14610d7157610410565b80632f745c59116103245780634f6ccce7116102ac578063564aa99d1161027b578063564aa99d14610b2d57806356e0d51f14610b605780636352211e14610b755780636d8ea5b414610b9f5780636eadde4314610bd257610410565b80634f6ccce714610a2257806352b0f63814610a4c57806352d6a8e414610a7f578063550ef3a814610ab257610410565b806339f46986116102f357806339f46986146108e25780633f33133a146109125780634136aa35146109a057806342842e0e146109b55780634d025fed146109f857610410565b80632f745c59146107ef57806330176e131461082857806335576ad0146108a357806338af3eed146108cd57610410565b806310803b72116103a7578063183767da11610376578063183767da1461073a578063217751bc1461074f57806323b872dd146107645780632af9162a146107a75780632d33dd5b146107da57610410565b806310803b721461067b57806310e56973146106fb57806311a4c03a1461071057806318160ddd1461072557610410565b8063095ea7b3116103e3578063095ea7b314610554578063097ba3331461058d5780630aaffd2a146106335780630f15023b1461066657610410565b806301ffc9a714610412578063025e7c271461045a57806306fdde03146104a0578063081812fc1461052a575b005b34801561041e57600080fd5b506104466004803603602081101561043557600080fd5b50356001600160e01b0319166114fe565b604080519115158252519081900360200190f35b34801561046657600080fd5b506104846004803603602081101561047d57600080fd5b5035611521565b604080516001600160a01b039092168252519081900360200190f35b3480156104ac57600080fd5b506104b5611548565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104ef5781810151838201526020016104d7565b50505050905090810190601f16801561051c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561053657600080fd5b506104846004803603602081101561054d57600080fd5b50356115d6565b34801561056057600080fd5b506104106004803603604081101561057757600080fd5b506001600160a01b03813516906020013561164c565b34801561059957600080fd5b50610621600480360360608110156105b057600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105e357600080fd5b8201836020820111156105f557600080fd5b803590602001918460018302840111600160201b8311171561061657600080fd5b5090925090506117d3565b60408051918252519081900360200190f35b34801561063f57600080fd5b506104106004803603602081101561065657600080fd5b50356001600160a01b0316611822565b34801561067257600080fd5b506104846118ff565b34801561068757600080fd5b506106ab6004803603604081101561069e57600080fd5b508035906020013561190e565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106e75781810151838201526020016106cf565b505050509050019250505060405180910390f35b34801561070757600080fd5b506106216119de565b34801561071c57600080fd5b506106216119e4565b34801561073157600080fd5b506106216119ea565b34801561074657600080fd5b506106216119f1565b34801561075b57600080fd5b506104846119f7565b34801561077057600080fd5b506104106004803603606081101561078757600080fd5b506001600160a01b03813581169160208101359091169060400135611a06565b3480156107b357600080fd5b50610410600480360360208110156107ca57600080fd5b50356001600160a01b0316611d05565b3480156107e657600080fd5b50610484611d91565b3480156107fb57600080fd5b506106216004803603604081101561081257600080fd5b506001600160a01b038135169060200135611da0565b34801561083457600080fd5b506104106004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460018302840111600160201b8311171561089857600080fd5b509092509050611dfe565b3480156108af57600080fd5b50610410600480360360208110156108c657600080fd5b5035611e53565b3480156108d957600080fd5b50610484611ef5565b3480156108ee57600080fd5b506104106004803603604081101561090557600080fd5b5080359060200135611f04565b6104106004803603608081101561092857600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561096257600080fd5b82018360208201111561097457600080fd5b803590602001918460018302840111600160201b8311171561099557600080fd5b509092509050611f8e565b3480156109ac57600080fd5b506104466124be565b3480156109c157600080fd5b50610410600480360360608110156109d857600080fd5b506001600160a01b038135811691602081013590911690604001356124ce565b348015610a0457600080fd5b5061048460048036036020811015610a1b57600080fd5b50356124e9565b348015610a2e57600080fd5b5061062160048036036020811015610a4557600080fd5b5035612504565b348015610a5857600080fd5b5061044660048036036020811015610a6f57600080fd5b50356001600160a01b031661254f565b348015610a8b57600080fd5b5061062160048036036020811015610aa257600080fd5b50356001600160a01b0316612562565b348015610abe57600080fd5b5061041060048036036020811015610ad557600080fd5b810190602081018135600160201b811115610aef57600080fd5b820183602082011115610b0157600080fd5b803590602001918460018302840111600160201b83111715610b2257600080fd5b50909250905061256d565b348015610b3957600080fd5b5061041060048036036020811015610b5057600080fd5b50356001600160a01b03166125bd565b348015610b6c57600080fd5b50610621612649565b348015610b8157600080fd5b5061048460048036036020811015610b9857600080fd5b503561264f565b348015610bab57600080fd5b5061044660048036036020811015610bc257600080fd5b50356001600160a01b031661266a565b348015610bde57600080fd5b50610410600480360360c0811015610bf557600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610c3a57600080fd5b820183602082011115610c4c57600080fd5b803590602001918460018302840111600160201b83111715610c6d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061268a945050505050565b348015610cba57600080fd5b5061062160048036036020811015610cd157600080fd5b50356001600160a01b031661278a565b348015610ced57600080fd5b506106216127f9565b348015610d0257600080fd5b5061041060048036036020811015610d1957600080fd5b810190602081018135600160201b811115610d3357600080fd5b820183602082011115610d4557600080fd5b803590602001918460018302840111600160201b83111715610d6657600080fd5b5090925090506127ff565b348015610d7d57600080fd5b506104106128b4565b348015610d9257600080fd5b5061041060048036036060811015610da957600080fd5b810190602081018135600160201b811115610dc357600080fd5b820183602082011115610dd557600080fd5b803590602001918460208302840111600160201b83111715610df657600080fd5b919390929091602081019035600160201b811115610e1357600080fd5b820183602082011115610e2557600080fd5b803590602001918460208302840111600160201b83111715610e4657600080fd5b919390929091602081019035600160201b811115610e6357600080fd5b820183602082011115610e7557600080fd5b803590602001918460208302840111600160201b83111715610e9657600080fd5b509092509050612966565b348015610ead57600080fd5b5061041060048036036020811015610ec457600080fd5b5035612b73565b348015610ed757600080fd5b5061062160048036036040811015610eee57600080fd5b506001600160a01b0381358116916020013516612bef565b348015610f1257600080fd5b50610621612c7a565b348015610f2757600080fd5b506104b5612c80565b348015610f3c57600080fd5b5061062160048036036020811015610f5357600080fd5b50356001600160a01b0316612e6f565b348015610f6f57600080fd5b5061041060048036036040811015610f8657600080fd5b506001600160a01b038135169060200135612e8a565b348015610fa857600080fd5b5061044660048036036040811015610fbf57600080fd5b50803590602001356001600160a01b0316612f23565b348015610fe157600080fd5b50610484612f44565b348015610ff657600080fd5b506104106004803603604081101561100d57600080fd5b506001600160a01b0381351690602001351515612f53565b34801561103157600080fd5b506104106004803603604081101561104857600080fd5b50803590602001356001600160a01b031661305e565b34801561106a57600080fd5b5061062161322d565b34801561107f57600080fd5b506104466004803603604081101561109657600080fd5b506001600160a01b038135169060200135613233565b3480156110b857600080fd5b50610446600480360360208110156110cf57600080fd5b50356001600160a01b031661329a565b3480156110eb57600080fd5b506106216004803603602081101561110257600080fd5b50356001600160a01b03166132ad565b34801561111e57600080fd5b506104106004803603604081101561113557600080fd5b506001600160a01b03813581169160200135166132cb565b34801561115957600080fd5b506104106004803603604081101561117057600080fd5b50803590602001356001600160a01b0316613425565b34801561119257600080fd5b50610410600480360360a08110156111a957600080fd5b506001600160a01b038135169060ff60208201351690604081013590606081013590608001356134f2565b3480156111e057600080fd5b50610446600480360360408110156111f757600080fd5b506001600160a01b038135169060200135613642565b34801561121957600080fd5b506104106004803603608081101561123057600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561126a57600080fd5b82018360208201111561127c57600080fd5b803590602001918460018302840111600160201b8311171561129d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061373c945050505050565b3480156112ea57600080fd5b506104106137aa565b3480156112ff57600080fd5b506104b56004803603602081101561131657600080fd5b5035613876565b34801561132957600080fd5b50610621613af0565b34801561133e57600080fd5b506104106004803603602081101561135557600080fd5b50356001600160a01b0316613af5565b34801561137157600080fd5b506104106004803603602081101561138857600080fd5b5035613b81565b34801561139b57600080fd5b50610621600480360360408110156113b257600080fd5b506001600160a01b0381358116916020013516613c27565b3480156113d657600080fd5b50610446600480360360408110156113ed57600080fd5b506001600160a01b0381358116916020013516613cd1565b34801561141157600080fd5b50610410613d66565b34801561142657600080fd5b506104106004803603606081101561143d57600080fd5b506001600160a01b038135169060208101359060400135613da4565b34801561146557600080fd5b506104106004803603604081101561147c57600080fd5b506001600160a01b03813516906020013561412a565b34801561149e57600080fd5b50610621600480360360408110156114b557600080fd5b506001600160a01b03813516906020013561426b565b3480156114d757600080fd5b50610621600480360360208110156114ee57600080fd5b50356001600160a01b03166142de565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b6074818154811061152e57fe5b6000918252602090912001546001600160a01b0316905081565b6078805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115ce5780601f106115a3576101008083540402835291602001916115ce565b820191906000526020600020905b8154815290600101906020018083116115b157829003601f168201915b505050505081565b60008181526073602052604081205482906001600160a01b031661162f576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607660205260409020546001600160a01b031690565b606954600160a01b900460ff1661169c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116a781336142f0565b806116b757506116b78133614352565b806116df57506000818152607360205260409020546116df906001600160a01b031633613cd1565b61171e576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b336001600160a01b038416141561176b576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260766020908152604080832080546001600160a01b0319166001600160a01b038881169182179092556073909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611816858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061437392505050565b50909695505050505050565b606f546001600160a01b031633148061183f575061183f3361329a565b611890576040805162461bcd60e51b815260206004820152601f60248201527f4f4e4c595f42454e45464943494152595f4f525f4c4f434b4d414e4147455200604482015290519081900360640190fd5b6001600160a01b0381166118dd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606f80546001600160a01b0319166001600160a01b0392909216919091179055565b606a546001600160a01b031681565b607454606090829084820290600090828401111561193457506074548181039250611939565b508082015b606083604051908082528060200260200182016040528015611965578160200160208202803883390190505b5090506000835b838110156119cf576074818154811061198157fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106119ab57fe5b6001600160a01b03909216602092830291909101909101526001918201910161196c565b50909450505050505b92915050565b606c5481565b606b5481565b606e545b90565b607b5481565b6071546001600160a01b031681565b606954600160a01b900460ff16611a56576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611a608161266a565b611aa1576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611aac81336142f0565b80611abc5750611abc8133614352565b80611ae45750600081815260736020526040902054611ae4906001600160a01b031633613cd1565b611b23576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b611b2d8386612f23565b611b7e576040805162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e455200000000604482015290519081900360640190fd5b612710607b5410611bcf576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611c1c576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611c2986600061426b565b6001600160a01b03808816600090815260726020526040808220928916825281206001810154939450919290611c62908890869061457f565b8154611c7e57868255611c7588886146a1565b611c7e87614729565b428111611cac5760018084015490830155868255611c9d876000614764565b611ca788886146a1565b611cc9565b6001830154611cc39042830363ffffffff6147e616565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615adc83398151915291a4505050505050505050565b611d0e3361329a565b611d495760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611d5a60678263ffffffff61484016565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6070546001600160a01b031681565b60008115611dee576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611df783612e6f565b9392505050565b611e073361329a565b611e425760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611e4e607a8383615845565b505050565b336000908152606860205260409020548111611eab576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260686020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b606f546001600160a01b031681565b611f0d3361329a565b611f485760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a1607d91909155607c55565b606954600160a01b900460ff16611fde576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606e54606d5411612026576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416612073576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260726020526040812080549091816120e35761209d836148a7565b825491506120ab87836146a1565b50606b5442016001830181905560405182906001600160a01b03891690600090600080516020615adc833981519152908290a46121ab565b428360010154111561215357606b5460018401546121069163ffffffff6147e616565b600184018190556040805182815290519192506001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9181900360200190a26121ab565b50606b5442016001830181905561216b826000614764565b6040805182815290516001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d919081900360200190a25b60008060006121f18a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061437392505050565b91945092509050811561226b57606a5460408051633652466360e01b8152600481018590526024810184905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b15801561225257600080fd5b505af1158015612266573d6000803e3d6000fd5b505050505b606a546001600160a01b031663939d9f1f846122868c61266a565b80156122a457508c6001600160a01b03168c6001600160a01b031614155b6122af5760006122b1565b8b5b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561230057600080fd5b505af1158015612314573d6000803e3d6000fd5b5050606954600092506001600160a01b031615905061235457506069548b906001600160a01b031661234e8133308563ffffffff6148bc16565b50612357565b50345b838110156123a1576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b6070546001600160a01b0316156124b057607060009054906101000a90046001600160a01b03166001600160a01b03166398499657338d8d8d8d8a886040518863ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f82011690508083019250505098505050505050505050600060405180830381600087803b15801561249757600080fd5b505af11580156124ab573d6000803e3d6000fd5b505050505b505050505050505050505050565b606954600160a01b900460ff1681565b611e4e8383836040518060200160405280600081525061373c565b6075602052600090815260409020546001600160a01b031681565b6000606e54821061254b576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b60006119d860678363ffffffff61491616565b60006119d88261497d565b6125763361329a565b6125b15760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611e4e60788383615845565b6125c63361329a565b6126015760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b61261260678263ffffffff614a8416565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b607c5481565b6000908152607360205260409020546001600160a01b031690565b6001600160a01b0316600090815260726020526040902060010154421090565b600054610100900460ff16806126a357506126a3614b05565b806126b1575060005460ff16155b6126ec5760405162461bcd60e51b815260040180806020018281038252602e815260200180615aae602e913960400191505060405180910390fd5b600054610100900460ff16158015612717576000805460ff1961ff0019909116610100171660011790555b61272085614b0b565b612728614bda565b61273487878686614bef565b61273d82614c85565b612745614cb1565b61274d614cc3565b61275687614ccb565b61275f87614ce9565b61276f6380ac58cd60e01b614d07565b8015612781576000805461ff00191690555b50505050505050565b60006001600160a01b0382166127d9576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6127e28261266a565b6127ed5760006127f0565b60015b60ff1692915050565b606d5481565b6128083361329a565b6128435760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b61284f60798383615845565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b600054610100900460ff16806128cd57506128cd614b05565b806128db575060005460ff16155b6129165760405162461bcd60e51b815260040180806020018281038252602e815260200180615aae602e913960400191505060405180910390fd5b600054610100900460ff16158015612941576000805460ff1961ff0019909116610100171660011790555b6129516301ffc9a760e01b614d07565b8015612963576000805461ff00191690555b50565b61296f3361254f565b8061297e575061297e3361329a565b6129b95760405162461bcd60e51b8152600401808060200182810382526048815260200180615a026048913960600191505060405180910390fd5b60005b858110156127815760008787838181106129d257fe5b905060200201356001600160a01b0316905060008686848181106129f257fe5b9050602002013590506000858585818110612a0957fe5b905060200201356001600160a01b0316905060006001600160a01b0316836001600160a01b03161415612a75576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038316600090815260726020526040902060018101548311612ad8576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b805480612af557612ae8826148a7565b508054612af585826146a1565b612aff8184614764565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615adc833981519152908290a45050600190930192506129bc915050565b612b7c3361329a565b612bb75760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a1607b55565b600030604051808061594860259139604080519182900360250182206001600160a01b03881660009081526068602081815291849020546bffffffffffffffffffffffff19606098891b811684880152603487019490945260548601529588901b90911660748401528151808403909501855260889092019052825192019190912091505092915050565b60745490565b60795460609060026000196101006001841615020190911604612ddd57606a60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b158015612ceb57600080fd5b505afa158015612cff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d2857600080fd5b8101908080516040519392919084600160201b821115612d4757600080fd5b908301906020820185811115612d5c57600080fd5b8251600160201b811182820188101715612d7557600080fd5b82525081516020918201929091019080838360005b83811015612da2578181015183820152602001612d8a565b50505050905090810190601f168015612dcf5780820380516001836020036101000a031916815260200191505b5060405250505090506119ee565b6079805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612e635780601f10612e3857610100808354040283529160200191612e63565b820191906000526020600020905b815481529060010190602001808311612e4657829003601f168201915b505050505090506119ee565b6001600160a01b031660009081526072602052604090205490565b612e933361329a565b612ece5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b81612ed88161266a565b612f19576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e4e8383614d8b565b600091825260736020526040909120546001600160a01b0391821691161490565b6069546001600160a01b031681565b606954600160a01b900460ff16612fa3576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612ff0576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526077602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b6130673361329a565b6130a25760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b606954600160a01b900460ff166130f2576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606c546069546001600160a01b03908116908316158061317657506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561314857600080fd5b505afa15801561315c573d6000803e3d6000fd5b505050506040513d602081101561317257600080fd5b5051115b6131b7576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b606c849055606980546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b607d5481565b606b54336000908152607260205260408120600181015491928402918390613261904263ffffffff614e8616565b90508083101561327f5761327a86836000015485613da4565b61328e565b61328e33878460000154611a06565b50600195945050505050565b60006119d860668363ffffffff61491616565b6001600160a01b031660009081526072602052604090206001015490565b6132d43361329a565b61330f5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b6001600160a01b03821615806133325750613332826001600160a01b0316614ec8565b613383576040805162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b0000000000000000604482015290519081900360640190fd5b6001600160a01b03811615806133a657506133a6816001600160a01b0316614ec8565b6133f7576040805162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b000000000000604482015290519081900360640190fd5b607080546001600160a01b039384166001600160a01b03199182161790915560718054929093169116179055565b60008281526073602052604090205482906001600160a01b031661347e576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b61348883336142f0565b8061349757506134973361329a565b6134e8576040805162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f55504441544500604482015290519081900360640190fd5b611e4e8383614764565b6134fc8533612bef565b85858585836001600160a01b0316600161351587614f04565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561356f573d6000803e3d6000fd5b505050602060405103516001600160a01b0316146135c8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260686020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006136298761264f565b905060006136368261497d565b90506124b08282614d8b565b600061364d3361329a565b806136625750606f546001600160a01b031633145b6136b3576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b6069546040805163095ea7b360e01b81526001600160a01b038681166004830152602482018690529151919092169163095ea7b39160448083019260209291908290030181600087803b15801561370957600080fd5b505af115801561371d573d6000803e3d6000fd5b505050506040513d602081101561373357600080fd5b50519392505050565b613747848484611a06565b61375384848484614f55565b6137a4576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b50505050565b6137b33361329a565b6137ee5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b606954600160a01b900460ff1661383e576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16069805460ff60a01b19169055565b606080808061388430615088565b90506060851561389e5761389786615204565b92506138b1565b6040518060200160405280600081525092505b607a5460026000196101006001841615020190911604613a2257606a60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561391957600080fd5b505afa15801561392d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561395657600080fd5b8101908080516040519392919084600160201b82111561397557600080fd5b90830190602082018581111561398a57600080fd5b8251600160201b8111828201881017156139a357600080fd5b82525081516020918201929091019080838360005b838110156139d05781810151838201526020016139b8565b50505050905090810190601f1680156139fd5780820380516001836020036101000a031916815260200191505b506040818101905260018152602f60f81b6020820152939750929350613ad492505050565b607a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015613aa85780601f10613a7d57610100808354040283529160200191613aa8565b820191906000526020600020905b815481529060010190602001808311613a8b57829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b613ae68483838663ffffffff6152c816565b9695505050505050565b600890565b613afe3361329a565b613b395760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b613b4a60668263ffffffff614a8416565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b80613b8c81336142f0565b80613b9c5750613b9c8133614352565b80613bc45750600081815260736020526040902054613bc4906001600160a01b031633613cd1565b613c03576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b6000613c0e8361264f565b90506000613c1b8261497d565b90506137a48282614d8b565b60006001600160a01b038316613c4857506001600160a01b038116316119d8565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613c9e57600080fd5b505afa158015613cb2573d6000803e3d6000fd5b505050506040513d6020811015613cc857600080fd5b505190506119d8565b6001600160a01b038083166000908152607260209081526040808320548084526075909252822054919290911680613d34575050506001600160a01b0380831660009081526077602090815260408083209385168352929052205460ff166119d8565b6001600160a01b0390811660009081526077602090815260408083209387168352929052205460ff1691506119d89050565b613d7760663363ffffffff61484016565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b606954600160a01b900460ff16613df4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613dff81336142f0565b80613e0f5750613e0f8133614352565b80613e375750600081815260736020526040902054613e37906001600160a01b031633613cd1565b613e76576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b612710607b5410613ec7576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613f14576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000838152607360205260409020546001600160a01b0316613f358161266a565b613f76576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0380821660009081526072602052604080822092881682528120805460018401549192909142900381613fb0878a61426b565b90506000613fc48a8363ffffffff6147e616565b905082811015613fe257899350613fdd8b82600061457f565b614026565b613fec888461426b565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8461406d57614034866148a7565b855494506140428c866146a1565b60405185906001600160a01b038e1690600090600080516020615adc833981519152908290a4614083565b4286600101541161408357614083856000614764565b61408f8585600161457f565b848c6001600160a01b0316896001600160a01b0316600080516020615adc83398151915260405160405180910390a46140d9888d8d60405180602001604052806000815250614f55565b6124b0576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b6141333361329a565b806141485750606f546001600160a01b031633145b614199576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b60006141a58330613c27565b905060008215806141b557508183115b156142095760008211614202576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b508061420c565b50815b606f546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a4606f546137a49085906001600160a01b031683615419565b60006142768361266a565b614282575060006119d8565b6001600160a01b03831660009081526072602052604081209080846142af574283600101540391506142b3565b8491505b6127106142cb607b548461546690919063ffffffff16565b816142d257fe5b0493506119d892505050565b60686020526000908152604090205481565b6000828152607560205260408120546001600160a01b038381169116148061433d57506000838152607560205260409020546001600160a01b031615801561433d575061433d8383612f23565b1561434a575060016119d8565b5060006119d8565b600091825260766020526040909120546001600160a01b0391821691161490565b607054600090819081906001600160a01b0316156144875760705460405163221c1fd160e01b815233600482018181526001600160a01b038a811660248501528981166044850152608060648501908152895160848601528951919095169463221c1fd1948c938c938c93919260a40190602085019080838360005b838110156144075781810151838201526020016143ef565b50505050905090810190601f1680156144345780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561445457600080fd5b505afa158015614468573d6000803e3d6000fd5b505050506040513d602081101561447e57600080fd5b5051925061448d565b606c5492505b821561457657606a5460408051630cb175e360e01b81526001600160a01b038981166004830152602482018790528251931692630cb175e392604480840193919291829003018186803b1580156144e357600080fd5b505afa1580156144f7573d6000803e3d6000fd5b505050506040513d604081101561450d57600080fd5b508051602090910151909250905082821115614570576040805162461bcd60e51b815260206004820152601c60248201527f494e56414c49445f444953434f554e545f46524f4d5f554e4c4f434b00000000604482015290519081900360640190fd5b81830392505b93509350939050565b6000838152607360205260409020546001600160a01b0316806145dc576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b0381166000908152607260205260408120600181015490916146048461266a565b9050841561464757801561462c57614622828763ffffffff6147e616565b6001840155614642565b61463c428763ffffffff6147e616565b60018401555b61465d565b614657828763ffffffff614e8616565b60018401555b604080518781528615156020820152815189927fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3928290030190a250505050505050565b6000818152607360205260409020546001600160a01b038381169116146147255760748054600181019091557f19a0b39aa25ac793b5f6e9a0534364cc0b3fd1ea9b651e79c7f50a59d48ef8130180546001600160a01b0384166001600160a01b031991821681179092556000838152607360205260409020805490911690911790555b5050565b6000818152607660205260409020546001600160a01b03161561296357600090815260766020526040902080546001600160a01b0319169055565b6000828152607560205260409020546001600160a01b0382811691161461472557600082815260756020526040902080546001600160a01b0319166001600160a01b0383161790556147b582614729565b60405160009083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e3908390a35050565b600082820183811015611df7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b61484a8282614916565b6148855760405162461bcd60e51b8152600401808060200182810382526021815260200180615a4a6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b805461296357606e8054600101908190559055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526137a49085906154bf565b60006001600160a01b03821661495d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615a8c6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000816149898161266a565b6149ca576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526072602052604090206001810154606b54607d544290920391820110614a0357606c549350614a24565b606b54606c54614a19908363ffffffff61546616565b81614a2057fe5b0493505b607d541580614a385750606b54607d548201105b15614a7c576000612710614a59607c54606c5461546690919063ffffffff16565b81614a6057fe5b04905080851115614a75578085039450614a7a565b600094505b505b505050919050565b614a8e8282614916565b15614ae0576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b303b1590565b606980546001600160a01b0319166001600160a01b0383169081179091551580614b9957506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614b6b57600080fd5b505afa158015614b7f573d6000803e3d6000fd5b505050506040513d6020811015614b9557600080fd5b5051115b612963576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b6069805460ff60a01b1916600160a01b179055565b63bbf81e00831115614c48576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606a8054336001600160a01b031991821617909155606f80549091166001600160a01b039590951694909417909355606b91909155606c55606d55565b614c8d6128b4565b8051614ca09060789060208401906158bf565b50612963635b5e139f60e01b614d07565b614cc163780e9d6360e01b614d07565b565b6103e8607c55565b614cd48161329a565b6129635761296360668263ffffffff614a8416565b614cf28161254f565b6129635761296360678263ffffffff614a8416565b6001600160e01b03198082161415614d66576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6001600160a01b03821660008181526072602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115614e0657606954614e06906001600160a01b03168484615419565b6071546001600160a01b031615611e4e576071546040805163b499b6c560e01b81523360048201526001600160a01b038681166024830152604482018690529151919092169163b499b6c591606480830192600092919082900301818387803b158015614e7257600080fd5b505af1158015612781573d6000803e3d6000fd5b6000611df783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615677565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590614efc57508115155b949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000614f69846001600160a01b0316614ec8565b614f7557506001614efc565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614fef578181015183820152602001614fd7565b50505050905090810190601f16801561501c5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561503e57600080fd5b505af1158015615052573d6000803e3d6000fd5b505050506040513d602081101561506857600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106150ec57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061511557fe5b60200101906001600160f81b031916908160001a90535060005b60148110156151fb578260048583600c016020811061514a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061516a57fe5b602001015160f81c60f81b82826002026002018151811061518757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106151ae57fe5b825191901a600f169081106151bf57fe5b602001015160f81c60f81b8282600202600301815181106151dc57fe5b60200101906001600160f81b031916908160001a90535060010161512f565b50949350505050565b6060818061522b5750506040805180820190915260018152600360fc1b602082015261151c565b8260005b811561524357600101600a8204915061522f565b6060816040519080825280601f01601f191660200182016040528015615270576020820181803883390190505b50905060001982015b84156152be57600a850660300160f81b8282806001900393508151811061529c57fe5b60200101906001600160f81b031916908160001a905350600a85049450615279565b5095945050505050565b6060848484846040516020018085805190602001908083835b602083106153005780518252601f1990920191602091820191016152e1565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106153485780518252601f199092019160209182019101615329565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106153905780518252601f199092019160209182019101615371565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106153d85780518252601f1990920191602091820191016153b9565b6001836020036101000a0380198251168184511680821785525050505050509050019450505050506040516020818303038152906040529050949350505050565b8015611e4e576001600160a01b03831661544b576154466001600160a01b0383168263ffffffff61570e16565b611e4e565b826137a46001600160a01b038216848463ffffffff6157f316565b600082615475575060006119d8565b8282028284828161548257fe5b0414611df75760405162461bcd60e51b8152600401808060200182810382526021815260200180615a6b6021913960400191505060405180910390fd5b6154d1826001600160a01b0316614ec8565b615522576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106155605780518252601f199092019160209182019101615541565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146155c2576040519150601f19603f3d011682016040523d82523d6000602084013e6155c7565b606091505b50915091508161561e576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156137a45780806020019051602081101561563a57600080fd5b50516137a45760405162461bcd60e51b815260040180806020018281038252602a815260200180615afc602a913960400191505060405180910390fd5b600081848411156157065760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156156cb5781810151838201526020016156b3565b50505050905090810190601f1680156156f85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b80471015615763576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146157ae576040519150601f19603f3d011682016040523d82523d6000602084013e6157b3565b606091505b5050905080611e4e5760405162461bcd60e51b815260040180806020018281038252603a8152602001806159a8603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611e4e9084906154bf565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158865782800160ff198235161785556158b3565b828001600101855582156158b3579182015b828111156158b3578235825591602001919060010190615898565b5061254b92915061592d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061590057805160ff19168380011785556158b3565b828001600101855582156158b3579182015b828111156158b3578251825591602001919060010190615912565b6119ee91905b8082111561254b576000815560010161593356fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f4e4c595f4b45595f4d414e414745525f4f525f415050524f564544000000004d6978696e4b65794772616e7465723a2063616c6c657220646f6573206e6f74206861766520746865204b65794772616e746572206f72204c6f636b4d616e6167657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158209749e0c6496e968cb0d91da8eb9608ffcbbdceecce35d34911522be79830c67764736f6c63430005110032", - "deployedBytecode": "0x6080604052600436106104105760003560e01c806370a082311161021e578063abdf82ce11610123578063d2503485116100ab578063f0ba60401161007a578063f0ba604014611405578063f12c6b6e1461141a578063f3fef3a314611459578063fc42b58f14611492578063fe72e4c1146114cb57610410565b8063d250348514611332578063d32bfb6c14611365578063d4fac45d1461138f578063e985e9c5146113ca57610410565b8063b585a6d5116100f2578063b585a6d5146111d4578063b88d4fde1461120d578063c1c98d03146112de578063c87b56dd146112f3578063d1bbd49c1461131d57610410565b8063abdf82ce146110df578063ad0e0a4d14611112578063b11d7ec11461114d578063b2e0f6e71461118657610410565b8063970aaeb7116101a6578063a22cb46511610175578063a22cb46514610fea578063a2e4cd2e14611025578063a375cb051461105e578063a9059cbb14611073578063aae4b8f7146110ac57610410565b8063970aaeb714610f3057806397aa390a14610f63578063994a8a7114610f9c5780639d76ea5814610fd557610410565b806381a3c943116101ed57806381a3c94314610d865780638577a6d514610ea15780638d0361fc14610ecb57806393fd184414610f0657806395d89b4114610f1b57610410565b806370a0823114610cae57806374b6c10614610ce1578063782a4ade14610cf65780638129fc1c14610d7157610410565b80632f745c59116103245780634f6ccce7116102ac578063564aa99d1161027b578063564aa99d14610b2d57806356e0d51f14610b605780636352211e14610b755780636d8ea5b414610b9f5780636eadde4314610bd257610410565b80634f6ccce714610a2257806352b0f63814610a4c57806352d6a8e414610a7f578063550ef3a814610ab257610410565b806339f46986116102f357806339f46986146108e25780633f33133a146109125780634136aa35146109a057806342842e0e146109b55780634d025fed146109f857610410565b80632f745c59146107ef57806330176e131461082857806335576ad0146108a357806338af3eed146108cd57610410565b806310803b72116103a7578063183767da11610376578063183767da1461073a578063217751bc1461074f57806323b872dd146107645780632af9162a146107a75780632d33dd5b146107da57610410565b806310803b721461067b57806310e56973146106fb57806311a4c03a1461071057806318160ddd1461072557610410565b8063095ea7b3116103e3578063095ea7b314610554578063097ba3331461058d5780630aaffd2a146106335780630f15023b1461066657610410565b806301ffc9a714610412578063025e7c271461045a57806306fdde03146104a0578063081812fc1461052a575b005b34801561041e57600080fd5b506104466004803603602081101561043557600080fd5b50356001600160e01b0319166114fe565b604080519115158252519081900360200190f35b34801561046657600080fd5b506104846004803603602081101561047d57600080fd5b5035611521565b604080516001600160a01b039092168252519081900360200190f35b3480156104ac57600080fd5b506104b5611548565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104ef5781810151838201526020016104d7565b50505050905090810190601f16801561051c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561053657600080fd5b506104846004803603602081101561054d57600080fd5b50356115d6565b34801561056057600080fd5b506104106004803603604081101561057757600080fd5b506001600160a01b03813516906020013561164c565b34801561059957600080fd5b50610621600480360360608110156105b057600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105e357600080fd5b8201836020820111156105f557600080fd5b803590602001918460018302840111600160201b8311171561061657600080fd5b5090925090506117d3565b60408051918252519081900360200190f35b34801561063f57600080fd5b506104106004803603602081101561065657600080fd5b50356001600160a01b0316611822565b34801561067257600080fd5b506104846118ff565b34801561068757600080fd5b506106ab6004803603604081101561069e57600080fd5b508035906020013561190e565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106e75781810151838201526020016106cf565b505050509050019250505060405180910390f35b34801561070757600080fd5b506106216119de565b34801561071c57600080fd5b506106216119e4565b34801561073157600080fd5b506106216119ea565b34801561074657600080fd5b506106216119f1565b34801561075b57600080fd5b506104846119f7565b34801561077057600080fd5b506104106004803603606081101561078757600080fd5b506001600160a01b03813581169160208101359091169060400135611a06565b3480156107b357600080fd5b50610410600480360360208110156107ca57600080fd5b50356001600160a01b0316611d05565b3480156107e657600080fd5b50610484611d91565b3480156107fb57600080fd5b506106216004803603604081101561081257600080fd5b506001600160a01b038135169060200135611da0565b34801561083457600080fd5b506104106004803603602081101561084b57600080fd5b810190602081018135600160201b81111561086557600080fd5b82018360208201111561087757600080fd5b803590602001918460018302840111600160201b8311171561089857600080fd5b509092509050611dfe565b3480156108af57600080fd5b50610410600480360360208110156108c657600080fd5b5035611e53565b3480156108d957600080fd5b50610484611ef5565b3480156108ee57600080fd5b506104106004803603604081101561090557600080fd5b5080359060200135611f04565b6104106004803603608081101561092857600080fd5b8135916001600160a01b03602082013581169260408301359091169190810190608081016060820135600160201b81111561096257600080fd5b82018360208201111561097457600080fd5b803590602001918460018302840111600160201b8311171561099557600080fd5b509092509050611f8e565b3480156109ac57600080fd5b506104466124be565b3480156109c157600080fd5b50610410600480360360608110156109d857600080fd5b506001600160a01b038135811691602081013590911690604001356124ce565b348015610a0457600080fd5b5061048460048036036020811015610a1b57600080fd5b50356124e9565b348015610a2e57600080fd5b5061062160048036036020811015610a4557600080fd5b5035612504565b348015610a5857600080fd5b5061044660048036036020811015610a6f57600080fd5b50356001600160a01b031661254f565b348015610a8b57600080fd5b5061062160048036036020811015610aa257600080fd5b50356001600160a01b0316612562565b348015610abe57600080fd5b5061041060048036036020811015610ad557600080fd5b810190602081018135600160201b811115610aef57600080fd5b820183602082011115610b0157600080fd5b803590602001918460018302840111600160201b83111715610b2257600080fd5b50909250905061256d565b348015610b3957600080fd5b5061041060048036036020811015610b5057600080fd5b50356001600160a01b03166125bd565b348015610b6c57600080fd5b50610621612649565b348015610b8157600080fd5b5061048460048036036020811015610b9857600080fd5b503561264f565b348015610bab57600080fd5b5061044660048036036020811015610bc257600080fd5b50356001600160a01b031661266a565b348015610bde57600080fd5b50610410600480360360c0811015610bf557600080fd5b6001600160a01b03823581169260208101359260408201359092169160608201359160808101359181019060c0810160a0820135600160201b811115610c3a57600080fd5b820183602082011115610c4c57600080fd5b803590602001918460018302840111600160201b83111715610c6d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061268a945050505050565b348015610cba57600080fd5b5061062160048036036020811015610cd157600080fd5b50356001600160a01b031661278a565b348015610ced57600080fd5b506106216127f9565b348015610d0257600080fd5b5061041060048036036020811015610d1957600080fd5b810190602081018135600160201b811115610d3357600080fd5b820183602082011115610d4557600080fd5b803590602001918460018302840111600160201b83111715610d6657600080fd5b5090925090506127ff565b348015610d7d57600080fd5b506104106128b4565b348015610d9257600080fd5b5061041060048036036060811015610da957600080fd5b810190602081018135600160201b811115610dc357600080fd5b820183602082011115610dd557600080fd5b803590602001918460208302840111600160201b83111715610df657600080fd5b919390929091602081019035600160201b811115610e1357600080fd5b820183602082011115610e2557600080fd5b803590602001918460208302840111600160201b83111715610e4657600080fd5b919390929091602081019035600160201b811115610e6357600080fd5b820183602082011115610e7557600080fd5b803590602001918460208302840111600160201b83111715610e9657600080fd5b509092509050612966565b348015610ead57600080fd5b5061041060048036036020811015610ec457600080fd5b5035612b73565b348015610ed757600080fd5b5061062160048036036040811015610eee57600080fd5b506001600160a01b0381358116916020013516612bef565b348015610f1257600080fd5b50610621612c7a565b348015610f2757600080fd5b506104b5612c80565b348015610f3c57600080fd5b5061062160048036036020811015610f5357600080fd5b50356001600160a01b0316612e6f565b348015610f6f57600080fd5b5061041060048036036040811015610f8657600080fd5b506001600160a01b038135169060200135612e8a565b348015610fa857600080fd5b5061044660048036036040811015610fbf57600080fd5b50803590602001356001600160a01b0316612f23565b348015610fe157600080fd5b50610484612f44565b348015610ff657600080fd5b506104106004803603604081101561100d57600080fd5b506001600160a01b0381351690602001351515612f53565b34801561103157600080fd5b506104106004803603604081101561104857600080fd5b50803590602001356001600160a01b031661305e565b34801561106a57600080fd5b5061062161322d565b34801561107f57600080fd5b506104466004803603604081101561109657600080fd5b506001600160a01b038135169060200135613233565b3480156110b857600080fd5b50610446600480360360208110156110cf57600080fd5b50356001600160a01b031661329a565b3480156110eb57600080fd5b506106216004803603602081101561110257600080fd5b50356001600160a01b03166132ad565b34801561111e57600080fd5b506104106004803603604081101561113557600080fd5b506001600160a01b03813581169160200135166132cb565b34801561115957600080fd5b506104106004803603604081101561117057600080fd5b50803590602001356001600160a01b0316613425565b34801561119257600080fd5b50610410600480360360a08110156111a957600080fd5b506001600160a01b038135169060ff60208201351690604081013590606081013590608001356134f2565b3480156111e057600080fd5b50610446600480360360408110156111f757600080fd5b506001600160a01b038135169060200135613642565b34801561121957600080fd5b506104106004803603608081101561123057600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561126a57600080fd5b82018360208201111561127c57600080fd5b803590602001918460018302840111600160201b8311171561129d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061373c945050505050565b3480156112ea57600080fd5b506104106137aa565b3480156112ff57600080fd5b506104b56004803603602081101561131657600080fd5b5035613876565b34801561132957600080fd5b50610621613af0565b34801561133e57600080fd5b506104106004803603602081101561135557600080fd5b50356001600160a01b0316613af5565b34801561137157600080fd5b506104106004803603602081101561138857600080fd5b5035613b81565b34801561139b57600080fd5b50610621600480360360408110156113b257600080fd5b506001600160a01b0381358116916020013516613c27565b3480156113d657600080fd5b50610446600480360360408110156113ed57600080fd5b506001600160a01b0381358116916020013516613cd1565b34801561141157600080fd5b50610410613d66565b34801561142657600080fd5b506104106004803603606081101561143d57600080fd5b506001600160a01b038135169060208101359060400135613da4565b34801561146557600080fd5b506104106004803603604081101561147c57600080fd5b506001600160a01b03813516906020013561412a565b34801561149e57600080fd5b50610621600480360360408110156114b557600080fd5b506001600160a01b03813516906020013561426b565b3480156114d757600080fd5b50610621600480360360208110156114ee57600080fd5b50356001600160a01b03166142de565b6001600160e01b0319811660009081526033602052604090205460ff165b919050565b6074818154811061152e57fe5b6000918252602090912001546001600160a01b0316905081565b6078805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115ce5780601f106115a3576101008083540402835291602001916115ce565b820191906000526020600020905b8154815290600101906020018083116115b157829003601f168201915b505050505081565b60008181526073602052604081205482906001600160a01b031661162f576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152607660205260409020546001600160a01b031690565b606954600160a01b900460ff1661169c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116a781336142f0565b806116b757506116b78133614352565b806116df57506000818152607360205260409020546116df906001600160a01b031633613cd1565b61171e576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b336001600160a01b038416141561176b576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260766020908152604080832080546001600160a01b0319166001600160a01b038881169182179092556073909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611816858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061437392505050565b50909695505050505050565b606f546001600160a01b031633148061183f575061183f3361329a565b611890576040805162461bcd60e51b815260206004820152601f60248201527f4f4e4c595f42454e45464943494152595f4f525f4c4f434b4d414e4147455200604482015290519081900360640190fd5b6001600160a01b0381166118dd576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606f80546001600160a01b0319166001600160a01b0392909216919091179055565b606a546001600160a01b031681565b607454606090829084820290600090828401111561193457506074548181039250611939565b508082015b606083604051908082528060200260200182016040528015611965578160200160208202803883390190505b5090506000835b838110156119cf576074818154811061198157fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106119ab57fe5b6001600160a01b03909216602092830291909101909101526001918201910161196c565b50909450505050505b92915050565b606c5481565b606b5481565b606e545b90565b607b5481565b6071546001600160a01b031681565b606954600160a01b900460ff16611a56576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611a608161266a565b611aa1576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611aac81336142f0565b80611abc5750611abc8133614352565b80611ae45750600081815260736020526040902054611ae4906001600160a01b031633613cd1565b611b23576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b611b2d8386612f23565b611b7e576040805162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e455200000000604482015290519081900360640190fd5b612710607b5410611bcf576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416611c1c576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000611c2986600061426b565b6001600160a01b03808816600090815260726020526040808220928916825281206001810154939450919290611c62908890869061457f565b8154611c7e57868255611c7588886146a1565b611c7e87614729565b428111611cac5760018084015490830155868255611c9d876000614764565b611ca788886146a1565b611cc9565b6001830154611cc39042830363ffffffff6147e616565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615adc83398151915291a4505050505050505050565b611d0e3361329a565b611d495760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611d5a60678263ffffffff61484016565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6070546001600160a01b031681565b60008115611dee576040805162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b604482015290519081900360640190fd5b611df783612e6f565b9392505050565b611e073361329a565b611e425760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611e4e607a8383615845565b505050565b336000908152606860205260409020548111611eab576040805162461bcd60e51b81526020600482015260126024820152711393d390d157d053149150511657d554d15160721b604482015290519081900360640190fd5b33600081815260686020908152604091829020849055815184815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a250565b606f546001600160a01b031681565b611f0d3361329a565b611f485760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b604080518381526020810183905281517fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c929181900390910190a1607d91909155607c55565b606954600160a01b900460ff16611fde576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606e54606d5411612026576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038416612073576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038416600090815260726020526040812080549091816120e35761209d836148a7565b825491506120ab87836146a1565b50606b5442016001830181905560405182906001600160a01b03891690600090600080516020615adc833981519152908290a46121ab565b428360010154111561215357606b5460018401546121069163ffffffff6147e616565b600184018190556040805182815290519192506001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9181900360200190a26121ab565b50606b5442016001830181905561216b826000614764565b6040805182815290516001600160a01b038916917f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d919081900360200190a25b60008060006121f18a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061437392505050565b91945092509050811561226b57606a5460408051633652466360e01b8152600481018590526024810184905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b15801561225257600080fd5b505af1158015612266573d6000803e3d6000fd5b505050505b606a546001600160a01b031663939d9f1f846122868c61266a565b80156122a457508c6001600160a01b03168c6001600160a01b031614155b6122af5760006122b1565b8b5b6040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b15801561230057600080fd5b505af1158015612314573d6000803e3d6000fd5b5050606954600092506001600160a01b031615905061235457506069548b906001600160a01b031661234e8133308563ffffffff6148bc16565b50612357565b50345b838110156123a1576040805162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b604482015290519081900360640190fd5b6070546001600160a01b0316156124b057607060009054906101000a90046001600160a01b03166001600160a01b03166398499657338d8d8d8d8a886040518863ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018481526020018381526020018281038252868682818152602001925080828437600081840152601f19601f82011690508083019250505098505050505050505050600060405180830381600087803b15801561249757600080fd5b505af11580156124ab573d6000803e3d6000fd5b505050505b505050505050505050505050565b606954600160a01b900460ff1681565b611e4e8383836040518060200160405280600081525061373c565b6075602052600090815260409020546001600160a01b031681565b6000606e54821061254b576040805162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b604482015290519081900360640190fd5b5090565b60006119d860678363ffffffff61491616565b60006119d88261497d565b6125763361329a565b6125b15760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b611e4e60788383615845565b6125c63361329a565b6126015760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b61261260678263ffffffff614a8416565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b607c5481565b6000908152607360205260409020546001600160a01b031690565b6001600160a01b0316600090815260726020526040902060010154421090565b600054610100900460ff16806126a357506126a3614b05565b806126b1575060005460ff16155b6126ec5760405162461bcd60e51b815260040180806020018281038252602e815260200180615aae602e913960400191505060405180910390fd5b600054610100900460ff16158015612717576000805460ff1961ff0019909116610100171660011790555b61272085614b0b565b612728614bda565b61273487878686614bef565b61273d82614c85565b612745614cb1565b61274d614cc3565b61275687614ccb565b61275f87614ce9565b61276f6380ac58cd60e01b614d07565b8015612781576000805461ff00191690555b50505050505050565b60006001600160a01b0382166127d9576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6127e28261266a565b6127ed5760006127f0565b60015b60ff1692915050565b606d5481565b6128083361329a565b6128435760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b61284f60798383615845565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b600054610100900460ff16806128cd57506128cd614b05565b806128db575060005460ff16155b6129165760405162461bcd60e51b815260040180806020018281038252602e815260200180615aae602e913960400191505060405180910390fd5b600054610100900460ff16158015612941576000805460ff1961ff0019909116610100171660011790555b6129516301ffc9a760e01b614d07565b8015612963576000805461ff00191690555b50565b61296f3361254f565b8061297e575061297e3361329a565b6129b95760405162461bcd60e51b8152600401808060200182810382526048815260200180615a026048913960600191505060405180910390fd5b60005b858110156127815760008787838181106129d257fe5b905060200201356001600160a01b0316905060008686848181106129f257fe5b9050602002013590506000858585818110612a0957fe5b905060200201356001600160a01b0316905060006001600160a01b0316836001600160a01b03161415612a75576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6001600160a01b038316600090815260726020526040902060018101548311612ad8576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b805480612af557612ae8826148a7565b508054612af585826146a1565b612aff8184614764565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615adc833981519152908290a45050600190930192506129bc915050565b612b7c3361329a565b612bb75760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b6040805182815290517f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49181900360200190a1607b55565b600030604051808061594860259139604080519182900360250182206001600160a01b03881660009081526068602081815291849020546bffffffffffffffffffffffff19606098891b811684880152603487019490945260548601529588901b90911660748401528151808403909501855260889092019052825192019190912091505092915050565b60745490565b60795460609060026000196101006001841615020190911604612ddd57606a60009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b158015612ceb57600080fd5b505afa158015612cff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d2857600080fd5b8101908080516040519392919084600160201b821115612d4757600080fd5b908301906020820185811115612d5c57600080fd5b8251600160201b811182820188101715612d7557600080fd5b82525081516020918201929091019080838360005b83811015612da2578181015183820152602001612d8a565b50505050905090810190601f168015612dcf5780820380516001836020036101000a031916815260200191505b5060405250505090506119ee565b6079805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015612e635780601f10612e3857610100808354040283529160200191612e63565b820191906000526020600020905b815481529060010190602001808311612e4657829003601f168201915b505050505090506119ee565b6001600160a01b031660009081526072602052604090205490565b612e933361329a565b612ece5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b81612ed88161266a565b612f19576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e4e8383614d8b565b600091825260736020526040909120546001600160a01b0391821691161490565b6069546001600160a01b031681565b606954600160a01b900460ff16612fa3576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612ff0576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526077602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b6130673361329a565b6130a25760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b606954600160a01b900460ff166130f2576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606c546069546001600160a01b03908116908316158061317657506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561314857600080fd5b505afa15801561315c573d6000803e3d6000fd5b505050506040513d602081101561317257600080fd5b5051115b6131b7576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b606c849055606980546001600160a01b0319166001600160a01b038581169190911791829055604080518581526020810188905284831681830152929091166060830152517f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d4916080908290030190a150505050565b607d5481565b606b54336000908152607260205260408120600181015491928402918390613261904263ffffffff614e8616565b90508083101561327f5761327a86836000015485613da4565b61328e565b61328e33878460000154611a06565b50600195945050505050565b60006119d860668363ffffffff61491616565b6001600160a01b031660009081526072602052604090206001015490565b6132d43361329a565b61330f5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b6001600160a01b03821615806133325750613332826001600160a01b0316614ec8565b613383576040805162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b0000000000000000604482015290519081900360640190fd5b6001600160a01b03811615806133a657506133a6816001600160a01b0316614ec8565b6133f7576040805162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b000000000000604482015290519081900360640190fd5b607080546001600160a01b039384166001600160a01b03199182161790915560718054929093169116179055565b60008281526073602052604090205482906001600160a01b031661347e576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b61348883336142f0565b8061349757506134973361329a565b6134e8576040805162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f55504441544500604482015290519081900360640190fd5b611e4e8383614764565b6134fc8533612bef565b85858585836001600160a01b0316600161351587614f04565b85858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561356f573d6000803e3d6000fd5b505050602060405103516001600160a01b0316146135c8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b038416600081815260686020908152604091829020805460010190819055825190815291517ff5d035b703f1ad8d403dd02e821d04257acafc5f6c5d70a3907bd8abf33a2e0f9281900390910190a260006136298761264f565b905060006136368261497d565b90506124b08282614d8b565b600061364d3361329a565b806136625750606f546001600160a01b031633145b6136b3576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b6069546040805163095ea7b360e01b81526001600160a01b038681166004830152602482018690529151919092169163095ea7b39160448083019260209291908290030181600087803b15801561370957600080fd5b505af115801561371d573d6000803e3d6000fd5b505050506040513d602081101561373357600080fd5b50519392505050565b613747848484611a06565b61375384848484614f55565b6137a4576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b50505050565b6137b33361329a565b6137ee5760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b606954600160a01b900460ff1661383e576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16069805460ff60a01b19169055565b606080808061388430615088565b90506060851561389e5761389786615204565b92506138b1565b6040518060200160405280600081525092505b607a5460026000196101006001841615020190911604613a2257606a60009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b15801561391957600080fd5b505afa15801561392d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561395657600080fd5b8101908080516040519392919084600160201b82111561397557600080fd5b90830190602082018581111561398a57600080fd5b8251600160201b8111828201881017156139a357600080fd5b82525081516020918201929091019080838360005b838110156139d05781810151838201526020016139b8565b50505050905090810190601f1680156139fd5780820380516001836020036101000a031916815260200191505b506040818101905260018152602f60f81b6020820152939750929350613ad492505050565b607a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015613aa85780601f10613a7d57610100808354040283529160200191613aa8565b820191906000526020600020905b815481529060010190602001808311613a8b57829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b613ae68483838663ffffffff6152c816565b9695505050505050565b600890565b613afe3361329a565b613b395760405162461bcd60e51b815260040180806020018281038252603b81526020018061596d603b913960400191505060405180910390fd5b613b4a60668263ffffffff614a8416565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b80613b8c81336142f0565b80613b9c5750613b9c8133614352565b80613bc45750600081815260736020526040902054613bc4906001600160a01b031633613cd1565b613c03576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b6000613c0e8361264f565b90506000613c1b8261497d565b90506137a48282614d8b565b60006001600160a01b038316613c4857506001600160a01b038116316119d8565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613c9e57600080fd5b505afa158015613cb2573d6000803e3d6000fd5b505050506040513d6020811015613cc857600080fd5b505190506119d8565b6001600160a01b038083166000908152607260209081526040808320548084526075909252822054919290911680613d34575050506001600160a01b0380831660009081526077602090815260408083209385168352929052205460ff166119d8565b6001600160a01b0390811660009081526077602090815260408083209387168352929052205460ff1691506119d89050565b613d7760663363ffffffff61484016565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b606954600160a01b900460ff16613df4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81613dff81336142f0565b80613e0f5750613e0f8133614352565b80613e375750600081815260736020526040902054613e37906001600160a01b031633613cd1565b613e76576040805162461bcd60e51b815260206004820152601c60248201526000805160206159e2833981519152604482015290519081900360640190fd5b612710607b5410613ec7576040805162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b604482015290519081900360640190fd5b6001600160a01b038416613f14576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000838152607360205260409020546001600160a01b0316613f358161266a565b613f76576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0380821660009081526072602052604080822092881682528120805460018401549192909142900381613fb0878a61426b565b90506000613fc48a8363ffffffff6147e616565b905082811015613fe257899350613fdd8b82600061457f565b614026565b613fec888461426b565b42600189015560405181850395509092508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b8461406d57614034866148a7565b855494506140428c866146a1565b60405185906001600160a01b038e1690600090600080516020615adc833981519152908290a4614083565b4286600101541161408357614083856000614764565b61408f8585600161457f565b848c6001600160a01b0316896001600160a01b0316600080516020615adc83398151915260405160405180910390a46140d9888d8d60405180602001604052806000815250614f55565b6124b0576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b6141333361329a565b806141485750606f546001600160a01b031633145b614199576040805162461bcd60e51b815260206004820181905260248201527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604482015290519081900360640190fd5b60006141a58330613c27565b905060008215806141b557508183115b156142095760008211614202576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b508061420c565b50815b606f546040805183815290516001600160a01b039283169287169133917f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9181900360200190a4606f546137a49085906001600160a01b031683615419565b60006142768361266a565b614282575060006119d8565b6001600160a01b03831660009081526072602052604081209080846142af574283600101540391506142b3565b8491505b6127106142cb607b548461546690919063ffffffff16565b816142d257fe5b0493506119d892505050565b60686020526000908152604090205481565b6000828152607560205260408120546001600160a01b038381169116148061433d57506000838152607560205260409020546001600160a01b031615801561433d575061433d8383612f23565b1561434a575060016119d8565b5060006119d8565b600091825260766020526040909120546001600160a01b0391821691161490565b607054600090819081906001600160a01b0316156144875760705460405163221c1fd160e01b815233600482018181526001600160a01b038a811660248501528981166044850152608060648501908152895160848601528951919095169463221c1fd1948c938c938c93919260a40190602085019080838360005b838110156144075781810151838201526020016143ef565b50505050905090810190601f1680156144345780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038186803b15801561445457600080fd5b505afa158015614468573d6000803e3d6000fd5b505050506040513d602081101561447e57600080fd5b5051925061448d565b606c5492505b821561457657606a5460408051630cb175e360e01b81526001600160a01b038981166004830152602482018790528251931692630cb175e392604480840193919291829003018186803b1580156144e357600080fd5b505afa1580156144f7573d6000803e3d6000fd5b505050506040513d604081101561450d57600080fd5b508051602090910151909250905082821115614570576040805162461bcd60e51b815260206004820152601c60248201527f494e56414c49445f444953434f554e545f46524f4d5f554e4c4f434b00000000604482015290519081900360640190fd5b81830392505b93509350939050565b6000838152607360205260409020546001600160a01b0316806145dc576040805162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b604482015290519081900360640190fd5b6001600160a01b0381166000908152607260205260408120600181015490916146048461266a565b9050841561464757801561462c57614622828763ffffffff6147e616565b6001840155614642565b61463c428763ffffffff6147e616565b60018401555b61465d565b614657828763ffffffff614e8616565b60018401555b604080518781528615156020820152815189927fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3928290030190a250505050505050565b6000818152607360205260409020546001600160a01b038381169116146147255760748054600181019091557f19a0b39aa25ac793b5f6e9a0534364cc0b3fd1ea9b651e79c7f50a59d48ef8130180546001600160a01b0384166001600160a01b031991821681179092556000838152607360205260409020805490911690911790555b5050565b6000818152607660205260409020546001600160a01b03161561296357600090815260766020526040902080546001600160a01b0319169055565b6000828152607560205260409020546001600160a01b0382811691161461472557600082815260756020526040902080546001600160a01b0319166001600160a01b0383161790556147b582614729565b60405160009083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e3908390a35050565b600082820183811015611df7576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b61484a8282614916565b6148855760405162461bcd60e51b8152600401808060200182810382526021815260200180615a4a6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b805461296357606e8054600101908190559055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526137a49085906154bf565b60006001600160a01b03821661495d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615a8c6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000816149898161266a565b6149ca576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526072602052604090206001810154606b54607d544290920391820110614a0357606c549350614a24565b606b54606c54614a19908363ffffffff61546616565b81614a2057fe5b0493505b607d541580614a385750606b54607d548201105b15614a7c576000612710614a59607c54606c5461546690919063ffffffff16565b81614a6057fe5b04905080851115614a75578085039450614a7a565b600094505b505b505050919050565b614a8e8282614916565b15614ae0576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b303b1590565b606980546001600160a01b0319166001600160a01b0383169081179091551580614b9957506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015614b6b57600080fd5b505afa158015614b7f573d6000803e3d6000fd5b505050506040513d6020811015614b9557600080fd5b5051115b612963576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b6069805460ff60a01b1916600160a01b179055565b63bbf81e00831115614c48576040805162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606a8054336001600160a01b031991821617909155606f80549091166001600160a01b039590951694909417909355606b91909155606c55606d55565b614c8d6128b4565b8051614ca09060789060208401906158bf565b50612963635b5e139f60e01b614d07565b614cc163780e9d6360e01b614d07565b565b6103e8607c55565b614cd48161329a565b6129635761296360668263ffffffff614a8416565b614cf28161254f565b6129635761296360678263ffffffff614a8416565b6001600160e01b03198082161415614d66576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152603360205260409020805460ff19166001179055565b6001600160a01b03821660008181526072602090815260409182902080548351868152935191943394909391927f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528929181900390910190a44260018201558115614e0657606954614e06906001600160a01b03168484615419565b6071546001600160a01b031615611e4e576071546040805163b499b6c560e01b81523360048201526001600160a01b038681166024830152604482018690529151919092169163b499b6c591606480830192600092919082900301818387803b158015614e7257600080fd5b505af1158015612781573d6000803e3d6000fd5b6000611df783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615677565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590614efc57508115155b949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b6000614f69846001600160a01b0316614ec8565b614f7557506001614efc565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614fef578181015183820152602001614fd7565b50505050905090810190601f16801561501c5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561503e57600080fd5b505af1158015615052573d6000803e3d6000fd5b505050506040513d602081101561506857600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106150ec57fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061511557fe5b60200101906001600160f81b031916908160001a90535060005b60148110156151fb578260048583600c016020811061514a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061516a57fe5b602001015160f81c60f81b82826002026002018151811061518757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106151ae57fe5b825191901a600f169081106151bf57fe5b602001015160f81c60f81b8282600202600301815181106151dc57fe5b60200101906001600160f81b031916908160001a90535060010161512f565b50949350505050565b6060818061522b5750506040805180820190915260018152600360fc1b602082015261151c565b8260005b811561524357600101600a8204915061522f565b6060816040519080825280601f01601f191660200182016040528015615270576020820181803883390190505b50905060001982015b84156152be57600a850660300160f81b8282806001900393508151811061529c57fe5b60200101906001600160f81b031916908160001a905350600a85049450615279565b5095945050505050565b6060848484846040516020018085805190602001908083835b602083106153005780518252601f1990920191602091820191016152e1565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106153485780518252601f199092019160209182019101615329565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106153905780518252601f199092019160209182019101615371565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106153d85780518252601f1990920191602091820191016153b9565b6001836020036101000a0380198251168184511680821785525050505050509050019450505050506040516020818303038152906040529050949350505050565b8015611e4e576001600160a01b03831661544b576154466001600160a01b0383168263ffffffff61570e16565b611e4e565b826137a46001600160a01b038216848463ffffffff6157f316565b600082615475575060006119d8565b8282028284828161548257fe5b0414611df75760405162461bcd60e51b8152600401808060200182810382526021815260200180615a6b6021913960400191505060405180910390fd5b6154d1826001600160a01b0316614ec8565b615522576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106155605780518252601f199092019160209182019101615541565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146155c2576040519150601f19603f3d011682016040523d82523d6000602084013e6155c7565b606091505b50915091508161561e576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156137a45780806020019051602081101561563a57600080fd5b50516137a45760405162461bcd60e51b815260040180806020018281038252602a815260200180615afc602a913960400191505060405180910390fd5b600081848411156157065760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156156cb5781810151838201526020016156b3565b50505050905090810190601f1680156156f85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b80471015615763576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146157ae576040519150601f19603f3d011682016040523d82523d6000602084013e6157b3565b606091505b5050905080611e4e5760405162461bcd60e51b815260040180806020018281038252603a8152602001806159a8603a913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611e4e9084906154bf565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158865782800160ff198235161785556158b3565b828001600101855582156158b3579182015b828111156158b3578235825591602001919060010190615898565b5061254b92915061592d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061590057805160ff19168380011785556158b3565b828001600101855582156158b3579182015b828111156158b3578251825591602001919060010190615912565b6119ee91905b8082111561254b576000815560010161593356fe63616e63656c416e64526566756e64466f722861646472657373205f6b65794f776e6572294d6978696e4c6f636b4d616e616765723a2063616c6c657220646f6573206e6f74206861766520746865204c6f636b4d616e6167657220726f6c65416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f4e4c595f4b45595f4d414e414745525f4f525f415050524f564544000000004d6978696e4b65794772616e7465723a2063616c6c657220646f6573206e6f74206861766520746865204b65794772616e746572206f72204c6f636b4d616e6167657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158209749e0c6496e968cb0d91da8eb9608ffcbbdceecce35d34911522be79830c67764736f6c63430005110032", - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13.Emscripten.clang" - }, - "schemaVersion": "3.2.0", - "updatedAt": "2020-07-11T18:54:37.073Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV0.json b/packages/contracts/src/abis/Unlock/UnlockV0.json deleted file mode 100644 index ed41ea9c9ae..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV0.json +++ /dev/null @@ -1,269 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "name": "deployed", - "type": "bool" - }, - { - "name": "totalSales", - "type": "uint256" - }, - { - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - } - ], - "name": "OwnershipRenounced", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "name": "createLock", - "outputs": [ - { - "name": "lock", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_purchaser", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "name": "discount", - "type": "uint256" - }, - { - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_discount", - "type": "uint256" - }, - { - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50612897806100206000396000f300608060405260043610620000c65763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630cb175e38114620000cb57806336524663146200010b5780635de9a137146200012b578063715018a6146200016f5780638da5cb5b14620001875780638f32d59b14620001bb578063939d9f1f14620001e7578063a082eb0e146200020e578063c4d66de81462000238578063d6e9e803146200025c578063f2fde38b1462000274578063f8f7a9fa1462000298575b600080fd5b348015620000d857600080fd5b50620000f2600160a060020a0360043516602435620002b9565b6040805192835260208301919091528051918290030190f35b3480156200011857600080fd5b5062000129600435602435620002c2565b005b3480156200013857600080fd5b506200014f600160a060020a03600435166200035e565b604080519315158452602084019290925282820152519081900360600190f35b3480156200017c57600080fd5b506200012962000383565b3480156200019457600080fd5b506200019f620003f0565b60408051600160a060020a039092168252519081900360200190f35b348015620001c857600080fd5b50620001d3620003ff565b604080519115158252519081900360200190f35b348015620001f457600080fd5b5062000129600435600160a060020a036024351662000410565b3480156200021b57600080fd5b5062000226620004ac565b60408051918252519081900360200190f35b3480156200024557600080fd5b5062000129600160a060020a0360043516620004b2565b3480156200026957600080fd5b5062000226620005ac565b3480156200028157600080fd5b5062000129600160a060020a0360043516620005b2565b348015620002a557600080fd5b506200019f600435602435604435620005d6565b50600091829150565b3360009081526068602052604090205460ff16151562000352576040805160e560020a62461bcd02815260206004820152602360248201527f4f6e6c792066726f6d2070726576696f75736c79206465706c6f796564206c6f60448201527f636b730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60678054830190555050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6200038d620003ff565b15156200039957600080fd5b603354604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26033805473ffffffffffffffffffffffffffffffffffffffff19169055565b603354600160a060020a031690565b603354600160a060020a0316331490565b3360009081526068602052604090205460ff161515620004a0576040805160e560020a62461bcd02815260206004820152602360248201527f4f6e6c792066726f6d2070726576696f75736c79206465706c6f796564206c6f60448201527f636b730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60668054830190555050565b60675481565b60008054610100900460ff1680620004cf5750620004cf620006b7565b80620004de575060005460ff16155b15156200055b576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166200058782620006bd565b60006066819055606781905580549115156101000261ff001990921691909117905550565b60665481565b620005bc620003ff565b1515620005c857600080fd5b620005d381620007c2565b50565b60008033858585620005e762000841565b600160a060020a039094168452602084019290925260408084019190915260608301919091525190819003608001906000f0801580156200062c573d6000803e3d6000fd5b5060408051606081018252600180825260006020808401828152848601838152600160a060020a03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3949350505050565b303b1590565b60008054610100900460ff1680620006da5750620006da620006b7565b80620006e9575060005460ff16155b151562000766576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b50600080546033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381161515620007d857600080fd5b603354604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b604051612019806200085383390190560060806040523480156200001157600080fd5b5060405160808062002019833981016040908152815160208301519183015160609093015190929063bbf81e00831115620000d357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45787069726174696f6e206475726174696f6e2065786365656473203130302060448201527f7965617273000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60998054600160a060020a03191633179055620000fe84640100000000620012636200012982021704565b6200011664010000000062000f836200023082021704565b609a92909255609b55609c5550620003ca565b60008054610100900460ff16806200014f57506200014f64010000000062000357810204565b806200015e575060005460ff16155b1515620001e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e602482015260008051602062001ff983398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b60008054610100900460ff16806200025657506200025664010000000062000357810204565b8062000265575060005460ff16155b1515620002e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e602482015260008051602062001ff983398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166200033d7f01ffc9a7000000000000000000000000000000000000000000000000000000006401000000006200035d810204565b600080549115156101000261ff0019909216919091179055565b303b1590565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200038d57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152603360205260409020805460ff19166001179055565b611c1f80620003da6000396000f3006080604052600436106101715763ffffffff60e060020a60003504166301ffc9a78114610176578063025e7c27146101ac578063081812fc146101e0578063095ea7b3146101f85780630f15023b1461021157806310803b721461022657806310e569731461029157806311a4c03a146102b8578063150b7a02146102cd5780631f1ec0291461035957806323b872dd146103715780633ba70e311461038e5780633ccfd60b146103a357806347dc1085146103b857806353b704d0146103cd5780636352211e146103ed57806370a0823114610405578063715018a61461042657806371d2ee6c1461043b57806374b6c106146104535780638129fc1c146104685780638da5cb5b1461047d5780638f32d59b1461049257806393fd1844146104a7578063970aaeb7146104bc5780639f98d3cb146104dd578063abdf82ce146104fe578063c4d66de81461051f578063d44fa14a14610540578063d8125eb3146105d6578063f2fde38b146105fe575b600080fd5b34801561018257600080fd5b50610198600160e060020a03196004351661061f565b604080519115158252519081900360200190f35b3480156101b857600080fd5b506101c460043561063e565b60408051600160a060020a039092168252519081900360200190f35b3480156101ec57600080fd5b506101c4600435610666565b61020f600160a060020a0360043516602435610677565b005b34801561021d57600080fd5b506101c4610719565b34801561023257600080fd5b50610241600435602435610728565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561027d578181015183820152602001610265565b505050509050019250505060405180910390f35b34801561029d57600080fd5b506102a66108c4565b60408051918252519081900360200190f35b3480156102c457600080fd5b506102a66108ca565b3480156102d957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261033c94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506108d09650505050505050565b60408051600160e060020a03199092168252519081900360200190f35b34801561036557600080fd5b5061020f6004356108f9565b61020f600160a060020a0360043581169060243516604435610956565b34801561039a57600080fd5b506102a6610cba565b3480156103af57600080fd5b5061020f610cc0565b3480156103c457600080fd5b506102a6610d3c565b61020f60048035600160a060020a03169060248035908101910135610d43565b3480156103f957600080fd5b506101c4600435610d84565b34801561041157600080fd5b506102a6600160a060020a0360043516610dff565b34801561043257600080fd5b5061020f610e95565b34801561044757600080fd5b5061020f600435610ef2565b34801561045f57600080fd5b506102a6610f7d565b34801561047457600080fd5b5061020f610f83565b34801561048957600080fd5b506101c461108b565b34801561049e57600080fd5b5061019861109a565b3480156104b357600080fd5b506102a66110ab565b3480156104c857600080fd5b506102a6600160a060020a03600435166110b1565b3480156104e957600080fd5b5061020f600160a060020a0360043516611133565b34801561050a57600080fd5b506102a6600160a060020a03600435166111de565b34801561052b57600080fd5b5061020f600160a060020a0360043516611263565b34801561054c57600080fd5b50610561600160a060020a0360043516611356565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561059b578181015183820152602001610583565b50505050905090810190601f1680156105c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020f600160a060020a0360048035821691602480359091169160443591820191013561146b565b34801561060a57600080fd5b5061020f600160a060020a0360043516611524565b600160e060020a03191660009081526033602052604090205460ff1690565b60a080548290811061064c57fe5b600091825260209091200154600160a060020a0316905081565b600061067182611540565b92915050565b6000818152609f60205260409020548190600160a060020a0316331461069c57600080fd5b600160a060020a03831615156106b157600080fd5b600082815260a1602090815260408083208054600160a060020a031916600160a060020a03888116918217909255609f909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b609954600160a060020a031681565b60606000806060600080600061073c610d3c565b11610791576040805160e560020a62461bcd02815260206004820152601360248201527f4e6f206b65797320746f20726574726965766500000000000000000000000000604482015290519081900360640190fd5b8688029450600085101580156107ad57506107aa610d3c565b85105b1515610803576040805160e560020a62461bcd02815260206004820152601760248201527f496e646578206d75737420626520696e2d626f756e6473000000000000000000604482015290519081900360640190fd5b60a054858801111561081e5760a05485810397509350610824565b86850193505b8660405190808252806020026020018201604052801561084e578160200160208202803883390190505b509250600091508490505b838110156108b85760a080548290811061086f57fe5b6000918252602090912001548351600160a060020a039091169084908490811061089557fe5b600160a060020a0390921660209283029091019091015260019182019101610859565b50909695505050505050565b609b5481565b609a5481565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b600061090361109a565b151561090e57600080fd5b50609b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b6000609d54609c541115156109db576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152609e6020526040902060018101548591904210610a51576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b6000848152609f60205260409020548490600160a060020a0316331480610a88575033610a7d82611540565b600160a060020a0316145b1515610ade576040805160e560020a62461bcd02815260206004820181905260248201527f4f6e6c79206b6579206f776e6572206f7220617070726f766564206f776e6572604482015290519081900360640190fd5b600160a060020a0386161515610af357600080fd5b600160a060020a0386166000908152609e60205260409020600101549350831515610b845760a08054600181019091557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038816600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b428411610bb957600160a060020a038088166000908152609e6020526040808220600190810154938a16835291200155610c04565b600160a060020a0387166000908152609e6020526040902060010154610be79042860363ffffffff61156416565b600160a060020a0387166000908152609e60205260409020600101555b600160a060020a038088166000908152609e60205260408082209289168252902060029182018054610c4a93928301926000196101006001841615020190911604611aca565b50600160a060020a038088166000818152609e602090815260408083204260019091015589835260a19091528082208054600160a060020a03191690555188938a1692917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b609d5481565b6000610cca61109a565b1515610cd557600080fd5b50303160008111610d30576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610d398161157d565b50565b609d545b90565b610d7f83600084848080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050565b6000818152609f60205260408120548290600160a060020a03161515610de2576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b50506000908152609f6020526040902054600160a060020a031690565b6000600160a060020a0382161515610e61576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382166000908152609e602052604081206001015411610e89576000610e8c565b60015b60ff1692915050565b610e9d61109a565b1515610ea857600080fd5b606654604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a260668054600160a060020a0319169055565b6000610efc61109a565b1515610f0757600080fd5b503031600081118015610f1a5750818110155b1515610f70576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610f798261157d565b5050565b609c5481565b60008054610100900460ff1680610f9d5750610f9d611a13565b80610fab575060005460ff16155b1515611027576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166110717f01ffc9a700000000000000000000000000000000000000000000000000000000611a1d565b600080549115156101000261ff0019909216919091179055565b606654600160a060020a031690565b606654600160a060020a0316331490565b60a05490565b600160a060020a0381166000908152609e6020526040812060018101548391908310611115576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090205490565b61113b61109a565b151561114657600080fd5b600160a060020a0381166000908152609e60205260409020600181015482919042106111bc576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b5050600160a060020a03166000908152609e6020526040902042600190910155565b600160a060020a0381166000908152609e6020526040812060018101548391908310611242576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090206001015490565b60008054610100900460ff168061127d575061127d611a13565b8061128b575060005460ff16155b1515611307576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381166000908152609e602052604081206001810154606092849291116113bc576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b600160a060020a0384166000908152609e60209081526040918290206002908101805484516001821615610100026000190190911692909204601f81018490048402830184019094528382529092909183018282801561145d5780601f106114325761010080835404028352916020019161145d565b820191906000526020600020905b81548152906001019060200180831161144057829003601f168201915b505050505092505050919050565b600160a060020a0383166000908152609e60205260409020600181015484919042106114e1576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b61151c868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050505050565b61152c61109a565b151561153757600080fd5b610d3981611a59565b600081815260a16020526040812054600160a060020a031680151561067157600080fd5b60008282018381101561157657600080fd5b9392505050565b61158561108b565b600160a060020a03166108fc829081150290604051600060405180830381858888f193505050501580156115bd573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600080600080600080609d54609c54111515611683576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a038916151561169857600080fd5b609954609b54604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152602482018490528251941699509195508892630cb175e39260448082019392918290030181600087803b15801561170b57600080fd5b505af115801561171f573d6000803e3d6000fd5b505050506040513d604081101561173557600080fd5b508051602090910151909550935082915081851115611757576000915061175d565b84830391505b348211156117b5576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50600160a060020a0388166000908152609e6020526040902060010154428110156118815780151561185757609d8054600190810190915560a0805491820190557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038b16600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b609a54600160a060020a038a166000908152609e60205260409020429091016001909101556118b2565b609a5461189590829063ffffffff61156416565b600160a060020a038a166000908152609e60205260409020600101555b600160a060020a0389166000908152609e6020908152604090912088516118e1926002909201918a0190611b4b565b5060008511156119555785600160a060020a0316633652466386866040518363ffffffff1660e060020a0281526004018083815260200182815260200192505050600060405180830381600087803b15801561193c57600080fd5b505af1158015611950573d6000803e3d6000fd5b505050505b85600160a060020a031663939d9f1f838a6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b5050604051600160a060020a038c1692508291506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050505050505050565b303b8015905b5090565b600160e060020a03198082161415611a3457600080fd5b600160e060020a0319166000908152603360205260409020805460ff19166001179055565b600160a060020a0381161515611a6e57600080fd5b606654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360668054600160a060020a031916600160a060020a0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b035780548555611b3f565b82800160010185558215611b3f57600052602060002091601f016020900482015b82811115611b3f578254825591600101919060010190611b24565b50611a19929150611bb9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b8c57805160ff1916838001178555611b3f565b82800160010185558215611b3f579182015b82811115611b3f578251825591602001919060010190611b9e565b610d4091905b80821115611a195760008155600101611bbf56004e6f2073756368206b6579000000000000000000000000000000000000000000a165627a7a72305820be0f0296c7f54e6f6a0d497b8f41b62652244fa2177534a70d7837c6fb9fc5ca0029436f6e747261637420696e7374616e63652068617320616c7265616479206265a165627a7a72305820074a253e19bdba965850026596bc4c7e7d6739d950ddc40957e766b8134e97360029", - "deployedBytecode": "0x608060405260043610620000c65763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630cb175e38114620000cb57806336524663146200010b5780635de9a137146200012b578063715018a6146200016f5780638da5cb5b14620001875780638f32d59b14620001bb578063939d9f1f14620001e7578063a082eb0e146200020e578063c4d66de81462000238578063d6e9e803146200025c578063f2fde38b1462000274578063f8f7a9fa1462000298575b600080fd5b348015620000d857600080fd5b50620000f2600160a060020a0360043516602435620002b9565b6040805192835260208301919091528051918290030190f35b3480156200011857600080fd5b5062000129600435602435620002c2565b005b3480156200013857600080fd5b506200014f600160a060020a03600435166200035e565b604080519315158452602084019290925282820152519081900360600190f35b3480156200017c57600080fd5b506200012962000383565b3480156200019457600080fd5b506200019f620003f0565b60408051600160a060020a039092168252519081900360200190f35b348015620001c857600080fd5b50620001d3620003ff565b604080519115158252519081900360200190f35b348015620001f457600080fd5b5062000129600435600160a060020a036024351662000410565b3480156200021b57600080fd5b5062000226620004ac565b60408051918252519081900360200190f35b3480156200024557600080fd5b5062000129600160a060020a0360043516620004b2565b3480156200026957600080fd5b5062000226620005ac565b3480156200028157600080fd5b5062000129600160a060020a0360043516620005b2565b348015620002a557600080fd5b506200019f600435602435604435620005d6565b50600091829150565b3360009081526068602052604090205460ff16151562000352576040805160e560020a62461bcd02815260206004820152602360248201527f4f6e6c792066726f6d2070726576696f75736c79206465706c6f796564206c6f60448201527f636b730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60678054830190555050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6200038d620003ff565b15156200039957600080fd5b603354604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26033805473ffffffffffffffffffffffffffffffffffffffff19169055565b603354600160a060020a031690565b603354600160a060020a0316331490565b3360009081526068602052604090205460ff161515620004a0576040805160e560020a62461bcd02815260206004820152602360248201527f4f6e6c792066726f6d2070726576696f75736c79206465706c6f796564206c6f60448201527f636b730000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60668054830190555050565b60675481565b60008054610100900460ff1680620004cf5750620004cf620006b7565b80620004de575060005460ff16155b15156200055b576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166200058782620006bd565b60006066819055606781905580549115156101000261ff001990921691909117905550565b60665481565b620005bc620003ff565b1515620005c857600080fd5b620005d381620007c2565b50565b60008033858585620005e762000841565b600160a060020a039094168452602084019290925260408084019190915260608301919091525190819003608001906000f0801580156200062c573d6000803e3d6000fd5b5060408051606081018252600180825260006020808401828152848601838152600160a060020a03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3949350505050565b303b1590565b60008054610100900460ff1680620006da5750620006da620006b7565b80620006e9575060005460ff16155b151562000766576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b50600080546033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381161515620007d857600080fd5b603354604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b604051612019806200085383390190560060806040523480156200001157600080fd5b5060405160808062002019833981016040908152815160208301519183015160609093015190929063bbf81e00831115620000d357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45787069726174696f6e206475726174696f6e2065786365656473203130302060448201527f7965617273000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b60998054600160a060020a03191633179055620000fe84640100000000620012636200012982021704565b6200011664010000000062000f836200023082021704565b609a92909255609b55609c5550620003ca565b60008054610100900460ff16806200014f57506200014f64010000000062000357810204565b806200015e575060005460ff16155b1515620001e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e602482015260008051602062001ff983398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b60008054610100900460ff16806200025657506200025664010000000062000357810204565b8062000265575060005460ff16155b1515620002e857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e602482015260008051602062001ff983398151915260448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166200033d7f01ffc9a7000000000000000000000000000000000000000000000000000000006401000000006200035d810204565b600080549115156101000261ff0019909216919091179055565b303b1590565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200038d57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152603360205260409020805460ff19166001179055565b611c1f80620003da6000396000f3006080604052600436106101715763ffffffff60e060020a60003504166301ffc9a78114610176578063025e7c27146101ac578063081812fc146101e0578063095ea7b3146101f85780630f15023b1461021157806310803b721461022657806310e569731461029157806311a4c03a146102b8578063150b7a02146102cd5780631f1ec0291461035957806323b872dd146103715780633ba70e311461038e5780633ccfd60b146103a357806347dc1085146103b857806353b704d0146103cd5780636352211e146103ed57806370a0823114610405578063715018a61461042657806371d2ee6c1461043b57806374b6c106146104535780638129fc1c146104685780638da5cb5b1461047d5780638f32d59b1461049257806393fd1844146104a7578063970aaeb7146104bc5780639f98d3cb146104dd578063abdf82ce146104fe578063c4d66de81461051f578063d44fa14a14610540578063d8125eb3146105d6578063f2fde38b146105fe575b600080fd5b34801561018257600080fd5b50610198600160e060020a03196004351661061f565b604080519115158252519081900360200190f35b3480156101b857600080fd5b506101c460043561063e565b60408051600160a060020a039092168252519081900360200190f35b3480156101ec57600080fd5b506101c4600435610666565b61020f600160a060020a0360043516602435610677565b005b34801561021d57600080fd5b506101c4610719565b34801561023257600080fd5b50610241600435602435610728565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561027d578181015183820152602001610265565b505050509050019250505060405180910390f35b34801561029d57600080fd5b506102a66108c4565b60408051918252519081900360200190f35b3480156102c457600080fd5b506102a66108ca565b3480156102d957600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261033c94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506108d09650505050505050565b60408051600160e060020a03199092168252519081900360200190f35b34801561036557600080fd5b5061020f6004356108f9565b61020f600160a060020a0360043581169060243516604435610956565b34801561039a57600080fd5b506102a6610cba565b3480156103af57600080fd5b5061020f610cc0565b3480156103c457600080fd5b506102a6610d3c565b61020f60048035600160a060020a03169060248035908101910135610d43565b3480156103f957600080fd5b506101c4600435610d84565b34801561041157600080fd5b506102a6600160a060020a0360043516610dff565b34801561043257600080fd5b5061020f610e95565b34801561044757600080fd5b5061020f600435610ef2565b34801561045f57600080fd5b506102a6610f7d565b34801561047457600080fd5b5061020f610f83565b34801561048957600080fd5b506101c461108b565b34801561049e57600080fd5b5061019861109a565b3480156104b357600080fd5b506102a66110ab565b3480156104c857600080fd5b506102a6600160a060020a03600435166110b1565b3480156104e957600080fd5b5061020f600160a060020a0360043516611133565b34801561050a57600080fd5b506102a6600160a060020a03600435166111de565b34801561052b57600080fd5b5061020f600160a060020a0360043516611263565b34801561054c57600080fd5b50610561600160a060020a0360043516611356565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561059b578181015183820152602001610583565b50505050905090810190601f1680156105c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61020f600160a060020a0360048035821691602480359091169160443591820191013561146b565b34801561060a57600080fd5b5061020f600160a060020a0360043516611524565b600160e060020a03191660009081526033602052604090205460ff1690565b60a080548290811061064c57fe5b600091825260209091200154600160a060020a0316905081565b600061067182611540565b92915050565b6000818152609f60205260409020548190600160a060020a0316331461069c57600080fd5b600160a060020a03831615156106b157600080fd5b600082815260a1602090815260408083208054600160a060020a031916600160a060020a03888116918217909255609f909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b609954600160a060020a031681565b60606000806060600080600061073c610d3c565b11610791576040805160e560020a62461bcd02815260206004820152601360248201527f4e6f206b65797320746f20726574726965766500000000000000000000000000604482015290519081900360640190fd5b8688029450600085101580156107ad57506107aa610d3c565b85105b1515610803576040805160e560020a62461bcd02815260206004820152601760248201527f496e646578206d75737420626520696e2d626f756e6473000000000000000000604482015290519081900360640190fd5b60a054858801111561081e5760a05485810397509350610824565b86850193505b8660405190808252806020026020018201604052801561084e578160200160208202803883390190505b509250600091508490505b838110156108b85760a080548290811061086f57fe5b6000918252602090912001548351600160a060020a039091169084908490811061089557fe5b600160a060020a0390921660209283029091019091015260019182019101610859565b50909695505050505050565b609b5481565b609a5481565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b600061090361109a565b151561090e57600080fd5b50609b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b6000609d54609c541115156109db576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a0384166000908152609e6020526040902060018101548591904210610a51576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b6000848152609f60205260409020548490600160a060020a0316331480610a88575033610a7d82611540565b600160a060020a0316145b1515610ade576040805160e560020a62461bcd02815260206004820181905260248201527f4f6e6c79206b6579206f776e6572206f7220617070726f766564206f776e6572604482015290519081900360640190fd5b600160a060020a0386161515610af357600080fd5b600160a060020a0386166000908152609e60205260409020600101549350831515610b845760a08054600181019091557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038816600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b428411610bb957600160a060020a038088166000908152609e6020526040808220600190810154938a16835291200155610c04565b600160a060020a0387166000908152609e6020526040902060010154610be79042860363ffffffff61156416565b600160a060020a0387166000908152609e60205260409020600101555b600160a060020a038088166000908152609e60205260408082209289168252902060029182018054610c4a93928301926000196101006001841615020190911604611aca565b50600160a060020a038088166000818152609e602090815260408083204260019091015589835260a19091528082208054600160a060020a03191690555188938a1692917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050505050565b609d5481565b6000610cca61109a565b1515610cd557600080fd5b50303160008111610d30576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610d398161157d565b50565b609d545b90565b610d7f83600084848080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050565b6000818152609f60205260408120548290600160a060020a03161515610de2576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b50506000908152609f6020526040902054600160a060020a031690565b6000600160a060020a0382161515610e61576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0382166000908152609e602052604081206001015411610e89576000610e8c565b60015b60ff1692915050565b610e9d61109a565b1515610ea857600080fd5b606654604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a260668054600160a060020a0319169055565b6000610efc61109a565b1515610f0757600080fd5b503031600081118015610f1a5750818110155b1515610f70576040805160e560020a62461bcd02815260206004820152601060248201527f4e6f7420656e6f7567682066756e647300000000000000000000000000000000604482015290519081900360640190fd5b610f798261157d565b5050565b609c5481565b60008054610100900460ff1680610f9d5750610f9d611a13565b80610fab575060005460ff16155b1515611027576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff1916919091179092550460ff166110717f01ffc9a700000000000000000000000000000000000000000000000000000000611a1d565b600080549115156101000261ff0019909216919091179055565b606654600160a060020a031690565b606654600160a060020a0316331490565b60a05490565b600160a060020a0381166000908152609e6020526040812060018101548391908310611115576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090205490565b61113b61109a565b151561114657600080fd5b600160a060020a0381166000908152609e60205260409020600181015482919042106111bc576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b5050600160a060020a03166000908152609e6020526040902042600190910155565b600160a060020a0381166000908152609e6020526040812060018101548391908310611242576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b505050600160a060020a03166000908152609e602052604090206001015490565b60008054610100900460ff168061127d575061127d611a13565b8061128b575060005460ff16155b1515611307576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b506000805460668054600160a060020a031916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a0381166000908152609e602052604081206001810154606092849291116113bc576040805160e560020a62461bcd02815260206004820152600b6024820152600080516020611bd4833981519152604482015290519081900360640190fd5b600160a060020a0384166000908152609e60209081526040918290206002908101805484516001821615610100026000190190911692909204601f81018490048402830184019094528382529092909183018282801561145d5780601f106114325761010080835404028352916020019161145d565b820191906000526020600020905b81548152906001019060200180831161144057829003601f168201915b505050505092505050919050565b600160a060020a0383166000908152609e60205260409020600181015484919042106114e1576040805160e560020a62461bcd02815260206004820152601060248201527f4b6579206973206e6f742076616c696400000000000000000000000000000000604482015290519081900360640190fd5b61151c868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437506115f7945050505050565b505050505050565b61152c61109a565b151561153757600080fd5b610d3981611a59565b600081815260a16020526040812054600160a060020a031680151561067157600080fd5b60008282018381101561157657600080fd5b9392505050565b61158561108b565b600160a060020a03166108fc829081150290604051600060405180830381858888f193505050501580156115bd573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600080600080600080609d54609c54111515611683576040805160e560020a62461bcd02815260206004820152602360248201527f4d6178696d756d206e756d626572206f66206b65797320616c7265616479207360448201527f6f6c640000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a038916151561169857600080fd5b609954609b54604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a038d81166004830152602482018490528251941699509195508892630cb175e39260448082019392918290030181600087803b15801561170b57600080fd5b505af115801561171f573d6000803e3d6000fd5b505050506040513d604081101561173557600080fd5b508051602090910151909550935082915081851115611757576000915061175d565b84830391505b348211156117b5576040805160e560020a62461bcd02815260206004820152601260248201527f496e73756666696369656e742066756e64730000000000000000000000000000604482015290519081900360640190fd5b50600160a060020a0388166000908152609e6020526040902060010154428110156118815780151561185757609d8054600190810190915560a0805491820190557f78fdc8d422c49ced035a9edf18d00d3c6a8d81df210f3e5e448e045e77b41e88018054600160a060020a038b16600160a060020a031991821681179092556000828152609f6020908152604080832080549094168517909355609e905220555b609a54600160a060020a038a166000908152609e60205260409020429091016001909101556118b2565b609a5461189590829063ffffffff61156416565b600160a060020a038a166000908152609e60205260409020600101555b600160a060020a0389166000908152609e6020908152604090912088516118e1926002909201918a0190611b4b565b5060008511156119555785600160a060020a0316633652466386866040518363ffffffff1660e060020a0281526004018083815260200182815260200192505050600060405180830381600087803b15801561193c57600080fd5b505af1158015611950573d6000803e3d6000fd5b505050505b85600160a060020a031663939d9f1f838a6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a0316815260200192505050600060405180830381600087803b1580156119b857600080fd5b505af11580156119cc573d6000803e3d6000fd5b5050604051600160a060020a038c1692508291506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050505050505050565b303b8015905b5090565b600160e060020a03198082161415611a3457600080fd5b600160e060020a0319166000908152603360205260409020805460ff19166001179055565b600160a060020a0381161515611a6e57600080fd5b606654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360668054600160a060020a031916600160a060020a0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b035780548555611b3f565b82800160010185558215611b3f57600052602060002091601f016020900482015b82811115611b3f578254825591600101919060010190611b24565b50611a19929150611bb9565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611b8c57805160ff1916838001178555611b3f565b82800160010185558215611b3f579182015b82811115611b3f578251825591602001919060010190611b9e565b610d4091905b80821115611a195760008155600101611bbf56004e6f2073756368206b6579000000000000000000000000000000000000000000a165627a7a72305820be0f0296c7f54e6f6a0d497b8f41b62652244fa2177534a70d7837c6fb9fc5ca0029436f6e747261637420696e7374616e63652068617320616c7265616479206265a165627a7a72305820074a253e19bdba965850026596bc4c7e7d6739d950ddc40957e766b8134e97360029", - "compiler": { - "name": "solc", - "version": "0.4.25+commit.59dbf8f1.Emscripten.clang" - }, - "schemaVersion": "2.0.2", - "updatedAt": "2019-03-02T13:33:23.721Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV1.json b/packages/contracts/src/abis/Unlock/UnlockV1.json deleted file mode 100644 index 234a262c446..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV1.json +++ /dev/null @@ -1,266 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "name": "deployed", - "type": "bool" - }, - { - "name": "totalSales", - "type": "uint256" - }, - { - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "name": "createLock", - "outputs": [ - { - "name": "lock", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_purchaser", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "name": "discount", - "type": "uint256" - }, - { - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_discount", - "type": "uint256" - }, - { - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b5061413b806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000e1576000357c010000000000000000000000000000000000000000000000000000000090048063939d9f1f1162000098578063939d9f1f1462000238578063a082eb0e1462000267578063b8199af21462000283578063c4d66de814620002be578063d6e9e80314620002e7578063f2fde38b14620002f157620000e1565b80630cb175e314620001315780633652466314620001795780635de9a13714620001a1578063715018a614620001ea5780638da5cb5b14620001f45780638f32d59b146200021a575b6040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b62000160600480360360408110156200014957600080fd5b50600160a060020a0381351690602001356200031a565b6040805192835260208301919091528051918290030190f35b6200019f600480360360408110156200019157600080fd5b508035906020013562000323565b005b620001ca60048036036020811015620001b957600080fd5b5035600160a060020a031662000397565b604080519315158452602084019290925282820152519081900360600190f35b6200019f620003bc565b620001fe62000427565b60408051600160a060020a039092168252519081900360200190f35b6200022462000436565b604080519115158252519081900360200190f35b6200019f600480360360408110156200025057600080fd5b5080359060200135600160a060020a031662000447565b62000271620004bb565b60408051918252519081900360200190f35b620001fe600480360360808110156200029b57600080fd5b50803590600160a060020a036020820135169060408101359060600135620004c1565b6200019f60048036036020811015620002d657600080fd5b5035600160a060020a0316620005b2565b6200027162000663565b6200019f600480360360208110156200030957600080fd5b5035600160a060020a031662000669565b50600091829150565b3360009081526068602052604090205460ff166200038b576040805160e560020a62461bcd02815260206004820152600a60248201527f4f4e4c595f4c4f434b5300000000000000000000000000000000000000000000604482015290519081900360640190fd5b60678054830190555050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b620003c662000436565b620003d057600080fd5b603354604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36033805473ffffffffffffffffffffffffffffffffffffffff19169055565b603354600160a060020a031690565b603354600160a060020a0316331490565b3360009081526068602052604090205460ff16620004af576040805160e560020a62461bcd02815260206004820152600a60248201527f4f4e4c595f4c4f434b5300000000000000000000000000000000000000000000604482015290519081900360640190fd5b60668054830190555050565b60675481565b6000803386868686604051620004d79062000811565b600160a060020a0395861681526020810194909452919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000526573d6000803e3d6000fd5b5060408051606081018252600180825260006020808401828152848601838152600160a060020a03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b600054610100900460ff1680620005ce5750620005ce6200068b565b80620005dd575060005460ff16155b6200061d5760405160e560020a62461bcd02815260040180806020018281038252602e815260200180620040e2602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff16620006488262000691565b600080549115156101000261ff001990921691909117905550565b60665481565b6200067362000436565b6200067d57600080fd5b620006888162000794565b50565b303b1590565b600054610100900460ff1680620006ad5750620006ad6200068b565b80620006bc575060005460ff16155b620006fc5760405160e560020a62461bcd02815260040180806020018281038252602e815260200180620040e2602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff19169190911783556033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b600160a060020a038116620007a857600080fd5b603354604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6138c280620008208339019056fe60806040526001607455600a607555600560765560646077553480156200002557600080fd5b5060405160a080620038c2833981018060405260a08110156200004757600080fd5b50805160208201516040830151606084015160809094015192939192909190838282600186620000a07f01ffc9a700000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b600160a060020a03811615806200013a5750600081600160a060020a03166318160ddd6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156200010a57600080fd5b505afa1580156200011f573d6000803e3d6000fd5b505050506040513d60208110156200013657600080fd5b5051115b620001a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460a060020a60ff0219600160a060020a03909316600160a060020a031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200025c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054600160a060020a03191633179055606993909355606a91909155606b55606d55620002b47f80ac58cd00000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b620002cd85640100000000620022846200034582021704565b505050505062000460565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200030857600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200036a57506200036a6401000000006200045a810204565b8062000379575060015460ff16155b620003d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003894602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff1916831790925560348054600160a060020a031916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b61342480620004706000396000f3fe608060405260043610610337576000357c01000000000000000000000000000000000000000000000000000000009004806370a08231116101c85780639d76ea5811610114578063c4d66de8116100b2578063e985e9c51161008c578063e985e9c514610ddb578063f2fde38b14610e16578063f6e4641f14610e49578063f8faf94214610e6f57610337565b8063c4d66de814610d7e578063d1bbd49c14610db1578063d42cfc4114610dc657610337565b8063a843a4e7116100ee578063a843a4e714610c5b578063abdf82ce14610c70578063b88d4fde14610ca3578063c1c98d0314610d6957610337565b80639d76ea5814610bd85780639f98d3cb14610bed578063a22cb46514610c2057610337565b80638da5cb5b1161018157806393fd18441161015b57806393fd184414610b1e578063970aaeb714610b33578063994a8a7114610b665780639b3f0b1714610b9f57610337565b80638da5cb5b14610adf5780638f32d59b14610af45780638f98ce8f14610b0957610337565b806370a082311461095b57806370efb7701461098e578063715018a6146109bc57806371d2ee6c146109d157806374b6c106146109fb5780637c7c425314610a1057610337565b80631f1ec029116102875780633d3359cb1161024057806352d6a8e41161021a57806352d6a8e41461084e578063550ef3a8146108815780636352211e146108fe5780636d8ea5b41461092857610337565b80633d3359cb146107d35780634136aa351461080357806342842e0e1461081857610337565b80631f1ec029146107045780632009dc651461072e57806323b872dd1461074357806339f46986146107795780633ba70e31146107a95780633ccfd60b146107be57610337565b80630ed3e2cc116102f457806310e56973116102ce57806310e56973146105d557806311a4c03a146105ea578063150b7a02146105ff57806318160ddd146106ef57610337565b80630ed3e2cc1461052b5780630f15023b1461054057806310803b721461055557610337565b806301ffc9a714610394578063025e7c27146103dc57806306fdde0314610422578063081812fc146104ac578063095ea7b3146104d65780630c79130f14610504575b34801561034357600080fd5b506040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b3480156103a057600080fd5b506103c8600480360360208110156103b757600080fd5b5035600160e060020a031916610eec565b604080519115158252519081900360200190f35b3480156103e857600080fd5b50610406600480360360208110156103ff57600080fd5b5035610f0f565b60408051600160a060020a039092168252519081900360200190f35b34801561042e57600080fd5b50610437610f36565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610471578181015183820152602001610459565b50505050905090810190601f16801561049e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104b857600080fd5b50610406600480360360208110156104cf57600080fd5b5035610fcd565b610502600480360360408110156104ec57600080fd5b50600160a060020a038135169060200135610fde565b005b34801561051057600080fd5b50610519611191565b60408051918252519081900360200190f35b34801561053757600080fd5b50610519611197565b34801561054c57600080fd5b5061040661119d565b34801561056157600080fd5b506105856004803603604081101561057857600080fd5b50803590602001356111ac565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105c15781810151838201526020016105a9565b505050509050019250505060405180910390f35b3480156105e157600080fd5b506105196112d1565b3480156105f657600080fd5b506105196112d7565b34801561060b57600080fd5b506106d26004803603608081101561062257600080fd5b600160a060020a0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561065d57600080fd5b82018360208201111561066f57600080fd5b8035906020019184600183028401116401000000008311171561069157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112dd945050505050565b60408051600160e060020a03199092168252519081900360200190f35b3480156106fb57600080fd5b50610519611307565b34801561071057600080fd5b506105026004803603602081101561072757600080fd5b503561130d565b34801561073a57600080fd5b506105026113b4565b6105026004803603606081101561075957600080fd5b50600160a060020a03813581169160208101359091169060400135611420565b34801561078557600080fd5b506105026004803603604081101561079c57600080fd5b508035906020013561164f565b3480156107b557600080fd5b5061051961170d565b3480156107ca57600080fd5b50610502611713565b3480156107df57600080fd5b50610502600480360360408110156107f657600080fd5b5080359060200135611795565b34801561080f57600080fd5b506103c8611853565b6105026004803603606081101561082e57600080fd5b50600160a060020a03813581169160208101359091169060400135611863565b34801561085a57600080fd5b506105196004803603602081101561087157600080fd5b5035600160a060020a0316611883565b34801561088d57600080fd5b50610502600480360360208110156108a457600080fd5b8101906020810181356401000000008111156108bf57600080fd5b8201836020820111156108d157600080fd5b803590602001918460018302840111640100000000831117156108f357600080fd5b50909250905061188e565b34801561090a57600080fd5b506104066004803603602081101561092157600080fd5b50356118ab565b34801561093457600080fd5b506103c86004803603602081101561094b57600080fd5b5035600160a060020a0316611936565b34801561096757600080fd5b506105196004803603602081101561097e57600080fd5b5035600160a060020a0316611956565b610502600480360360408110156109a457600080fd5b50600160a060020a03813581169160200135166119d7565b3480156109c857600080fd5b50610502611a7c565b3480156109dd57600080fd5b50610502600480360360208110156109f457600080fd5b5035611ae4565b348015610a0757600080fd5b50610519611bbb565b348015610a1c57600080fd5b5061050260048036036040811015610a3357600080fd5b810190602081018135640100000000811115610a4e57600080fd5b820183602082011115610a6057600080fd5b80359060200191846020830284011164010000000083111715610a8257600080fd5b919390929091602081019035640100000000811115610aa057600080fd5b820183602082011115610ab257600080fd5b80359060200191846020830284011164010000000083111715610ad457600080fd5b509092509050611bc1565b348015610aeb57600080fd5b50610406611c23565b348015610b0057600080fd5b506103c8611c32565b348015610b1557600080fd5b50610519611c43565b348015610b2a57600080fd5b50610519611c49565b348015610b3f57600080fd5b5061051960048036036020811015610b5657600080fd5b5035600160a060020a0316611c4f565b348015610b7257600080fd5b506103c860048036036040811015610b8957600080fd5b5080359060200135600160a060020a0316611ce1565b348015610bab57600080fd5b5061050260048036036040811015610bc257600080fd5b50600160a060020a038135169060200135611d02565b348015610be457600080fd5b50610406611d1d565b348015610bf957600080fd5b5061050260048036036020811015610c1057600080fd5b5035600160a060020a0316611d2c565b348015610c2c57600080fd5b5061050260048036036040811015610c4357600080fd5b50600160a060020a0381351690602001351515611de4565b348015610c6757600080fd5b50610502611f02565b348015610c7c57600080fd5b5061051960048036036020811015610c9357600080fd5b5035600160a060020a0316611faf565b61050260048036036080811015610cb957600080fd5b600160a060020a03823581169260208101359091169160408201359190810190608081016060820135640100000000811115610cf457600080fd5b820183602082011115610d0657600080fd5b80359060200191846001830284011164010000000083111715610d2857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612044945050505050565b348015610d7557600080fd5b506105026121db565b348015610d8a57600080fd5b5061050260048036036020811015610da157600080fd5b5035600160a060020a0316612284565b348015610dbd57600080fd5b50610519612380565b348015610dd257600080fd5b50610519612386565b348015610de757600080fd5b506103c860048036036040811015610dfe57600080fd5b50600160a060020a038135811691602001351661238c565b348015610e2257600080fd5b5061050260048036036020811015610e3957600080fd5b5035600160a060020a03166123ba565b61050260048036036020811015610e5f57600080fd5b5035600160a060020a03166123d4565b348015610e7b57600080fd5b5061050260048036036040811015610e9257600080fd5b810190602081018135640100000000811115610ead57600080fd5b820183602082011115610ebf57600080fd5b80359060200191846020830284011164010000000083111715610ee157600080fd5b91935091503561242e565b600160e060020a0319811660009081526020819052604090205460ff165b919050565b60708181548110610f1c57fe5b600091825260209091200154600160a060020a0316905081565b60738054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fc25780601f10610f9757610100808354040283529160200191610fc2565b820191906000526020600020905b815481529060010190602001808311610fa557829003601f168201915b505050505090505b90565b6000610fd88261247d565b92915050565b60675460a060020a900460ff1661102d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b806110388133611ce1565b80611048575061104881336124ea565b80611060575061106061105a826118ab565b3361238c565b6110b4576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b33600160a060020a0384161415611115576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b6000828152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385169081179091558290611157826118ab565b600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60755481565b60745481565b606854600160a060020a031681565b607054606090611206576040805160e560020a62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b60705482908482029060009082840111156112295750607054818103925061122e565b508082015b60608360405190808252806020026020018201604052801561125a578160200160208202803883390190505b5090506000835b838110156112c4576070818154811061127657fe5b9060005260206000200160009054906101000a9004600160a060020a03168383815181106112a057fe5b600160a060020a039092166020928302919091019091015260019182019101611261565b5090979650505050505050565b606a5481565b60695481565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b606c5490565b611315611c32565b61131e57600080fd5b60675460a060020a900460ff1661136d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113bf3361250b565b905060006113cc33612525565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a3426001830155801561141c5761141c3382612605565b5050565b60675460a060020a900460ff1661146f576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8261147981611936565b6114bb576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b816114c68133611ce1565b806114d657506114d681336124ea565b806114e857506114e861105a826118ab565b61153c576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b600160a060020a038416611588576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b60006115938661250b565b905060006115a08661250b565b60018101548154919250906115b457825482555b6115c287836000015461283b565b4281116115d857600180840154908301556115f5565b60018301546115ef9042830363ffffffff6128cf16565b60018301555b426001840155611604866128e8565b8587600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611657611c32565b61166057600080fd5b806116b5576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607491909155607555565b606c5481565b61171b611c32565b61172457600080fd5b600061172f30612930565b905060008111611789576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792816129d7565b50565b61179d611c32565b6117a657600080fd5b806117fb576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b60675460a060020a900460ff1681565b61187e83838360405180602001604052806000815250612044565b505050565b6000610fd882612525565b611896611c32565b61189f57600080fd5b61187e607383836132d2565b6000818152606f60205260408120548290600160a060020a0316611919576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b50506000908152606f6020526040902054600160a060020a031690565b600160a060020a03166000908152606e6020526040902060010154421090565b6000600160a060020a0382166119a4576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e60205260409020600101546119cb5760006119ce565b60015b60ff1692915050565b60675460a060020a900460ff16611a26576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b80611a3081611936565b611a72576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b61187e8383612a21565b611a84611c32565b611a8d57600080fd5b603454604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36034805473ffffffffffffffffffffffffffffffffffffffff19169055565b611aec611c32565b611af557600080fd5b60008111611b4d576040805160e560020a62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5830612930565b905081811015611bb2576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b61141c826129d7565b606b5481565b611bc9611c32565b611bd257600080fd5b60005b83811015611c1c57611c14858583818110611bec57fe5b90506020020135600160a060020a0316848484818110611c0857fe5b90506020020135612d43565b600101611bd5565b5050505050565b603454600160a060020a031690565b603454600160a060020a0316331490565b60765481565b60705490565b600160a060020a0381166000908152606e602052604081206001810154839190611cc3576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090205490565b6000918252606f602052604090912054600160a060020a0391821691161490565b611d0a611c32565b611d1357600080fd5b61141c8282612d43565b606754600160a060020a031681565b611d34611c32565b611d3d57600080fd5b80611d4781611936565b611d89576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b60675460a060020a900460ff16611e33576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b600160a060020a038216331415611e94576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152607260209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611f0a611c32565b611f1357600080fd5b60675460a060020a900460ff1615611f75576040805160e560020a62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b600160a060020a0381166000908152606e602052604081206001810154839190612023576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090206001015490565b60675460a060020a900460ff16612093576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8161209e8133611ce1565b806120ae57506120ae81336124ea565b806120c057506120c061105a826118ab565b612114576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b61211d836118ab565b61212681611936565b612168576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b612173868686611420565b61217f86868686612e52565b6121d3576040805160e560020a62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6121e3611c32565b6121ec57600080fd5b60675460a060020a900460ff1661223b576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061229d575061229d612fb7565b806122ab575060015460ff16155b6122e95760405160e560020a62461bcd02815260040180806020018281038252602e81526020018061338b602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff191683179092556034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606d5481565b60775481565b600160a060020a03918216600090815260726020908152604080832093909416825291909152205460ff1690565b6123c2611c32565b6123cb57600080fd5b61179281612fbd565b60675460a060020a900460ff16612423576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b611792816000612a21565b612436611c32565b61243f57600080fd5b60005b828110156124775761246f84848381811061245957fe5b90506020020135600160a060020a031683612d43565b600101612442565b50505050565b600081815260716020526040812054600160a060020a031680610fd8576040805160e560020a62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b60009182526071602052604090912054600160a060020a0391821691161490565b600160a060020a03166000908152606e6020526040902090565b60008161253181611936565b612573576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600061257e8461250b565b90506000428260010154039050606954811061259e57606a5493506125bf565b606954606a546125b4908363ffffffff61303916565b816125bb57fe5b0493505b60006075546125db607454606a5461303990919063ffffffff16565b816125e257fe5b049050808511156125f75780850394506125fc565b600094505b50505050919050565b606754600160a060020a031661265157604051600160a060020a0383169082156108fc029083906000818181858888f1935050505015801561264b573d6000803e3d6000fd5b5061141c565b6067546040805160e060020a6370a08231028152600160a060020a0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b1580156126a657600080fd5b505afa1580156126ba573d6000803e3d6000fd5b505050506040513d60208110156126d057600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561274157600080fd5b505af1158015612755573d6000803e3d6000fd5b505050506040513d602081101561276b57600080fd5b50506040805160e060020a6370a08231028152600160a060020a038681166004830152915183928516916370a08231916024808301926020929190829003018186803b1580156127ba57600080fd5b505afa1580156127ce573d6000803e3d6000fd5b505050506040513d60208110156127e457600080fd5b505111612477576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b6000818152606f6020526040902054600160a060020a0383811691161461141c5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b018054600160a060020a03841673ffffffffffffffffffffffffffffffffffffffff1991821681179092556000838152606f60205260409020805490911690911790555050565b6000828201838110156128e157600080fd5b9392505050565b600081815260716020526040902054600160a060020a031615611792576000908152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b606754600090600160a060020a03166129545750600160a060020a03811631610f0a565b6067546040805160e060020a6370a08231028152600160a060020a038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156129a457600080fd5b505afa1580156129b8573d6000803e3d6000fd5b505050506040513d60208110156129ce57600080fd5b50519050610f0a565b6129e86129e2611c23565b82612605565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606c54606b5411612a7c576040805160e560020a62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216612ac8576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b606a54606854604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612b3a57600080fd5b505afa158015612b4e573d6000803e3d6000fd5b505050506040513d6040811015612b6457600080fd5b50805160209091015190935091508080841115612b8357506000612b88565b508281035b612b9181613060565b6000612b9c8761250b565b600181015490915042811015612bd257612bb5826132b7565b612bc388836000015461283b565b60695442016001830155612bec565b606954612be690829063ffffffff6128cf16565b60018301555b8515612c7857606854604080517f3652466300000000000000000000000000000000000000000000000000000000815260048101899052602481018890529051600160a060020a039092169163365246639160448082019260009290919082900301818387803b158015612c5f57600080fd5b505af1158015612c73573d6000803e3d6000fd5b505050505b606854604080517f939d9f1f00000000000000000000000000000000000000000000000000000000815260048101869052600160a060020a038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612ce657600080fd5b505af1158015612cfa573d6000803e3d6000fd5b5050606c54604051909250600160a060020a038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b600160a060020a038216612d8f576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b6000612d9a8361250b565b905080600101548211612df7576040805160e560020a62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b612e00816132b7565b612e0e83826000015461283b565b600181018290558054604051600160a060020a038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000612e6684600160a060020a03166132cc565b612e72575060016112ff565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015612f05578181015183820152602001612eed565b50505050905090810190601f168015612f325780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612f5457600080fd5b505af1158015612f68573d6000803e3d6000fd5b505050506040513d6020811015612f7e57600080fd5b5051600160e060020a0319167f150b7a020000000000000000000000000000000000000000000000000000000014915050949350505050565b303b1590565b600160a060020a038116612fd057600080fd5b603454604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008261304857506000610fd8565b8282028284828161305557fe5b04146128e157600080fd5b606754600160a060020a03166130cd57803410156130c8576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792565b6067546040805160e060020a6370a082310281523060048201529051600160a060020a039092169160009183916370a0823191602480820192602092909190829003018186803b15801561312057600080fd5b505afa158015613134573d6000803e3d6000fd5b505050506040513d602081101561314a57600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690529051919250600160a060020a038416916323b872dd916064808201926020929091908290030181600087803b1580156131be57600080fd5b505af11580156131d2573d6000803e3d6000fd5b505050506040513d60208110156131e857600080fd5b50506040805160e060020a6370a0823102815230600482015290518291600160a060020a038516916370a0823191602480820192602092909190829003018186803b15801561323657600080fd5b505afa15801561324a573d6000803e3d6000fd5b505050506040513d602081101561326057600080fd5b50511161187e576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b805461179257606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106133135782800160ff19823516178555613340565b82800160010185558215613340579182015b82811115613340578235825591602001919060010190613325565b5061334c929150613350565b5090565b610fca91905b8082111561334c576000815560010161335656fe4c4f434b5f444550524543415445440000000000000000000000000000000000436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65644b45595f4e4f545f56414c494400000000000000000000000000000000000000494e56414c49445f414444524553530000000000000000000000000000000000a165627a7a72305820307d7415f1879a4c56340443cd73d8bea62267dd331ec6d62442029fc4f258790029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a723058203e7ea4127724044a183879e7ab1ae9026261e202e8b32d7e782c980e83ede77e0029", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000e1576000357c010000000000000000000000000000000000000000000000000000000090048063939d9f1f1162000098578063939d9f1f1462000238578063a082eb0e1462000267578063b8199af21462000283578063c4d66de814620002be578063d6e9e80314620002e7578063f2fde38b14620002f157620000e1565b80630cb175e314620001315780633652466314620001795780635de9a13714620001a1578063715018a614620001ea5780638da5cb5b14620001f45780638f32d59b146200021a575b6040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b62000160600480360360408110156200014957600080fd5b50600160a060020a0381351690602001356200031a565b6040805192835260208301919091528051918290030190f35b6200019f600480360360408110156200019157600080fd5b508035906020013562000323565b005b620001ca60048036036020811015620001b957600080fd5b5035600160a060020a031662000397565b604080519315158452602084019290925282820152519081900360600190f35b6200019f620003bc565b620001fe62000427565b60408051600160a060020a039092168252519081900360200190f35b6200022462000436565b604080519115158252519081900360200190f35b6200019f600480360360408110156200025057600080fd5b5080359060200135600160a060020a031662000447565b62000271620004bb565b60408051918252519081900360200190f35b620001fe600480360360808110156200029b57600080fd5b50803590600160a060020a036020820135169060408101359060600135620004c1565b6200019f60048036036020811015620002d657600080fd5b5035600160a060020a0316620005b2565b6200027162000663565b6200019f600480360360208110156200030957600080fd5b5035600160a060020a031662000669565b50600091829150565b3360009081526068602052604090205460ff166200038b576040805160e560020a62461bcd02815260206004820152600a60248201527f4f4e4c595f4c4f434b5300000000000000000000000000000000000000000000604482015290519081900360640190fd5b60678054830190555050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b620003c662000436565b620003d057600080fd5b603354604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36033805473ffffffffffffffffffffffffffffffffffffffff19169055565b603354600160a060020a031690565b603354600160a060020a0316331490565b3360009081526068602052604090205460ff16620004af576040805160e560020a62461bcd02815260206004820152600a60248201527f4f4e4c595f4c4f434b5300000000000000000000000000000000000000000000604482015290519081900360640190fd5b60668054830190555050565b60675481565b6000803386868686604051620004d79062000811565b600160a060020a0395861681526020810194909452919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000526573d6000803e3d6000fd5b5060408051606081018252600180825260006020808401828152848601838152600160a060020a03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b600054610100900460ff1680620005ce5750620005ce6200068b565b80620005dd575060005460ff16155b6200061d5760405160e560020a62461bcd02815260040180806020018281038252602e815260200180620040e2602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff16620006488262000691565b600080549115156101000261ff001990921691909117905550565b60665481565b6200067362000436565b6200067d57600080fd5b620006888162000794565b50565b303b1590565b600054610100900460ff1680620006ad5750620006ad6200068b565b80620006bc575060005460ff16155b620006fc5760405160e560020a62461bcd02815260040180806020018281038252602e815260200180620040e2602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff19169190911783556033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b600160a060020a038116620007a857600080fd5b603354604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36033805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6138c280620008208339019056fe60806040526001607455600a607555600560765560646077553480156200002557600080fd5b5060405160a080620038c2833981018060405260a08110156200004757600080fd5b50805160208201516040830151606084015160809094015192939192909190838282600186620000a07f01ffc9a700000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b600160a060020a03811615806200013a5750600081600160a060020a03166318160ddd6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b1580156200010a57600080fd5b505afa1580156200011f573d6000803e3d6000fd5b505050506040513d60208110156200013657600080fd5b5051115b620001a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460a060020a60ff0219600160a060020a03909316600160a060020a031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200025c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054600160a060020a03191633179055606993909355606a91909155606b55606d55620002b47f80ac58cd00000000000000000000000000000000000000000000000000000000640100000000620002d8810204565b620002cd85640100000000620022846200034582021704565b505050505062000460565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200030857600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200036a57506200036a6401000000006200045a810204565b8062000379575060015460ff16155b620003d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003894602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff1916831790925560348054600160a060020a031916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b61342480620004706000396000f3fe608060405260043610610337576000357c01000000000000000000000000000000000000000000000000000000009004806370a08231116101c85780639d76ea5811610114578063c4d66de8116100b2578063e985e9c51161008c578063e985e9c514610ddb578063f2fde38b14610e16578063f6e4641f14610e49578063f8faf94214610e6f57610337565b8063c4d66de814610d7e578063d1bbd49c14610db1578063d42cfc4114610dc657610337565b8063a843a4e7116100ee578063a843a4e714610c5b578063abdf82ce14610c70578063b88d4fde14610ca3578063c1c98d0314610d6957610337565b80639d76ea5814610bd85780639f98d3cb14610bed578063a22cb46514610c2057610337565b80638da5cb5b1161018157806393fd18441161015b57806393fd184414610b1e578063970aaeb714610b33578063994a8a7114610b665780639b3f0b1714610b9f57610337565b80638da5cb5b14610adf5780638f32d59b14610af45780638f98ce8f14610b0957610337565b806370a082311461095b57806370efb7701461098e578063715018a6146109bc57806371d2ee6c146109d157806374b6c106146109fb5780637c7c425314610a1057610337565b80631f1ec029116102875780633d3359cb1161024057806352d6a8e41161021a57806352d6a8e41461084e578063550ef3a8146108815780636352211e146108fe5780636d8ea5b41461092857610337565b80633d3359cb146107d35780634136aa351461080357806342842e0e1461081857610337565b80631f1ec029146107045780632009dc651461072e57806323b872dd1461074357806339f46986146107795780633ba70e31146107a95780633ccfd60b146107be57610337565b80630ed3e2cc116102f457806310e56973116102ce57806310e56973146105d557806311a4c03a146105ea578063150b7a02146105ff57806318160ddd146106ef57610337565b80630ed3e2cc1461052b5780630f15023b1461054057806310803b721461055557610337565b806301ffc9a714610394578063025e7c27146103dc57806306fdde0314610422578063081812fc146104ac578063095ea7b3146104d65780630c79130f14610504575b34801561034357600080fd5b506040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f46414c4c4241434b000000000000000000000000000000000000000000604482015290519081900360640190fd5b3480156103a057600080fd5b506103c8600480360360208110156103b757600080fd5b5035600160e060020a031916610eec565b604080519115158252519081900360200190f35b3480156103e857600080fd5b50610406600480360360208110156103ff57600080fd5b5035610f0f565b60408051600160a060020a039092168252519081900360200190f35b34801561042e57600080fd5b50610437610f36565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610471578181015183820152602001610459565b50505050905090810190601f16801561049e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104b857600080fd5b50610406600480360360208110156104cf57600080fd5b5035610fcd565b610502600480360360408110156104ec57600080fd5b50600160a060020a038135169060200135610fde565b005b34801561051057600080fd5b50610519611191565b60408051918252519081900360200190f35b34801561053757600080fd5b50610519611197565b34801561054c57600080fd5b5061040661119d565b34801561056157600080fd5b506105856004803603604081101561057857600080fd5b50803590602001356111ac565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105c15781810151838201526020016105a9565b505050509050019250505060405180910390f35b3480156105e157600080fd5b506105196112d1565b3480156105f657600080fd5b506105196112d7565b34801561060b57600080fd5b506106d26004803603608081101561062257600080fd5b600160a060020a0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561065d57600080fd5b82018360208201111561066f57600080fd5b8035906020019184600183028401116401000000008311171561069157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112dd945050505050565b60408051600160e060020a03199092168252519081900360200190f35b3480156106fb57600080fd5b50610519611307565b34801561071057600080fd5b506105026004803603602081101561072757600080fd5b503561130d565b34801561073a57600080fd5b506105026113b4565b6105026004803603606081101561075957600080fd5b50600160a060020a03813581169160208101359091169060400135611420565b34801561078557600080fd5b506105026004803603604081101561079c57600080fd5b508035906020013561164f565b3480156107b557600080fd5b5061051961170d565b3480156107ca57600080fd5b50610502611713565b3480156107df57600080fd5b50610502600480360360408110156107f657600080fd5b5080359060200135611795565b34801561080f57600080fd5b506103c8611853565b6105026004803603606081101561082e57600080fd5b50600160a060020a03813581169160208101359091169060400135611863565b34801561085a57600080fd5b506105196004803603602081101561087157600080fd5b5035600160a060020a0316611883565b34801561088d57600080fd5b50610502600480360360208110156108a457600080fd5b8101906020810181356401000000008111156108bf57600080fd5b8201836020820111156108d157600080fd5b803590602001918460018302840111640100000000831117156108f357600080fd5b50909250905061188e565b34801561090a57600080fd5b506104066004803603602081101561092157600080fd5b50356118ab565b34801561093457600080fd5b506103c86004803603602081101561094b57600080fd5b5035600160a060020a0316611936565b34801561096757600080fd5b506105196004803603602081101561097e57600080fd5b5035600160a060020a0316611956565b610502600480360360408110156109a457600080fd5b50600160a060020a03813581169160200135166119d7565b3480156109c857600080fd5b50610502611a7c565b3480156109dd57600080fd5b50610502600480360360208110156109f457600080fd5b5035611ae4565b348015610a0757600080fd5b50610519611bbb565b348015610a1c57600080fd5b5061050260048036036040811015610a3357600080fd5b810190602081018135640100000000811115610a4e57600080fd5b820183602082011115610a6057600080fd5b80359060200191846020830284011164010000000083111715610a8257600080fd5b919390929091602081019035640100000000811115610aa057600080fd5b820183602082011115610ab257600080fd5b80359060200191846020830284011164010000000083111715610ad457600080fd5b509092509050611bc1565b348015610aeb57600080fd5b50610406611c23565b348015610b0057600080fd5b506103c8611c32565b348015610b1557600080fd5b50610519611c43565b348015610b2a57600080fd5b50610519611c49565b348015610b3f57600080fd5b5061051960048036036020811015610b5657600080fd5b5035600160a060020a0316611c4f565b348015610b7257600080fd5b506103c860048036036040811015610b8957600080fd5b5080359060200135600160a060020a0316611ce1565b348015610bab57600080fd5b5061050260048036036040811015610bc257600080fd5b50600160a060020a038135169060200135611d02565b348015610be457600080fd5b50610406611d1d565b348015610bf957600080fd5b5061050260048036036020811015610c1057600080fd5b5035600160a060020a0316611d2c565b348015610c2c57600080fd5b5061050260048036036040811015610c4357600080fd5b50600160a060020a0381351690602001351515611de4565b348015610c6757600080fd5b50610502611f02565b348015610c7c57600080fd5b5061051960048036036020811015610c9357600080fd5b5035600160a060020a0316611faf565b61050260048036036080811015610cb957600080fd5b600160a060020a03823581169260208101359091169160408201359190810190608081016060820135640100000000811115610cf457600080fd5b820183602082011115610d0657600080fd5b80359060200191846001830284011164010000000083111715610d2857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612044945050505050565b348015610d7557600080fd5b506105026121db565b348015610d8a57600080fd5b5061050260048036036020811015610da157600080fd5b5035600160a060020a0316612284565b348015610dbd57600080fd5b50610519612380565b348015610dd257600080fd5b50610519612386565b348015610de757600080fd5b506103c860048036036040811015610dfe57600080fd5b50600160a060020a038135811691602001351661238c565b348015610e2257600080fd5b5061050260048036036020811015610e3957600080fd5b5035600160a060020a03166123ba565b61050260048036036020811015610e5f57600080fd5b5035600160a060020a03166123d4565b348015610e7b57600080fd5b5061050260048036036040811015610e9257600080fd5b810190602081018135640100000000811115610ead57600080fd5b820183602082011115610ebf57600080fd5b80359060200191846020830284011164010000000083111715610ee157600080fd5b91935091503561242e565b600160e060020a0319811660009081526020819052604090205460ff165b919050565b60708181548110610f1c57fe5b600091825260209091200154600160a060020a0316905081565b60738054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fc25780601f10610f9757610100808354040283529160200191610fc2565b820191906000526020600020905b815481529060010190602001808311610fa557829003601f168201915b505050505090505b90565b6000610fd88261247d565b92915050565b60675460a060020a900460ff1661102d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b806110388133611ce1565b80611048575061104881336124ea565b80611060575061106061105a826118ab565b3361238c565b6110b4576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b33600160a060020a0384161415611115576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b6000828152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385169081179091558290611157826118ab565b600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60755481565b60745481565b606854600160a060020a031681565b607054606090611206576040805160e560020a62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b60705482908482029060009082840111156112295750607054818103925061122e565b508082015b60608360405190808252806020026020018201604052801561125a578160200160208202803883390190505b5090506000835b838110156112c4576070818154811061127657fe5b9060005260206000200160009054906101000a9004600160a060020a03168383815181106112a057fe5b600160a060020a039092166020928302919091019091015260019182019101611261565b5090979650505050505050565b606a5481565b60695481565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b606c5490565b611315611c32565b61131e57600080fd5b60675460a060020a900460ff1661136d576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113bf3361250b565b905060006113cc33612525565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a3426001830155801561141c5761141c3382612605565b5050565b60675460a060020a900460ff1661146f576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8261147981611936565b6114bb576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b816114c68133611ce1565b806114d657506114d681336124ea565b806114e857506114e861105a826118ab565b61153c576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b600160a060020a038416611588576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b60006115938661250b565b905060006115a08661250b565b60018101548154919250906115b457825482555b6115c287836000015461283b565b4281116115d857600180840154908301556115f5565b60018301546115ef9042830363ffffffff6128cf16565b60018301555b426001840155611604866128e8565b8587600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611657611c32565b61166057600080fd5b806116b5576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607491909155607555565b606c5481565b61171b611c32565b61172457600080fd5b600061172f30612930565b905060008111611789576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792816129d7565b50565b61179d611c32565b6117a657600080fd5b806117fb576040805160e560020a62461bcd02815260206004820152600c60248201527f494e56414c49445f524154450000000000000000000000000000000000000000604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b60675460a060020a900460ff1681565b61187e83838360405180602001604052806000815250612044565b505050565b6000610fd882612525565b611896611c32565b61189f57600080fd5b61187e607383836132d2565b6000818152606f60205260408120548290600160a060020a0316611919576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b50506000908152606f6020526040902054600160a060020a031690565b600160a060020a03166000908152606e6020526040902060010154421090565b6000600160a060020a0382166119a4576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e60205260409020600101546119cb5760006119ce565b60015b60ff1692915050565b60675460a060020a900460ff16611a26576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b80611a3081611936565b611a72576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b61187e8383612a21565b611a84611c32565b611a8d57600080fd5b603454604051600091600160a060020a0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36034805473ffffffffffffffffffffffffffffffffffffffff19169055565b611aec611c32565b611af557600080fd5b60008111611b4d576040805160e560020a62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5830612930565b905081811015611bb2576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b61141c826129d7565b606b5481565b611bc9611c32565b611bd257600080fd5b60005b83811015611c1c57611c14858583818110611bec57fe5b90506020020135600160a060020a0316848484818110611c0857fe5b90506020020135612d43565b600101611bd5565b5050505050565b603454600160a060020a031690565b603454600160a060020a0316331490565b60765481565b60705490565b600160a060020a0381166000908152606e602052604081206001810154839190611cc3576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090205490565b6000918252606f602052604090912054600160a060020a0391821691161490565b611d0a611c32565b611d1357600080fd5b61141c8282612d43565b606754600160a060020a031681565b611d34611c32565b611d3d57600080fd5b80611d4781611936565b611d89576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600160a060020a0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b60675460a060020a900460ff16611e33576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b600160a060020a038216331415611e94576040805160e560020a62461bcd02815260206004820152600c60248201527f415050524f56455f53454c460000000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152607260209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611f0a611c32565b611f1357600080fd5b60675460a060020a900460ff1615611f75576040805160e560020a62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b600160a060020a0381166000908152606e602052604081206001810154839190612023576040805160e560020a62461bcd02815260206004820152600b60248201527f4e4f5f535543485f4b4559000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050600160a060020a03166000908152606e602052604090206001015490565b60675460a060020a900460ff16612093576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b8161209e8133611ce1565b806120ae57506120ae81336124ea565b806120c057506120c061105a826118ab565b612114576040805160e560020a62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b61211d836118ab565b61212681611936565b612168576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b612173868686611420565b61217f86868686612e52565b6121d3576040805160e560020a62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b6121e3611c32565b6121ec57600080fd5b60675460a060020a900460ff1661223b576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061229d575061229d612fb7565b806122ab575060015460ff16155b6122e95760405160e560020a62461bcd02815260040180806020018281038252602e81526020018061338b602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff191683179092556034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606d5481565b60775481565b600160a060020a03918216600090815260726020908152604080832093909416825291909152205460ff1690565b6123c2611c32565b6123cb57600080fd5b61179281612fbd565b60675460a060020a900460ff16612423576040805160e560020a62461bcd02815260206004820152600f602482015260008051602061336b833981519152604482015290519081900360640190fd5b611792816000612a21565b612436611c32565b61243f57600080fd5b60005b828110156124775761246f84848381811061245957fe5b90506020020135600160a060020a031683612d43565b600101612442565b50505050565b600081815260716020526040812054600160a060020a031680610fd8576040805160e560020a62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b60009182526071602052604090912054600160a060020a0391821691161490565b600160a060020a03166000908152606e6020526040902090565b60008161253181611936565b612573576040805160e560020a62461bcd02815260206004820152600d60248201526000805160206133b9833981519152604482015290519081900360640190fd5b600061257e8461250b565b90506000428260010154039050606954811061259e57606a5493506125bf565b606954606a546125b4908363ffffffff61303916565b816125bb57fe5b0493505b60006075546125db607454606a5461303990919063ffffffff16565b816125e257fe5b049050808511156125f75780850394506125fc565b600094505b50505050919050565b606754600160a060020a031661265157604051600160a060020a0383169082156108fc029083906000818181858888f1935050505015801561264b573d6000803e3d6000fd5b5061141c565b6067546040805160e060020a6370a08231028152600160a060020a0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b1580156126a657600080fd5b505afa1580156126ba573d6000803e3d6000fd5b505050506040513d60208110156126d057600080fd5b5051604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b15801561274157600080fd5b505af1158015612755573d6000803e3d6000fd5b505050506040513d602081101561276b57600080fd5b50506040805160e060020a6370a08231028152600160a060020a038681166004830152915183928516916370a08231916024808301926020929190829003018186803b1580156127ba57600080fd5b505afa1580156127ce573d6000803e3d6000fd5b505050506040513d60208110156127e457600080fd5b505111612477576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b6000818152606f6020526040902054600160a060020a0383811691161461141c5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b018054600160a060020a03841673ffffffffffffffffffffffffffffffffffffffff1991821681179092556000838152606f60205260409020805490911690911790555050565b6000828201838110156128e157600080fd5b9392505050565b600081815260716020526040902054600160a060020a031615611792576000908152607160205260409020805473ffffffffffffffffffffffffffffffffffffffff19169055565b606754600090600160a060020a03166129545750600160a060020a03811631610f0a565b6067546040805160e060020a6370a08231028152600160a060020a038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156129a457600080fd5b505afa1580156129b8573d6000803e3d6000fd5b505050506040513d60208110156129ce57600080fd5b50519050610f0a565b6129e86129e2611c23565b82612605565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606c54606b5411612a7c576040805160e560020a62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216612ac8576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b606a54606854604080517f0cb175e3000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612b3a57600080fd5b505afa158015612b4e573d6000803e3d6000fd5b505050506040513d6040811015612b6457600080fd5b50805160209091015190935091508080841115612b8357506000612b88565b508281035b612b9181613060565b6000612b9c8761250b565b600181015490915042811015612bd257612bb5826132b7565b612bc388836000015461283b565b60695442016001830155612bec565b606954612be690829063ffffffff6128cf16565b60018301555b8515612c7857606854604080517f3652466300000000000000000000000000000000000000000000000000000000815260048101899052602481018890529051600160a060020a039092169163365246639160448082019260009290919082900301818387803b158015612c5f57600080fd5b505af1158015612c73573d6000803e3d6000fd5b505050505b606854604080517f939d9f1f00000000000000000000000000000000000000000000000000000000815260048101869052600160a060020a038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612ce657600080fd5b505af1158015612cfa573d6000803e3d6000fd5b5050606c54604051909250600160a060020a038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b600160a060020a038216612d8f576040805160e560020a62461bcd02815260206004820152600f60248201526000805160206133d9833981519152604482015290519081900360640190fd5b6000612d9a8361250b565b905080600101548211612df7576040805160e560020a62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b612e00816132b7565b612e0e83826000015461283b565b600181018290558054604051600160a060020a038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000612e6684600160a060020a03166132cc565b612e72575060016112ff565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201818152600160a060020a03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015612f05578181015183820152602001612eed565b50505050905090810190601f168015612f325780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015612f5457600080fd5b505af1158015612f68573d6000803e3d6000fd5b505050506040513d6020811015612f7e57600080fd5b5051600160e060020a0319167f150b7a020000000000000000000000000000000000000000000000000000000014915050949350505050565b303b1590565b600160a060020a038116612fd057600080fd5b603454604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36034805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008261304857506000610fd8565b8282028284828161305557fe5b04146128e157600080fd5b606754600160a060020a03166130cd57803410156130c8576040805160e560020a62461bcd02815260206004820152601060248201527f4e4f545f454e4f5547485f46554e445300000000000000000000000000000000604482015290519081900360640190fd5b611792565b6067546040805160e060020a6370a082310281523060048201529051600160a060020a039092169160009183916370a0823191602480820192602092909190829003018186803b15801561312057600080fd5b505afa158015613134573d6000803e3d6000fd5b505050506040513d602081101561314a57600080fd5b5051604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690529051919250600160a060020a038416916323b872dd916064808201926020929091908290030181600087803b1580156131be57600080fd5b505af11580156131d2573d6000803e3d6000fd5b505050506040513d60208110156131e857600080fd5b50506040805160e060020a6370a0823102815230600482015290518291600160a060020a038516916370a0823191602480820192602092909190829003018186803b15801561323657600080fd5b505afa15801561324a573d6000803e3d6000fd5b505050506040513d602081101561326057600080fd5b50511161187e576040805160e560020a62461bcd02815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015290519081900360640190fd5b805461179257606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106133135782800160ff19823516178555613340565b82800160010185558215613340579182015b82811115613340578235825591602001919060010190613325565b5061334c929150613350565b5090565b610fca91905b8082111561334c576000815560010161335656fe4c4f434b5f444550524543415445440000000000000000000000000000000000436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65644b45595f4e4f545f56414c494400000000000000000000000000000000000000494e56414c49445f414444524553530000000000000000000000000000000000a165627a7a72305820307d7415f1879a4c56340443cd73d8bea62267dd331ec6d62442029fc4f258790029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a723058203e7ea4127724044a183879e7ab1ae9026261e202e8b32d7e782c980e83ede77e0029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.6", - "updatedAt": "2019-04-04T15:05:08.514Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV2.json b/packages/contracts/src/abis/Unlock/UnlockV2.json deleted file mode 100644 index ccbbfb926a1..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV2.json +++ /dev/null @@ -1,280 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "name": "deployed", - "type": "bool" - }, - { - "name": "totalSales", - "type": "uint256" - }, - { - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "name": "createLock", - "outputs": [ - { - "name": "lock", - "type": "address" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_purchaser", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "name": "discount", - "type": "uint256" - }, - { - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_discount", - "type": "uint256" - }, - { - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50614092806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000e25760003560e01c80638f32d59b1162000099578063b8199af2116200006f578063b8199af21462000295578063c4d66de814620002d0578063d6e9e80314620002f9578063f2fde38b146200030357620000e2565b80638f32d59b146200022c578063939d9f1f146200024a578063a082eb0e146200027957620000e2565b80630cb175e3146200012357806336524663146200016b5780634220bd4614620001935780635de9a13714620001b3578063715018a614620001fc5780638da5cb5b1462000206575b60408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b62000152600480360360408110156200013b57600080fd5b506001600160a01b0381351690602001356200032c565b6040805192835260208301919091528051918290030190f35b62000191600480360360408110156200018357600080fd5b508035906020013562000335565b005b6200019d62000399565b6040805160ff9092168252519081900360200190f35b620001dc60048036036020811015620001cb57600080fd5b50356001600160a01b03166200039e565b604080519315158452602084019290925282820152519081900360600190f35b62000191620003c3565b6200021062000421565b604080516001600160a01b039092168252519081900360200190f35b6200023662000430565b604080519115158252519081900360200190f35b62000191600480360360408110156200026257600080fd5b50803590602001356001600160a01b031662000441565b62000283620004bd565b60408051918252519081900360200190f35b6200021060048036036080811015620002ad57600080fd5b508035906001600160a01b036020820135169060408101359060600135620004c3565b6200019160048036036020811015620002e857600080fd5b50356001600160a01b0316620005b4565b6200028362000665565b62000191600480360360208110156200031b57600080fd5b50356001600160a01b03166200066b565b50600091829150565b3360009081526068602052604090205460ff166200038d5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b60678054830190555050565b600290565b60686020526000908152604090208054600182015460029092015460ff909116919083565b620003cd62000430565b620003d757600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff16620004995760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b6000803386868686604051620004d990620007f9565b6001600160a01b0395861681526020810194909452919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000528573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b600054610100900460ff1680620005d05750620005d06200068d565b80620005df575060005460ff16155b6200061f57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062004039602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff166200064a8262000693565b600080549115156101000261ff001990921691909117905550565b60665481565b6200067562000430565b6200067f57600080fd5b6200068a8162000789565b50565b303b1590565b600054610100900460ff1680620006af5750620006af6200068d565b80620006be575060005460ff16155b620006fe57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062004039602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091178355603380546001600160a01b0319166001600160a01b0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b6001600160a01b0381166200079d57600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b61383180620008088339019056fe6080604052600060745560646075556001607655600a6077553480156200002557600080fd5b5060405160a08062003831833981018060405260a08110156200004757600080fd5b508051602080830151604084015160608501516080909501519394919390928490839083906001908790620000a2907f01ffc9a70000000000000000000000000000000000000000000000000000000090620002cb811b901c565b6001600160a01b03811615806200012057506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015620000f057600080fd5b505afa15801562000105573d6000803e3d6000fd5b505050506040513d60208110156200011c57600080fd5b5051115b6200018c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60688054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200024257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606980546001600160a01b03191633179055606a93909355606b91909155606c55606e805460ff90921660ff19909216919091179055620002aa7f80ac58cd00000000000000000000000000000000000000000000000000000000620002cb602090811b901c565b620002c0856200033860201b620023341760201c565b505050505062000450565b7fffffffff000000000000000000000000000000000000000000000000000000008082161415620002fb57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200035a57506200035a6200044a60201b60201c565b8062000369575060015460ff16155b620003c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003803602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b6133a380620004606000396000f3fe6080604052600436106103355760003560e01c806370efb770116101ab5780639d76ea58116100f7578063c4d66de811610095578063e985e9c51161006f578063e985e9c514610e09578063f2fde38b14610e44578063f6e4641f14610e77578063f8faf94214610e9d57610335565b8063c4d66de814610d96578063d1bbd49c14610dc9578063d42cfc4114610df457610335565b8063a843a4e7116100d1578063a843a4e714610c75578063abdf82ce14610c8a578063b88d4fde14610cbd578063c1c98d0314610d8157610335565b80639d76ea5814610bf25780639f98d3cb14610c07578063a22cb46514610c3a57610335565b80638da5cb5b1161016457806393fd18441161013e57806393fd184414610b38578063970aaeb714610b4d578063994a8a7114610b805780639b3f0b1714610bb957610335565b80638da5cb5b14610af95780638f32d59b14610b0e5780638f98ce8f14610b2357610335565b806370efb77014610979578063715018a6146109a757806371d2ee6c146109bc57806374b6c106146109e65780637c7c4253146109fb57806383cb0fa914610ac657610335565b80631f1ec029116102855780634136aa3511610223578063550ef3a8116101fd578063550ef3a81461086e5780636352211e146108e95780636d8ea5b41461091357806370a082311461094657610335565b80634136aa35146107f057806342842e0e1461080557806352d6a8e41461083b57610335565b806339f469861161025f57806339f46986146107665780633ba70e31146107965780633ccfd60b146107ab5780633d3359cb146107c057610335565b80631f1ec029146106f15780632009dc651461071b57806323b872dd1461073057610335565b80630ed3e2cc116102f257806310e56973116102cc57806310e56973146105c457806311a4c03a146105d9578063150b7a02146105ee57806318160ddd146106dc57610335565b80630ed3e2cc1461051a5780630f15023b1461052f57806310803b721461054457610335565b806301ffc9a714610383578063025e7c27146103cb57806306fdde0314610411578063081812fc1461049b578063095ea7b3146104c55780630c79130f146104f3575b34801561034157600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561038f57600080fd5b506103b7600480360360208110156103a657600080fd5b50356001600160e01b031916610f18565b604080519115158252519081900360200190f35b3480156103d757600080fd5b506103f5600480360360208110156103ee57600080fd5b5035610f3b565b604080516001600160a01b039092168252519081900360200190f35b34801561041d57600080fd5b50610426610f62565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610460578181015183820152602001610448565b50505050905090810190601f16801561048d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104a757600080fd5b506103f5600480360360208110156104be57600080fd5b5035610ff9565b6104f1600480360360408110156104db57600080fd5b506001600160a01b03813516906020013561100a565b005b3480156104ff57600080fd5b506105086111a9565b60408051918252519081900360200190f35b34801561052657600080fd5b506105086111af565b34801561053b57600080fd5b506103f56111b5565b34801561055057600080fd5b506105746004803603604081101561056757600080fd5b50803590602001356111c4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105b0578181015183820152602001610598565b505050509050019250505060405180910390f35b3480156105d057600080fd5b506105086112e9565b3480156105e557600080fd5b506105086112ef565b3480156105fa57600080fd5b506106bf6004803603608081101561061157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561064b57600080fd5b82018360208201111561065d57600080fd5b803590602001918460018302840111600160201b8311171561067e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112f5945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156106e857600080fd5b50610508611309565b3480156106fd57600080fd5b506104f16004803603602081101561071457600080fd5b503561130f565b34801561072757600080fd5b506104f16113bd565b6104f16004803603606081101561074657600080fd5b506001600160a01b03813581169160208101359091169060400135611429565b34801561077257600080fd5b506104f16004803603604081101561078957600080fd5b508035906020013561167c565b3480156107a257600080fd5b5061050861172c565b3480156107b757600080fd5b506104f1611732565b3480156107cc57600080fd5b506104f1600480360360408110156107e357600080fd5b50803590602001356117aa565b3480156107fc57600080fd5b506103b761185a565b6104f16004803603606081101561081b57600080fd5b506001600160a01b0381358116916020810135909116906040013561186a565b34801561084757600080fd5b506105086004803603602081101561085e57600080fd5b50356001600160a01b031661188a565b34801561087a57600080fd5b506104f16004803603602081101561089157600080fd5b810190602081018135600160201b8111156108ab57600080fd5b8201836020820111156108bd57600080fd5b803590602001918460018302840111600160201b831117156108de57600080fd5b509092509050611895565b3480156108f557600080fd5b506103f56004803603602081101561090c57600080fd5b50356118b2565b34801561091f57600080fd5b506103b76004803603602081101561093657600080fd5b50356001600160a01b031661192e565b34801561095257600080fd5b506105086004803603602081101561096957600080fd5b50356001600160a01b031661194e565b6104f16004803603604081101561098f57600080fd5b506001600160a01b03813581169160200135166119d6565b3480156109b357600080fd5b506104f1611a87565b3480156109c857600080fd5b506104f1600480360360208110156109df57600080fd5b5035611ae2565b3480156109f257600080fd5b50610508611baf565b348015610a0757600080fd5b506104f160048036036040811015610a1e57600080fd5b810190602081018135600160201b811115610a3857600080fd5b820183602082011115610a4a57600080fd5b803590602001918460208302840111600160201b83111715610a6b57600080fd5b919390929091602081019035600160201b811115610a8857600080fd5b820183602082011115610a9a57600080fd5b803590602001918460208302840111600160201b83111715610abb57600080fd5b509092509050611bb5565b348015610ad257600080fd5b5061050860048036036020811015610ae957600080fd5b50356001600160a01b0316611c17565b348015610b0557600080fd5b506103f5611ce0565b348015610b1a57600080fd5b506103b7611cef565b348015610b2f57600080fd5b50610508611d00565b348015610b4457600080fd5b50610508611d06565b348015610b5957600080fd5b5061050860048036036020811015610b7057600080fd5b50356001600160a01b0316611d0c565b348015610b8c57600080fd5b506103b760048036036040811015610ba357600080fd5b50803590602001356001600160a01b0316611d8f565b348015610bc557600080fd5b506104f160048036036040811015610bdc57600080fd5b506001600160a01b038135169060200135611db0565b348015610bfe57600080fd5b506103f5611dcb565b348015610c1357600080fd5b506104f160048036036020811015610c2a57600080fd5b50356001600160a01b0316611dda565b348015610c4657600080fd5b506104f160048036036040811015610c5d57600080fd5b506001600160a01b0381351690602001351515611e97565b348015610c8157600080fd5b506104f1611fae565b348015610c9657600080fd5b5061050860048036036020811015610cad57600080fd5b50356001600160a01b031661205b565b6104f160048036036080811015610cd357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610d0d57600080fd5b820183602082011115610d1f57600080fd5b803590602001918460018302840111600160201b83111715610d4057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506120e1945050505050565b348015610d8d57600080fd5b506104f1612284565b348015610da257600080fd5b506104f160048036036020811015610db957600080fd5b50356001600160a01b0316612334565b348015610dd557600080fd5b50610dde612423565b6040805160ff9092168252519081900360200190f35b348015610e0057600080fd5b5061050861242c565b348015610e1557600080fd5b506103b760048036036040811015610e2c57600080fd5b506001600160a01b0381358116916020013516612432565b348015610e5057600080fd5b506104f160048036036020811015610e6757600080fd5b50356001600160a01b0316612460565b6104f160048036036020811015610e8d57600080fd5b50356001600160a01b031661247a565b348015610ea957600080fd5b506104f160048036036040811015610ec057600080fd5b810190602081018135600160201b811115610eda57600080fd5b820183602082011115610eec57600080fd5b803590602001918460208302840111600160201b83111715610f0d57600080fd5b9193509150356124db565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60718181548110610f4857fe5b6000918252602090912001546001600160a01b0316905081565b60678054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fee5780601f10610fc357610100808354040283529160200191610fee565b820191906000526020600020905b815481529060010190602001808311610fd157829003601f168201915b505050505090505b90565b60006110048261252a565b92915050565b606854600160a01b900460ff166110605760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b8061106b8133611d8f565b8061107b575061107b8133612597565b80611093575061109361108d826118b2565b33612432565b6110e75760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b038416141561113a5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260726020526040902080546001600160a01b0319166001600160a01b038516908117909155829061116f826118b2565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60775481565b60765481565b6069546001600160a01b031681565b60715460609061121e5760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b607154829084820290600090828401111561124157506071548181039250611246565b508082015b606083604051908082528060200260200182016040528015611272578160200160208202803883390190505b5090506000835b838110156112dc576071818154811061128e57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106112b857fe5b6001600160a01b039092166020928302919091019091015260019182019101611279565b5090979650505050505050565b606b5481565b606a5481565b600160e11b630a85bd01025b949350505050565b606d5490565b611317611cef565b61132057600080fd5b606854600160a01b900460ff166113765760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113c8336125b8565b905060006113d5336125d2565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a342600183015580156114255761142533826126b7565b5050565b606854600160a01b900460ff1661147f5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826114898161192e565b6114d05760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816114db8133611d8f565b806114eb57506114eb8133612597565b806114fd57506114fd61108d826118b2565b6115515760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b0384166115a45760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6115b56115b086611c17565b6128cc565b60006115c0866125b8565b905060006115cd866125b8565b60018101548154919250906115e157825482555b6115ef878360000154612af8565b4281116116055760018084015490830155611622565b600183015461161c9042830363ffffffff612b7f16565b60018301555b42600184015561163186612b98565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611684611cef565b61168d57600080fd5b806116d45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607691909155607755565b606d5481565b61173a611cef565b61174357600080fd5b600061174e30612bd3565b90506000811161179e5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a781612c7a565b50565b6117b2611cef565b6117bb57600080fd5b806118025760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607491909155607555565b606854600160a01b900460ff1681565b611885838383604051806020016040528060008152506120e1565b505050565b6000611004826125d2565b61189d611cef565b6118a657600080fd5b611885606783836132b1565b60008181526070602052604081205482906001600160a01b03166119115760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152607060205260409020546001600160a01b031690565b6001600160a01b03166000908152606f6020526040902060010154421090565b60006001600160a01b0382166119a35760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6001600160a01b0382166000908152606f60205260409020600101546119ca5760006119cd565b60015b60ff1692915050565b606854600160a01b900460ff16611a2c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b80611a368161192e565b611a7d5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6118858383612cc4565b611a8f611cef565b611a9857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b611aea611cef565b611af357600080fd5b60008111611b4b5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5630612bd3565b905081811015611ba65760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61142582612c7a565b606c5481565b611bbd611cef565b611bc657600080fd5b60005b83811015611c1057611c08858583818110611be057fe5b905060200201356001600160a01b0316848484818110611bfc57fe5b90506020020135612fab565b600101611bc9565b5050505050565b600081611c238161192e565b611c6a5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000611c75846125b8565b905060004282600101540390506000606a548210611c965750606b54611cb7565b606a54606b54611cac908463ffffffff6130c116565b81611cb357fe5b0490505b607554607454611cce90839063ffffffff6130c116565b81611cd557fe5b049695505050505050565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60745481565b60715490565b6001600160a01b0381166000908152606f602052604081206001810154839190611d715760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090205490565b600091825260706020526040909120546001600160a01b0391821691161490565b611db8611cef565b611dc157600080fd5b6114258282612fab565b6068546001600160a01b031681565b611de2611cef565b611deb57600080fd5b80611df58161192e565b611e3c5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606f602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606854600160a01b900460ff16611eed5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415611f405760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526073602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611fb6611cef565b611fbf57600080fd5b606854600160a01b900460ff16156120215760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b6001600160a01b0381166000908152606f6020526040812060018101548391906120c05760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090206001015490565b606854600160a01b900460ff166121375760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b816121428133611d8f565b8061215257506121528133612597565b80612164575061216461108d826118b2565b6121b85760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6121c1836118b2565b6121ca8161192e565b6122115760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b61221c868686611429565b612228868686866130e8565b61227c5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b61228c611cef565b61229557600080fd5b606854600160a01b900460ff166122eb5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16068805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061234d575061234d613221565b8061235b575060015460ff16155b61239957604051600160e51b62461bcd02815260040180806020018281038252602e81526020018061334a602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606e5460ff1681565b60755481565b6001600160a01b03918216600090815260736020908152604080832093909416825291909152205460ff1690565b612468611cef565b61247157600080fd5b6117a781613227565b606854600160a01b900460ff166124d05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6117a7816000612cc4565b6124e3611cef565b6124ec57600080fd5b60005b828110156125245761251c84848381811061250657fe5b905060200201356001600160a01b031683612fab565b6001016124ef565b50505050565b6000818152607260205260408120546001600160a01b0316806110045760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260726020526040909120546001600160a01b0391821691161490565b6001600160a01b03166000908152606f6020526040902090565b6000816125de8161192e565b6126255760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000612630846125b8565b90506000428260010154039050606a54811061265057606b549350612671565b606a54606b54612666908363ffffffff6130c116565b8161266d57fe5b0493505b600060775461268d607654606b546130c190919063ffffffff16565b8161269457fe5b049050808511156126a95780850394506126ae565b600094505b50505050919050565b6068546001600160a01b0316612703576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156126fd573d6000803e3d6000fd5b50611425565b60685460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b15801561275857600080fd5b505afa15801561276c573d6000803e3d6000fd5b505050506040513d602081101561278257600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d602081101561280757600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b15801561285657600080fd5b505afa15801561286a573d6000803e3d6000fd5b505050506040513d602081101561288057600080fd5b5051116125245760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6068546001600160a01b031661292f578034101561292a5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a7565b60685460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b158015612a0a57600080fd5b505af1158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015612a8257600080fd5b505afa158015612a96573d6000803e3d6000fd5b505050506040513d6020811015612aac57600080fd5b5051116118855760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6000818152607060205260409020546001600160a01b038381169116146114255760718054600181019091557fa1fcd19bfe8c32a61095b6bfbb2664842857e148fcbb5188386c8cd40348d5b60180546001600160a01b0384166001600160a01b031991821681179092556000838152607060205260409020805490911690911790555050565b600082820183811015612b9157600080fd5b9392505050565b6000818152607260205260409020546001600160a01b0316156117a757600090815260726020526040902080546001600160a01b0319169055565b6068546000906001600160a01b0316612bf757506001600160a01b03811631610f36565b60685460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d6020811015612c7157600080fd5b50519050610f36565b612c8b612c85611ce0565b826126b7565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606d54606c5411612d1f5760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216612d725760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606b5460695460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d6040811015612df857600080fd5b50805160209091015190935091508080841115612e1757506000612e1c565b508281035b612e25816128cc565b6000612e30876125b8565b600181015490915042811015612e6657612e4982613296565b612e57888360000154612af8565b606a5442016001830155612e80565b606a54612e7a90829063ffffffff612b7f16565b60018301555b8515612ef65760695460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015612edd57600080fd5b505af1158015612ef1573d6000803e3d6000fd5b505050505b60695460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612f4e57600080fd5b505af1158015612f62573d6000803e3d6000fd5b5050606d546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216612ffe5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613009836125b8565b9050806001015482116130665760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b61306f81613296565b61307d838260000154612af8565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000826130d057506000611004565b828202828482816130dd57fe5b0414612b9157600080fd5b60006130fc846001600160a01b03166132ab565b61310857506001611301565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b8381101561318557818101518382015260200161316d565b50505050905090810190601f1680156131b25780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156131d457600080fd5b505af11580156131e8573d6000803e3d6000fd5b505050506040513d60208110156131fe57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b303b1590565b6001600160a01b03811661323a57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546117a757606d8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132f25782800160ff1982351617855561331f565b8280016001018555821561331f579182015b8281111561331f578235825591602001919060010190613304565b5061332b92915061332f565b5090565b610ff691905b8082111561332b576000815560010161333556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582090e2645e8f5c8a27b9aa3e516ad14db63bd34f8938f3f859e51115419dc428460029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a723058209f8266073118c2fedd1d71f9f463a1f49f5dbf726c75cc7b47dc56f379d4c8610029", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000e25760003560e01c80638f32d59b1162000099578063b8199af2116200006f578063b8199af21462000295578063c4d66de814620002d0578063d6e9e80314620002f9578063f2fde38b146200030357620000e2565b80638f32d59b146200022c578063939d9f1f146200024a578063a082eb0e146200027957620000e2565b80630cb175e3146200012357806336524663146200016b5780634220bd4614620001935780635de9a13714620001b3578063715018a614620001fc5780638da5cb5b1462000206575b60408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b62000152600480360360408110156200013b57600080fd5b506001600160a01b0381351690602001356200032c565b6040805192835260208301919091528051918290030190f35b62000191600480360360408110156200018357600080fd5b508035906020013562000335565b005b6200019d62000399565b6040805160ff9092168252519081900360200190f35b620001dc60048036036020811015620001cb57600080fd5b50356001600160a01b03166200039e565b604080519315158452602084019290925282820152519081900360600190f35b62000191620003c3565b6200021062000421565b604080516001600160a01b039092168252519081900360200190f35b6200023662000430565b604080519115158252519081900360200190f35b62000191600480360360408110156200026257600080fd5b50803590602001356001600160a01b031662000441565b62000283620004bd565b60408051918252519081900360200190f35b6200021060048036036080811015620002ad57600080fd5b508035906001600160a01b036020820135169060408101359060600135620004c3565b6200019160048036036020811015620002e857600080fd5b50356001600160a01b0316620005b4565b6200028362000665565b62000191600480360360208110156200031b57600080fd5b50356001600160a01b03166200066b565b50600091829150565b3360009081526068602052604090205460ff166200038d5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b60678054830190555050565b600290565b60686020526000908152604090208054600182015460029092015460ff909116919083565b620003cd62000430565b620003d757600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff16620004995760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b6000803386868686604051620004d990620007f9565b6001600160a01b0395861681526020810194909452919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000528573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b600054610100900460ff1680620005d05750620005d06200068d565b80620005df575060005460ff16155b6200061f57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062004039602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff166200064a8262000693565b600080549115156101000261ff001990921691909117905550565b60665481565b6200067562000430565b6200067f57600080fd5b6200068a8162000789565b50565b303b1590565b600054610100900460ff1680620006af5750620006af6200068d565b80620006be575060005460ff16155b620006fe57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062004039602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091178355603380546001600160a01b0319166001600160a01b0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b6001600160a01b0381166200079d57600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b61383180620008088339019056fe6080604052600060745560646075556001607655600a6077553480156200002557600080fd5b5060405160a08062003831833981018060405260a08110156200004757600080fd5b508051602080830151604084015160608501516080909501519394919390928490839083906001908790620000a2907f01ffc9a70000000000000000000000000000000000000000000000000000000090620002cb811b901c565b6001600160a01b03811615806200012057506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015620000f057600080fd5b505afa15801562000105573d6000803e3d6000fd5b505050506040513d60208110156200011c57600080fd5b5051115b6200018c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60688054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008411156200024257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606980546001600160a01b03191633179055606a93909355606b91909155606c55606e805460ff90921660ff19909216919091179055620002aa7f80ac58cd00000000000000000000000000000000000000000000000000000000620002cb602090811b901c565b620002c0856200033860201b620023341760201c565b505050505062000450565b7fffffffff000000000000000000000000000000000000000000000000000000008082161415620002fb57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff16806200035a57506200035a6200044a60201b60201c565b8062000369575060015460ff16155b620003c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062003803602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b1590565b6133a380620004606000396000f3fe6080604052600436106103355760003560e01c806370efb770116101ab5780639d76ea58116100f7578063c4d66de811610095578063e985e9c51161006f578063e985e9c514610e09578063f2fde38b14610e44578063f6e4641f14610e77578063f8faf94214610e9d57610335565b8063c4d66de814610d96578063d1bbd49c14610dc9578063d42cfc4114610df457610335565b8063a843a4e7116100d1578063a843a4e714610c75578063abdf82ce14610c8a578063b88d4fde14610cbd578063c1c98d0314610d8157610335565b80639d76ea5814610bf25780639f98d3cb14610c07578063a22cb46514610c3a57610335565b80638da5cb5b1161016457806393fd18441161013e57806393fd184414610b38578063970aaeb714610b4d578063994a8a7114610b805780639b3f0b1714610bb957610335565b80638da5cb5b14610af95780638f32d59b14610b0e5780638f98ce8f14610b2357610335565b806370efb77014610979578063715018a6146109a757806371d2ee6c146109bc57806374b6c106146109e65780637c7c4253146109fb57806383cb0fa914610ac657610335565b80631f1ec029116102855780634136aa3511610223578063550ef3a8116101fd578063550ef3a81461086e5780636352211e146108e95780636d8ea5b41461091357806370a082311461094657610335565b80634136aa35146107f057806342842e0e1461080557806352d6a8e41461083b57610335565b806339f469861161025f57806339f46986146107665780633ba70e31146107965780633ccfd60b146107ab5780633d3359cb146107c057610335565b80631f1ec029146106f15780632009dc651461071b57806323b872dd1461073057610335565b80630ed3e2cc116102f257806310e56973116102cc57806310e56973146105c457806311a4c03a146105d9578063150b7a02146105ee57806318160ddd146106dc57610335565b80630ed3e2cc1461051a5780630f15023b1461052f57806310803b721461054457610335565b806301ffc9a714610383578063025e7c27146103cb57806306fdde0314610411578063081812fc1461049b578063095ea7b3146104c55780630c79130f146104f3575b34801561034157600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561038f57600080fd5b506103b7600480360360208110156103a657600080fd5b50356001600160e01b031916610f18565b604080519115158252519081900360200190f35b3480156103d757600080fd5b506103f5600480360360208110156103ee57600080fd5b5035610f3b565b604080516001600160a01b039092168252519081900360200190f35b34801561041d57600080fd5b50610426610f62565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610460578181015183820152602001610448565b50505050905090810190601f16801561048d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104a757600080fd5b506103f5600480360360208110156104be57600080fd5b5035610ff9565b6104f1600480360360408110156104db57600080fd5b506001600160a01b03813516906020013561100a565b005b3480156104ff57600080fd5b506105086111a9565b60408051918252519081900360200190f35b34801561052657600080fd5b506105086111af565b34801561053b57600080fd5b506103f56111b5565b34801561055057600080fd5b506105746004803603604081101561056757600080fd5b50803590602001356111c4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105b0578181015183820152602001610598565b505050509050019250505060405180910390f35b3480156105d057600080fd5b506105086112e9565b3480156105e557600080fd5b506105086112ef565b3480156105fa57600080fd5b506106bf6004803603608081101561061157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561064b57600080fd5b82018360208201111561065d57600080fd5b803590602001918460018302840111600160201b8311171561067e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506112f5945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156106e857600080fd5b50610508611309565b3480156106fd57600080fd5b506104f16004803603602081101561071457600080fd5b503561130f565b34801561072757600080fd5b506104f16113bd565b6104f16004803603606081101561074657600080fd5b506001600160a01b03813581169160208101359091169060400135611429565b34801561077257600080fd5b506104f16004803603604081101561078957600080fd5b508035906020013561167c565b3480156107a257600080fd5b5061050861172c565b3480156107b757600080fd5b506104f1611732565b3480156107cc57600080fd5b506104f1600480360360408110156107e357600080fd5b50803590602001356117aa565b3480156107fc57600080fd5b506103b761185a565b6104f16004803603606081101561081b57600080fd5b506001600160a01b0381358116916020810135909116906040013561186a565b34801561084757600080fd5b506105086004803603602081101561085e57600080fd5b50356001600160a01b031661188a565b34801561087a57600080fd5b506104f16004803603602081101561089157600080fd5b810190602081018135600160201b8111156108ab57600080fd5b8201836020820111156108bd57600080fd5b803590602001918460018302840111600160201b831117156108de57600080fd5b509092509050611895565b3480156108f557600080fd5b506103f56004803603602081101561090c57600080fd5b50356118b2565b34801561091f57600080fd5b506103b76004803603602081101561093657600080fd5b50356001600160a01b031661192e565b34801561095257600080fd5b506105086004803603602081101561096957600080fd5b50356001600160a01b031661194e565b6104f16004803603604081101561098f57600080fd5b506001600160a01b03813581169160200135166119d6565b3480156109b357600080fd5b506104f1611a87565b3480156109c857600080fd5b506104f1600480360360208110156109df57600080fd5b5035611ae2565b3480156109f257600080fd5b50610508611baf565b348015610a0757600080fd5b506104f160048036036040811015610a1e57600080fd5b810190602081018135600160201b811115610a3857600080fd5b820183602082011115610a4a57600080fd5b803590602001918460208302840111600160201b83111715610a6b57600080fd5b919390929091602081019035600160201b811115610a8857600080fd5b820183602082011115610a9a57600080fd5b803590602001918460208302840111600160201b83111715610abb57600080fd5b509092509050611bb5565b348015610ad257600080fd5b5061050860048036036020811015610ae957600080fd5b50356001600160a01b0316611c17565b348015610b0557600080fd5b506103f5611ce0565b348015610b1a57600080fd5b506103b7611cef565b348015610b2f57600080fd5b50610508611d00565b348015610b4457600080fd5b50610508611d06565b348015610b5957600080fd5b5061050860048036036020811015610b7057600080fd5b50356001600160a01b0316611d0c565b348015610b8c57600080fd5b506103b760048036036040811015610ba357600080fd5b50803590602001356001600160a01b0316611d8f565b348015610bc557600080fd5b506104f160048036036040811015610bdc57600080fd5b506001600160a01b038135169060200135611db0565b348015610bfe57600080fd5b506103f5611dcb565b348015610c1357600080fd5b506104f160048036036020811015610c2a57600080fd5b50356001600160a01b0316611dda565b348015610c4657600080fd5b506104f160048036036040811015610c5d57600080fd5b506001600160a01b0381351690602001351515611e97565b348015610c8157600080fd5b506104f1611fae565b348015610c9657600080fd5b5061050860048036036020811015610cad57600080fd5b50356001600160a01b031661205b565b6104f160048036036080811015610cd357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610d0d57600080fd5b820183602082011115610d1f57600080fd5b803590602001918460018302840111600160201b83111715610d4057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506120e1945050505050565b348015610d8d57600080fd5b506104f1612284565b348015610da257600080fd5b506104f160048036036020811015610db957600080fd5b50356001600160a01b0316612334565b348015610dd557600080fd5b50610dde612423565b6040805160ff9092168252519081900360200190f35b348015610e0057600080fd5b5061050861242c565b348015610e1557600080fd5b506103b760048036036040811015610e2c57600080fd5b506001600160a01b0381358116916020013516612432565b348015610e5057600080fd5b506104f160048036036020811015610e6757600080fd5b50356001600160a01b0316612460565b6104f160048036036020811015610e8d57600080fd5b50356001600160a01b031661247a565b348015610ea957600080fd5b506104f160048036036040811015610ec057600080fd5b810190602081018135600160201b811115610eda57600080fd5b820183602082011115610eec57600080fd5b803590602001918460208302840111600160201b83111715610f0d57600080fd5b9193509150356124db565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60718181548110610f4857fe5b6000918252602090912001546001600160a01b0316905081565b60678054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610fee5780601f10610fc357610100808354040283529160200191610fee565b820191906000526020600020905b815481529060010190602001808311610fd157829003601f168201915b505050505090505b90565b60006110048261252a565b92915050565b606854600160a01b900460ff166110605760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b8061106b8133611d8f565b8061107b575061107b8133612597565b80611093575061109361108d826118b2565b33612432565b6110e75760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b038416141561113a5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260726020526040902080546001600160a01b0319166001600160a01b038516908117909155829061116f826118b2565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60775481565b60765481565b6069546001600160a01b031681565b60715460609061121e5760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b607154829084820290600090828401111561124157506071548181039250611246565b508082015b606083604051908082528060200260200182016040528015611272578160200160208202803883390190505b5090506000835b838110156112dc576071818154811061128e57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106112b857fe5b6001600160a01b039092166020928302919091019091015260019182019101611279565b5090979650505050505050565b606b5481565b606a5481565b600160e11b630a85bd01025b949350505050565b606d5490565b611317611cef565b61132057600080fd5b606854600160a01b900460ff166113765760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606b805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b60006113c8336125b8565b905060006113d5336125d2565b825460408051838152905192935033927f6f64cc1e7c0b20e2221d29714cd68b961e800f1ae03450a17c8bc0510e02bf729181900360200190a342600183015580156114255761142533826126b7565b5050565b606854600160a01b900460ff1661147f5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826114898161192e565b6114d05760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816114db8133611d8f565b806114eb57506114eb8133612597565b806114fd57506114fd61108d826118b2565b6115515760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b0384166115a45760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6115b56115b086611c17565b6128cc565b60006115c0866125b8565b905060006115cd866125b8565b60018101548154919250906115e157825482555b6115ef878360000154612af8565b4281116116055760018084015490830155611622565b600183015461161c9042830363ffffffff612b7f16565b60018301555b42600184015561163186612b98565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611684611cef565b61168d57600080fd5b806116d45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607691909155607755565b606d5481565b61173a611cef565b61174357600080fd5b600061174e30612bd3565b90506000811161179e5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a781612c7a565b50565b6117b2611cef565b6117bb57600080fd5b806118025760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60745460755460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607491909155607555565b606854600160a01b900460ff1681565b611885838383604051806020016040528060008152506120e1565b505050565b6000611004826125d2565b61189d611cef565b6118a657600080fd5b611885606783836132b1565b60008181526070602052604081205482906001600160a01b03166119115760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152607060205260409020546001600160a01b031690565b6001600160a01b03166000908152606f6020526040902060010154421090565b60006001600160a01b0382166119a35760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6001600160a01b0382166000908152606f60205260409020600101546119ca5760006119cd565b60015b60ff1692915050565b606854600160a01b900460ff16611a2c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b80611a368161192e565b611a7d5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6118858383612cc4565b611a8f611cef565b611a9857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b611aea611cef565b611af357600080fd5b60008111611b4b5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b6000611b5630612bd3565b905081811015611ba65760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61142582612c7a565b606c5481565b611bbd611cef565b611bc657600080fd5b60005b83811015611c1057611c08858583818110611be057fe5b905060200201356001600160a01b0316848484818110611bfc57fe5b90506020020135612fab565b600101611bc9565b5050505050565b600081611c238161192e565b611c6a5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000611c75846125b8565b905060004282600101540390506000606a548210611c965750606b54611cb7565b606a54606b54611cac908463ffffffff6130c116565b81611cb357fe5b0490505b607554607454611cce90839063ffffffff6130c116565b81611cd557fe5b049695505050505050565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60745481565b60715490565b6001600160a01b0381166000908152606f602052604081206001810154839190611d715760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090205490565b600091825260706020526040909120546001600160a01b0391821691161490565b611db8611cef565b611dc157600080fd5b6114258282612fab565b6068546001600160a01b031681565b611de2611cef565b611deb57600080fd5b80611df58161192e565b611e3c5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606f602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606854600160a01b900460ff16611eed5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415611f405760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526073602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b611fb6611cef565b611fbf57600080fd5b606854600160a01b900460ff16156120215760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a233ff5b6001600160a01b0381166000908152606f6020526040812060018101548391906120c05760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b5050506001600160a01b03166000908152606f602052604090206001015490565b606854600160a01b900460ff166121375760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b816121428133611d8f565b8061215257506121528133612597565b80612164575061216461108d826118b2565b6121b85760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6121c1836118b2565b6121ca8161192e565b6122115760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b61221c868686611429565b612228868686866130e8565b61227c5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b61228c611cef565b61229557600080fd5b606854600160a01b900460ff166122eb5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16068805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061234d575061234d613221565b8061235b575060015460ff16155b61239957604051600160e51b62461bcd02815260040180806020018281038252602e81526020018061334a602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b606e5460ff1681565b60755481565b6001600160a01b03918216600090815260736020908152604080832093909416825291909152205460ff1690565b612468611cef565b61247157600080fd5b6117a781613227565b606854600160a01b900460ff166124d05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6117a7816000612cc4565b6124e3611cef565b6124ec57600080fd5b60005b828110156125245761251c84848381811061250657fe5b905060200201356001600160a01b031683612fab565b6001016124ef565b50505050565b6000818152607260205260408120546001600160a01b0316806110045760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260726020526040909120546001600160a01b0391821691161490565b6001600160a01b03166000908152606f6020526040902090565b6000816125de8161192e565b6126255760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6000612630846125b8565b90506000428260010154039050606a54811061265057606b549350612671565b606a54606b54612666908363ffffffff6130c116565b8161266d57fe5b0493505b600060775461268d607654606b546130c190919063ffffffff16565b8161269457fe5b049050808511156126a95780850394506126ae565b600094505b50505050919050565b6068546001600160a01b0316612703576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156126fd573d6000803e3d6000fd5b50611425565b60685460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b15801561275857600080fd5b505afa15801561276c573d6000803e3d6000fd5b505050506040513d602081101561278257600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d602081101561280757600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b15801561285657600080fd5b505afa15801561286a573d6000803e3d6000fd5b505050506040513d602081101561288057600080fd5b5051116125245760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6068546001600160a01b031661292f578034101561292a5760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b6117a7565b60685460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b158015612a0a57600080fd5b505af1158015612a1e573d6000803e3d6000fd5b505050506040513d6020811015612a3457600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015612a8257600080fd5b505afa158015612a96573d6000803e3d6000fd5b505050506040513d6020811015612aac57600080fd5b5051116118855760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6000818152607060205260409020546001600160a01b038381169116146114255760718054600181019091557fa1fcd19bfe8c32a61095b6bfbb2664842857e148fcbb5188386c8cd40348d5b60180546001600160a01b0384166001600160a01b031991821681179092556000838152607060205260409020805490911690911790555050565b600082820183811015612b9157600080fd5b9392505050565b6000818152607260205260409020546001600160a01b0316156117a757600090815260726020526040902080546001600160a01b0319169055565b6068546000906001600160a01b0316612bf757506001600160a01b03811631610f36565b60685460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b158015612c4757600080fd5b505afa158015612c5b573d6000803e3d6000fd5b505050506040513d6020811015612c7157600080fd5b50519050610f36565b612c8b612c85611ce0565b826126b7565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b606d54606c5411612d1f5760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216612d725760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606b5460695460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015612dce57600080fd5b505afa158015612de2573d6000803e3d6000fd5b505050506040513d6040811015612df857600080fd5b50805160209091015190935091508080841115612e1757506000612e1c565b508281035b612e25816128cc565b6000612e30876125b8565b600181015490915042811015612e6657612e4982613296565b612e57888360000154612af8565b606a5442016001830155612e80565b606a54612e7a90829063ffffffff612b7f16565b60018301555b8515612ef65760695460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015612edd57600080fd5b505af1158015612ef1573d6000803e3d6000fd5b505050505b60695460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015612f4e57600080fd5b505af1158015612f62573d6000803e3d6000fd5b5050606d546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216612ffe5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613009836125b8565b9050806001015482116130665760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b61306f81613296565b61307d838260000154612af8565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b6000826130d057506000611004565b828202828482816130dd57fe5b0414612b9157600080fd5b60006130fc846001600160a01b03166132ab565b61310857506001611301565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b8381101561318557818101518382015260200161316d565b50505050905090810190601f1680156131b25780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156131d457600080fd5b505af11580156131e8573d6000803e3d6000fd5b505050506040513d60208110156131fe57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b303b1590565b6001600160a01b03811661323a57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546117a757606d8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106132f25782800160ff1982351617855561331f565b8280016001018555821561331f579182015b8281111561331f578235825591602001919060010190613304565b5061332b92915061332f565b5090565b610ff691905b8082111561332b576000815560010161333556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582090e2645e8f5c8a27b9aa3e516ad14db63bd34f8938f3f859e51115419dc428460029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a723058209f8266073118c2fedd1d71f9f463a1f49f5dbf726c75cc7b47dc56f379d4c8610029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.6", - "updatedAt": "2019-04-18T21:59:58.637Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV3.json b/packages/contracts/src/abis/Unlock/UnlockV3.json deleted file mode 100644 index c1ddac2b3a1..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV3.json +++ /dev/null @@ -1,359 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "name": "deployed", - "type": "bool" - }, - { - "name": "totalSales", - "type": "uint256" - }, - { - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenURI", - "type": "string" - } - ], - "name": "NewTokenURI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenSymbol", - "type": "string" - } - ], - "name": "NewGlobalTokenSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "name": "_lockName", - "type": "string" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_purchaser", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "name": "discount", - "type": "uint256" - }, - { - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_discount", - "type": "uint256" - }, - { - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalBaseTokenURI", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_URI", - "type": "string" - } - ], - "name": "setGlobalBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalTokenSymbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_symbol", - "type": "string" - } - ], - "name": "setGlobalTokenSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b5061578b806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001245760003560e01c80638da5cb5b11620000b1578063c4d66de8116200007b578063c4d66de814620003da578063cf92a2b11462000403578063d6e9e80314620004d0578063f2fde38b14620004da578063f700b9e214620005035762000124565b80638da5cb5b146200034b5780638f32d59b1462000371578063939d9f1f146200038f578063a082eb0e14620003be5762000124565b80634220bd4611620000f35780634220bd4614620002cd5780635de9a13714620002ee578063715018a614620003375780637ff94bb214620003415762000124565b80630c8346d014620001655780630cb175e314620001dd57806335a750de14620002255780633652466314620002a7575b60408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b620001db600480360360208110156200017d57600080fd5b8101906020810181356401000000008111156200019957600080fd5b820183602082011115620001ac57600080fd5b80359060200191846001830284011164010000000083111715620001cf57600080fd5b50909250905062000579565b005b6200020c60048036036040811015620001f557600080fd5b506001600160a01b03813516906020013562000600565b6040805192835260208301919091528051918290030190f35b6200022f62000609565b6040805160208082528351818301528351919283929083019185019080838360005b838110156200026b57818101518382015260200162000251565b50505050905090810190601f168015620002995780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620001db60048036036040811015620002bf57600080fd5b5080359060200135620006a4565b620002d762000708565b6040805161ffff9092168252519081900360200190f35b62000317600480360360208110156200030657600080fd5b50356001600160a01b03166200070d565b604080519315158452602084019290925282820152519081900360600190f35b620001db62000732565b6200022f62000790565b62000355620007f4565b604080516001600160a01b039092168252519081900360200190f35b6200037b62000803565b604080519115158252519081900360200190f35b620001db60048036036040811015620003a757600080fd5b50803590602001356001600160a01b031662000814565b620003c862000890565b60408051918252519081900360200190f35b620001db60048036036020811015620003f257600080fd5b50356001600160a01b031662000896565b620001db600480360360a08110156200041b57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156200045857600080fd5b8201836020820111156200046b57600080fd5b803590602001918460018302840111640100000000831117156200048e57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062000947945050505050565b620003c862000abb565b620001db60048036036020811015620004f257600080fd5b50356001600160a01b031662000ac1565b620001db600480360360208110156200051b57600080fd5b8101906020810181356401000000008111156200053757600080fd5b8201836020820111156200054a57600080fd5b803590602001918460018302840111640100000000831117156200056d57600080fd5b50909250905062000ae3565b6200058362000803565b6200058d57600080fd5b6200059b6069838362000cd6565b507f8eca6ea708f9bc34439b72366aa672afc86bb8b1294f1ba9637945c5dab8ea74828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b50600091829150565b606a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006995780601f106200066d5761010080835404028352916020019162000699565b820191906000526020600020905b8154815290600101906020018083116200067b57829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff16620006fc5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b60678054830190555050565b600390565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6200073c62000803565b6200074657600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006995780601f106200066d5761010080835404028352916020019162000699565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff166200086c5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b600054610100900460ff1680620008b25750620008b262000b6a565b80620008c1575060005460ff16155b6200090157604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062005732602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff166200092c8262000b70565b600080549115156101000261ff001990921691909117905550565b60003386868686866040516200095d9062000d5b565b80876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015620009db578181015183820152602001620009c1565b50505050905090810190601f16801562000a095780820380516001836020036101000a031916815260200191505b50975050505050505050604051809103906000f08015801562000a30573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3505050505050565b60665481565b62000acb62000803565b62000ad557600080fd5b62000ae08162000c66565b50565b62000aed62000803565b62000af757600080fd5b62000b05606a838362000cd6565b507f5df60d9c07de4f51d515f589e0a9040f9734137499f203619d3092675226f049828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b303b1590565b600054610100900460ff168062000b8c575062000b8c62000b6a565b8062000b9b575060005460ff16155b62000bdb57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062005732602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091178355603380546001600160a01b0319166001600160a01b0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b6001600160a01b03811662000c7a57600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000d195782800160ff1982351617855562000d49565b8280016001018555821562000d49579182015b8281111562000d4957823582559160200191906001019062000d2c565b5062000d5792915062000d69565b5090565b6149ab8062000d8783390190565b620006a191905b8082111562000d57576000815560010162000d7056fe6080604052600060755560646076556001607755600a6078553480156200002557600080fd5b50604051620049ab380380620049ab833981018060405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50509291905050508085848487620000db6301ffc9a760e01b6200030260201b60201c565b6001600160a01b03811615806200015957506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200012957600080fd5b505afa1580156200013e573d6000803e3d6000fd5b505050506040513d60208110156200015557600080fd5b5051115b620001c557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60678054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200027b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606880546001600160a01b03191633179055606992909255606a55606b558051620002ae90607090602084019062000488565b50620002c7635b5e139f60e01b6200030260201b60201c565b50620002e06380ac58cd60e01b6200030260201b60201c565b620002f6866200036f60201b62002ff81760201c565b5050505050506200052a565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200033257600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620003915750620003916200048160201b60201c565b80620003a0575060015460ff16155b620003f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806200497d602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004cb57805160ff1916838001178555620004fb565b82800160010185558215620004fb579182015b82811115620004fb578251825591602001919060010190620004de565b50620005099291506200050d565b5090565b6200048591905b8082111562000509576000815560010162000514565b614443806200053a6000396000f3fe6080604052600436106103ce5760003560e01c806370a08231116101fd5780639b3f0b1711610118578063c1c98d03116100ab578063d42cfc411161007a578063d42cfc411461136e578063e985e9c514611383578063f2fde38b146113be578063f6e4641f146113f1578063f8faf94214611417576103ce565b8063c1c98d03146112d0578063c4d66de8146112e5578063c87b56dd14611318578063d1bbd49c14611342576103ce565b8063a843a4e7116100e7578063a843a4e714611139578063abdf82ce1461114e578063b88d4fde14611181578063b8968bb414611245576103ce565b80639b3f0b171461107d5780639d76ea58146110b65780639f98d3cb146110cb578063a22cb465146110fe576103ce565b80638d0361fc1161019057806393fd18441161015f57806393fd184414610fe757806395d89b4114610ffc578063970aaeb714611011578063994a8a7114611044576103ce565b80638d0361fc14610f6d5780638da5cb5b14610fa85780638f32d59b14610fbd5780638f98ce8f14610fd2576103ce565b806374b6c106116101cc57806374b6c10614610ddf578063782a4ade14610df45780637c7c425314610e6f57806383cb0fa914610f3a576103ce565b806370a0823114610d3f57806370efb77014610d72578063715018a614610da057806371d2ee6c14610db5576103ce565b806330176e13116102ed5780634bc5a135116102805780635fdb97e11161024f5780635fdb97e114610c9a578063627cdcb914610ccd5780636352211e14610ce25780636d8ea5b414610d0c576103ce565b80634bc5a13514610b8f5780634c7a12a014610bc257806352d6a8e414610bec578063550ef3a814610c1f576103ce565b80633d3359cb116102bc5780633d3359cb146108d45780634136aa351461090457806342842e0e1461091957806345e965cd1461094f576103ce565b806330176e13146107ff57806339f469861461087a5780633ba70e31146108aa5780633ccfd60b146108bf576103ce565b806310803b721161036557806318160ddd1161033457806318160ddd146107755780631f1ec0291461078a5780632009dc65146107b457806323b872dd146107c9576103ce565b806310803b72146105dd57806310e569731461065d57806311a4c03a14610672578063150b7a0214610687576103ce565b8063095ea7b3116103a1578063095ea7b31461055e5780630c79130f1461058c5780630ed3e2cc146105b35780630f15023b146105c8576103ce565b806301ffc9a71461041c578063025e7c271461046457806306fdde03146104aa578063081812fc14610534575b3480156103da57600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561042857600080fd5b506104506004803603602081101561043f57600080fd5b50356001600160e01b031916611492565b604080519115158252519081900360200190f35b34801561047057600080fd5b5061048e6004803603602081101561048757600080fd5b50356114b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104b657600080fd5b506104bf6114dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104f95781810151838201526020016104e1565b50505050905090810190601f1680156105265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054057600080fd5b5061048e6004803603602081101561055757600080fd5b5035611573565b61058a6004803603604081101561057457600080fd5b506001600160a01b038135169060200135611584565b005b34801561059857600080fd5b506105a1611723565b60408051918252519081900360200190f35b3480156105bf57600080fd5b506105a1611729565b3480156105d457600080fd5b5061048e61172f565b3480156105e957600080fd5b5061060d6004803603604081101561060057600080fd5b508035906020013561173e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610649578181015183820152602001610631565b505050509050019250505060405180910390f35b34801561066957600080fd5b506105a1611863565b34801561067e57600080fd5b506105a1611869565b34801561069357600080fd5b50610758600480360360808110156106aa57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156106e457600080fd5b8201836020820111156106f657600080fd5b803590602001918460018302840111600160201b8311171561071757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061186f945050505050565b604080516001600160e01b03199092168252519081900360200190f35b34801561078157600080fd5b506105a1611883565b34801561079657600080fd5b5061058a600480360360208110156107ad57600080fd5b5035611889565b3480156107c057600080fd5b5061058a611937565b61058a600480360360608110156107df57600080fd5b506001600160a01b03813581169160208101359091169060400135611942565b34801561080b57600080fd5b5061058a6004803603602081101561082257600080fd5b810190602081018135600160201b81111561083c57600080fd5b82018360208201111561084e57600080fd5b803590602001918460018302840111600160201b8311171561086f57600080fd5b509092509050611ba4565b34801561088657600080fd5b5061058a6004803603604081101561089d57600080fd5b5080359060200135611bc6565b3480156108b657600080fd5b506105a1611c76565b3480156108cb57600080fd5b5061058a611c7c565b3480156108e057600080fd5b5061058a600480360360408110156108f757600080fd5b5080359060200135611cf4565b34801561091057600080fd5b50610450611da4565b61058a6004803603606081101561092f57600080fd5b506001600160a01b03813581169160208101359091169060400135611db4565b34801561095b57600080fd5b506104bf6004803603608081101561097257600080fd5b810190602081018135600160201b81111561098c57600080fd5b82018360208201111561099e57600080fd5b803590602001918460018302840111600160201b831117156109bf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1157600080fd5b820183602082011115610a2357600080fd5b803590602001918460018302840111600160201b83111715610a4457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a9657600080fd5b820183602082011115610aa857600080fd5b803590602001918460018302840111600160201b83111715610ac957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b1b57600080fd5b820183602082011115610b2d57600080fd5b803590602001918460018302840111600160201b83111715610b4e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611dcf945050505050565b348015610b9b57600080fd5b506105a160048036036020811015610bb257600080fd5b50356001600160a01b0316611f84565b348015610bce57600080fd5b506104bf60048036036020811015610be557600080fd5b5035611f96565b348015610bf857600080fd5b506105a160048036036020811015610c0f57600080fd5b50356001600160a01b031661205d565b348015610c2b57600080fd5b5061058a60048036036020811015610c4257600080fd5b810190602081018135600160201b811115610c5c57600080fd5b820183602082011115610c6e57600080fd5b803590602001918460018302840111600160201b83111715610c8f57600080fd5b509092509050612068565b348015610ca657600080fd5b506104bf60048036036020811015610cbd57600080fd5b50356001600160a01b0316612085565b348015610cd957600080fd5b5061058a61221d565b348015610cee57600080fd5b5061048e60048036036020811015610d0557600080fd5b5035612235565b348015610d1857600080fd5b5061045060048036036020811015610d2f57600080fd5b50356001600160a01b03166122b1565b348015610d4b57600080fd5b506105a160048036036020811015610d6257600080fd5b50356001600160a01b03166122d1565b61058a60048036036040811015610d8857600080fd5b506001600160a01b0381358116916020013516612346565b348015610dac57600080fd5b5061058a6123f7565b348015610dc157600080fd5b5061058a60048036036020811015610dd857600080fd5b5035612452565b348015610deb57600080fd5b506105a1612523565b348015610e0057600080fd5b5061058a60048036036020811015610e1757600080fd5b810190602081018135600160201b811115610e3157600080fd5b820183602082011115610e4357600080fd5b803590602001918460018302840111600160201b83111715610e6457600080fd5b509092509050612529565b348015610e7b57600080fd5b5061058a60048036036040811015610e9257600080fd5b810190602081018135600160201b811115610eac57600080fd5b820183602082011115610ebe57600080fd5b803590602001918460208302840111600160201b83111715610edf57600080fd5b919390929091602081019035600160201b811115610efc57600080fd5b820183602082011115610f0e57600080fd5b803590602001918460208302840111600160201b83111715610f2f57600080fd5b5090925090506125ab565b348015610f4657600080fd5b506105a160048036036020811015610f5d57600080fd5b50356001600160a01b031661260d565b348015610f7957600080fd5b506105a160048036036040811015610f9057600080fd5b506001600160a01b03813581169160200135166126d6565b348015610fb457600080fd5b5061048e61272d565b348015610fc957600080fd5b5061045061273c565b348015610fde57600080fd5b506105a161274d565b348015610ff357600080fd5b506105a1612753565b34801561100857600080fd5b506104bf612759565b34801561101d57600080fd5b506105a16004803603602081101561103457600080fd5b50356001600160a01b03166128e4565b34801561105057600080fd5b506104506004803603604081101561106757600080fd5b50803590602001356001600160a01b0316612954565b34801561108957600080fd5b5061058a600480360360408110156110a057600080fd5b506001600160a01b038135169060200135612975565b3480156110c257600080fd5b5061048e612990565b3480156110d757600080fd5b5061058a600480360360208110156110ee57600080fd5b50356001600160a01b031661299f565b34801561110a57600080fd5b5061058a6004803603604081101561112157600080fd5b506001600160a01b0381351690602001351515612a5c565b34801561114557600080fd5b5061058a612b73565b34801561115a57600080fd5b506105a16004803603602081101561117157600080fd5b50356001600160a01b0316612c32565b61058a6004803603608081101561119757600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111d157600080fd5b8201836020820111156111e357600080fd5b803590602001918460018302840111600160201b8311171561120457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612cc4945050505050565b34801561125157600080fd5b5061058a6004803603604081101561126857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561129257600080fd5b8201836020820111156112a457600080fd5b803590602001918460018302840111600160201b831117156112c557600080fd5b509092509050612e67565b3480156112dc57600080fd5b5061058a612f48565b3480156112f157600080fd5b5061058a6004803603602081101561130857600080fd5b50356001600160a01b0316612ff8565b34801561132457600080fd5b506104bf6004803603602081101561133b57600080fd5b50356130e7565b34801561134e57600080fd5b50611357613308565b6040805161ffff9092168252519081900360200190f35b34801561137a57600080fd5b506105a161330d565b34801561138f57600080fd5b50610450600480360360408110156113a657600080fd5b506001600160a01b0381358116916020013516613313565b3480156113ca57600080fd5b5061058a600480360360208110156113e157600080fd5b50356001600160a01b0316613341565b61058a6004803603602081101561140757600080fd5b50356001600160a01b031661335b565b34801561142357600080fd5b5061058a6004803603604081101561143a57600080fd5b810190602081018135600160201b81111561145457600080fd5b82018360208201111561146657600080fd5b803590602001918460208302840111600160201b8311171561148757600080fd5b9193509150356133bc565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b606f81815481106114c257fe5b6000918252602090912001546001600160a01b0316905081565b60708054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115685780601f1061153d57610100808354040283529160200191611568565b820191906000526020600020905b81548152906001019060200180831161154b57829003601f168201915b505050505090505b90565b600061157e8261340b565b92915050565b606754600160a01b900460ff166115da5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806115e58133612954565b806115f557506115f58133613478565b8061160d575061160d61160782612235565b33613313565b6116615760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b03841614156116b45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260736020526040902080546001600160a01b0319166001600160a01b03851690811790915582906116e982612235565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60785481565b60775481565b6068546001600160a01b031681565b606f546060906117985760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b606f5482908482029060009082840111156117bb5750606f5481810392506117c0565b508082015b6060836040519080825280602002602001820160405280156117ec578160200160208202803883390190505b5090506000835b8381101561185657606f818154811061180857fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061183257fe5b6001600160a01b0390921660209283029190910190910152600191820191016117f3565b5090979650505050505050565b606a5481565b60695481565b600160e11b630a85bd01025b949350505050565b606c5490565b61189161273c565b61189a57600080fd5b606754600160a01b900460ff166118f05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b61194033613499565b565b606754600160a01b900460ff166119985760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826119a2816122b1565b6119e95760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816119f48133612954565b80611a045750611a048133613478565b80611a165750611a1661160782612235565b611a6a5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b038416611abd5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b611ace611ac98661260d565b61350e565b6000611ad986613740565b90506000611ae686613740565b6001810154815491925090611b05578254808355611b0590889061375a565b428111611b29576001808401549083015582548255611b24878761375a565b611b46565b6001830154611b409042830363ffffffff6137e116565b60018301555b42600184015560008355611b59866137fa565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611bac61273c565b611bb557600080fd5b611bc160728383614351565b505050565b611bce61273c565b611bd757600080fd5b80611c1e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60775460785460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607791909155607855565b606c5481565b611c8461273c565b611c8d57600080fd5b6000611c9830613835565b905060008111611ce85760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1816138dc565b50565b611cfc61273c565b611d0557600080fd5b80611d4c5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60755460765460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607591909155607655565b606754600160a01b900460ff1681565b611bc183838360405180602001604052806000815250612cc4565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015611e1b576020820181803883390190505b509050806000805b8751811015611e7457878181518110611e3857fe5b602001015160f81c60f81b838380600101945081518110611e5557fe5b60200101906001600160f81b031916908160001a905350600101611e23565b5060005b8651811015611ec957868181518110611e8d57fe5b602001015160f81c60f81b838380600101945081518110611eaa57fe5b60200101906001600160f81b031916908160001a905350600101611e78565b5060005b8551811015611f1e57858181518110611ee257fe5b602001015160f81c60f81b838380600101945081518110611eff57fe5b60200101906001600160f81b031916908160001a905350600101611ecd565b5060005b8451811015611f7357848181518110611f3757fe5b602001015160f81c60f81b838380600101945081518110611f5457fe5b60200101906001600160f81b031916908160001a905350600101611f22565b50909b9a5050505050505050505050565b60796020526000908152604090205481565b60608180611fc05750506040805180820190915260018152600160fc1b60030260208201526114b0565b8260005b8115611fd857600101600a82049150611fc4565b6060816040519080825280601f01601f191660200182016040528015612005576020820181803883390190505b50905060001982015b841561205357600a850660300160f81b8282806001900393508151811061203157fe5b60200101906001600160f81b031916908160001a905350600a8504945061200e565b5095945050505050565b600061157e82613926565b61207061273c565b61207957600080fd5b611bc160708383614351565b604080518082018252601081527f303132333435363738396162636465660000000000000000000000000000000060208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600160fc1b600302816000815181106120f957fe5b60200101906001600160f81b031916908160001a905350600160fb1b600f028160018151811061212557fe5b60200101906001600160f81b031916908160001a90535060005b6014811015612214578260048583600c016020811061215a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061217a57fe5b602001015160f81c60f81b82826002026002018151811061219757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106121be57fe5b1a60f81b600f60f81b1660f81c60ff16815181106121d857fe5b602001015160f81c60f81b8282600202600301815181106121f557fe5b60200101906001600160f81b031916908160001a90535060010161213f565b50949350505050565b33600090815260796020526040902080546001019055565b6000818152606e602052604081205482906001600160a01b03166122945760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152606e60205260409020546001600160a01b031690565b6001600160a01b03166000908152606d6020526040902060010154421090565b60006001600160a01b0382166123265760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b61232f826122b1565b61233a57600061233d565b60015b60ff1692915050565b606754600160a01b900460ff1661239c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806123a6816122b1565b6123ed5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b611bc18383613a0b565b6123ff61273c565b61240857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b61245a61273c565b61246357600080fd5b600081116124bb5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b60006124c630613835565b9050818110156125165760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61251f826138dc565b5050565b606b5481565b61253161273c565b61253a57600080fd5b61254660718383614351565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125b361273c565b6125bc57600080fd5b60005b83811015612606576125fe8585838181106125d657fe5b905060200201356001600160a01b03168484848181106125f257fe5b90506020020135613cf1565b6001016125bf565b5050505050565b600081612619816122b1565b6126605760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061266b84613740565b905060004282600101540390506000606954821061268c5750606a546126ad565b606954606a546126a2908463ffffffff613e0716565b816126a957fe5b0490505b6076546075546126c490839063ffffffff613e0716565b816126cb57fe5b049695505050505050565b6001600160a01b0391821660009081526079602090815260409182902054825130606090811b8285015260348201929092529390941690931b60548301528051808303604801815260689092019052805191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60755481565b606f5490565b6071546060906002600019610100600184161502019091160461285257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156127c457600080fd5b505afa1580156127d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561280157600080fd5b810190808051600160201b81111561281857600080fd5b8201602081018481111561282b57600080fd5b8151600160201b81118282018710171561284457600080fd5b509094506115709350505050565b6071805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156128d85780601f106128ad576101008083540402835291602001916128d8565b820191906000526020600020905b8154815290600101906020018083116128bb57829003601f168201915b50505050509050611570565b6000816128f0816122b1565b6129375760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090205490565b6000918252606e6020526040909120546001600160a01b0391821691161490565b61297d61273c565b61298657600080fd5b61251f8282613cf1565b6067546001600160a01b031681565b6129a761273c565b6129b057600080fd5b806129ba816122b1565b612a015760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606d602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ab25760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415612b055760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526074602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612b7b61273c565b612b8457600080fd5b606754600160a01b900460ff1615612be65760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612c2f33612c2a30613835565b613e2e565b33ff5b6001600160a01b0381166000908152606d60205260408120600101548290612ca45760408051600160e51b62461bcd02815260206004820152601360248201527f4841535f4e455645525f4f574e45445f4b455900000000000000000000000000604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090206001015490565b606754600160a01b900460ff16612d1a5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b81612d258133612954565b80612d355750612d358133613478565b80612d475750612d4761160782612235565b612d9b5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b612da483612235565b612dad816122b1565b612df45760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b612dff868686611942565b612e0b86868686614049565b612e5f5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612ec2612e86612e8186336126d6565b614182565b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141d392505050565b6001600160a01b031614612f205760408051600160e51b62461bcd02815260206004820152601160248201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038316600090815260796020526040902080546001019055611bc183613499565b612f5061273c565b612f5957600080fd5b606754600160a01b900460ff16612faf5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061301157506130116142c1565b8061301f575060015460ff16155b61305d57604051600160e51b62461bcd02815260040180806020018281038252602e8152602001806143ea602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b6000818152606e602052604090205460609082906001600160a01b03166131495760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b6072546060906002600019610100600184161502019091160461324257606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b1580156131b457600080fd5b505afa1580156131c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156131f157600080fd5b810190808051600160201b81111561320857600080fd5b8201602081018481111561321b57600080fd5b8151600160201b81118282018710171561323457600080fd5b509094506132d09350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156132c85780601f1061329d576101008083540402835291602001916132c8565b820191906000526020600020905b8154815290600101906020018083116132ab57829003601f168201915b505050505090505b61187b816132dd30612085565b604051806040016040528060018152602001600160f81b602f0281525061330388611f96565b611dcf565b600390565b60765481565b6001600160a01b03918216600090815260746020908152604080832093909416825291909152205460ff1690565b61334961273c565b61335257600080fd5b611cf1816142c7565b606754600160a01b900460ff166133b15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b611cf1816000613a0b565b6133c461273c565b6133cd57600080fd5b60005b82811015613405576133fd8484838181106133e757fe5b905060200201356001600160a01b031683613cf1565b6001016133d0565b50505050565b6000818152607360205260408120546001600160a01b03168061157e5760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260736020526040909120546001600160a01b0391821691161490565b60006134a482613740565b905060006134b183613926565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611bc157611bc13382613e2e565b8015611cf1576067546001600160a01b031661357757803410156135725760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1565b60675460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156135ca57600080fd5b505afa1580156135de573d6000803e3d6000fd5b505050506040513d60208110156135f457600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561365257600080fd5b505af1158015613666573d6000803e3d6000fd5b505050506040513d602081101561367c57600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156136ca57600080fd5b505afa1580156136de573d6000803e3d6000fd5b505050506040513d60208110156136f457600080fd5b505111611bc15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6001600160a01b03166000908152606d6020526040902090565b6000818152606e60205260409020546001600160a01b0383811691161461251f57606f8054600181019091557f39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e127110180546001600160a01b0384166001600160a01b031991821681179092556000838152606e60205260409020805490911690911790555050565b6000828201838110156137f357600080fd5b9392505050565b6000818152607360205260409020546001600160a01b031615611cf157600090815260736020526040902080546001600160a01b0319169055565b6067546000906001600160a01b031661385957506001600160a01b038116316114b0565b60675460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156138a957600080fd5b505afa1580156138bd573d6000803e3d6000fd5b505050506040513d60208110156138d357600080fd5b505190506114b0565b6138ed6138e761272d565b82613e2e565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600081613932816122b1565b6139795760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061398484613740565b9050600042826001015403905060695481106139a457606a5493506139c5565b606954606a546139ba908363ffffffff613e0716565b816139c157fe5b0493505b60006078546139e1607754606a54613e0790919063ffffffff16565b816139e857fe5b049050808511156139fd578085039450613a02565b600094505b50505050919050565b606c54606b5411613a665760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216613ab95760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606a5460685460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613b1557600080fd5b505afa158015613b29573d6000803e3d6000fd5b505050506040513d6040811015613b3f57600080fd5b50805160209091015190935091508080841115613b5e57506000613b63565b508281035b613b6c8161350e565b6000613b7787613740565b6001810154815491925090613bac57613b8f82614336565b613b9d88836000015461375a565b60695442016001830155613bc6565b606954613bc090829063ffffffff6137e116565b60018301555b8515613c3c5760685460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613c2357600080fd5b505af1158015613c37573d6000803e3d6000fd5b505050505b60685460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613c9457600080fd5b505af1158015613ca8573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216613d445760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613d4f83613740565b905080600101548211613dac5760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b613db581614336565b613dc383826000015461375a565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082613e165750600061157e565b82820282848281613e2357fe5b04146137f357600080fd5b801561251f576067546001600160a01b0316613e80576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015613e7a573d6000803e3d6000fd5b5061251f565b60675460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613ed557600080fd5b505afa158015613ee9573d6000803e3d6000fd5b505050506040513d6020811015613eff57600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613f5a57600080fd5b505af1158015613f6e573d6000803e3d6000fd5b505050506040513d6020811015613f8457600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6020811015613ffd57600080fd5b5051116134055760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b600061405d846001600160a01b031661434b565b6140695750600161187b565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b838110156140e65781810151838201526020016140ce565b50505050905090810190601f1680156141135780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561413557600080fd5b505af1158015614149573d6000803e3d6000fd5b505050506040513d602081101561415f57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b600081516041146141e65750600061157e565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561422c576000935050505061157e565b8060ff16601b1415801561424457508060ff16601c14155b15614255576000935050505061157e565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142ac573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b0381166142da57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b8054611cf157606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143925782800160ff198235161785556143bf565b828001600101855582156143bf579182015b828111156143bf5782358255916020019190600101906143a4565b506143cb9291506143cf565b5090565b61157091905b808211156143cb57600081556001016143d556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582031474d01281aa90a56dde5554eed5c93cdafcfbf9c58bfb981584096593435520029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a72305820f809adf8c89c25b83b9c11ae79bd8a35345c3f519ec7b94f14e165e0a1b229670029", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620001245760003560e01c80638da5cb5b11620000b1578063c4d66de8116200007b578063c4d66de814620003da578063cf92a2b11462000403578063d6e9e80314620004d0578063f2fde38b14620004da578063f700b9e214620005035762000124565b80638da5cb5b146200034b5780638f32d59b1462000371578063939d9f1f146200038f578063a082eb0e14620003be5762000124565b80634220bd4611620000f35780634220bd4614620002cd5780635de9a13714620002ee578063715018a614620003375780637ff94bb214620003415762000124565b80630c8346d014620001655780630cb175e314620001dd57806335a750de14620002255780633652466314620002a7575b60408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b620001db600480360360208110156200017d57600080fd5b8101906020810181356401000000008111156200019957600080fd5b820183602082011115620001ac57600080fd5b80359060200191846001830284011164010000000083111715620001cf57600080fd5b50909250905062000579565b005b6200020c60048036036040811015620001f557600080fd5b506001600160a01b03813516906020013562000600565b6040805192835260208301919091528051918290030190f35b6200022f62000609565b6040805160208082528351818301528351919283929083019185019080838360005b838110156200026b57818101518382015260200162000251565b50505050905090810190601f168015620002995780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620001db60048036036040811015620002bf57600080fd5b5080359060200135620006a4565b620002d762000708565b6040805161ffff9092168252519081900360200190f35b62000317600480360360208110156200030657600080fd5b50356001600160a01b03166200070d565b604080519315158452602084019290925282820152519081900360600190f35b620001db62000732565b6200022f62000790565b62000355620007f4565b604080516001600160a01b039092168252519081900360200190f35b6200037b62000803565b604080519115158252519081900360200190f35b620001db60048036036040811015620003a757600080fd5b50803590602001356001600160a01b031662000814565b620003c862000890565b60408051918252519081900360200190f35b620001db60048036036020811015620003f257600080fd5b50356001600160a01b031662000896565b620001db600480360360a08110156200041b57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156200045857600080fd5b8201836020820111156200046b57600080fd5b803590602001918460018302840111640100000000831117156200048e57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062000947945050505050565b620003c862000abb565b620001db60048036036020811015620004f257600080fd5b50356001600160a01b031662000ac1565b620001db600480360360208110156200051b57600080fd5b8101906020810181356401000000008111156200053757600080fd5b8201836020820111156200054a57600080fd5b803590602001918460018302840111640100000000831117156200056d57600080fd5b50909250905062000ae3565b6200058362000803565b6200058d57600080fd5b6200059b6069838362000cd6565b507f8eca6ea708f9bc34439b72366aa672afc86bb8b1294f1ba9637945c5dab8ea74828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b50600091829150565b606a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006995780601f106200066d5761010080835404028352916020019162000699565b820191906000526020600020905b8154815290600101906020018083116200067b57829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff16620006fc5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b60678054830190555050565b600390565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6200073c62000803565b6200074657600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006995780601f106200066d5761010080835404028352916020019162000699565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff166200086c5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b01b694f4e4c595f4c4f434b5302604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b600054610100900460ff1680620008b25750620008b262000b6a565b80620008c1575060005460ff16155b6200090157604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062005732602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091179092550460ff166200092c8262000b70565b600080549115156101000261ff001990921691909117905550565b60003386868686866040516200095d9062000d5b565b80876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015620009db578181015183820152602001620009c1565b50505050905090810190601f16801562000a095780820380516001836020036101000a031916815260200191505b50975050505050505050604051809103906000f08015801562000a30573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3505050505050565b60665481565b62000acb62000803565b62000ad557600080fd5b62000ae08162000c66565b50565b62000aed62000803565b62000af757600080fd5b62000b05606a838362000cd6565b507f5df60d9c07de4f51d515f589e0a9040f9734137499f203619d3092675226f049828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b303b1590565b600054610100900460ff168062000b8c575062000b8c62000b6a565b8062000b9b575060005460ff16155b62000bdb57604051600160e51b62461bcd02815260040180806020018281038252602e81526020018062005732602e913960400191505060405180910390fd5b60008054600161010061ff00198316811760ff1916919091178355603380546001600160a01b0319166001600160a01b0386811691909117918290556040519290930460ff1693921691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080549115156101000261ff001990921691909117905550565b6001600160a01b03811662000c7a57600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000d195782800160ff1982351617855562000d49565b8280016001018555821562000d49579182015b8281111562000d4957823582559160200191906001019062000d2c565b5062000d5792915062000d69565b5090565b6149ab8062000d8783390190565b620006a191905b8082111562000d57576000815560010162000d7056fe6080604052600060755560646076556001607755600a6078553480156200002557600080fd5b50604051620049ab380380620049ab833981018060405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50509291905050508085848487620000db6301ffc9a760e01b6200030260201b60201c565b6001600160a01b03811615806200015957506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200012957600080fd5b505afa1580156200013e573d6000803e3d6000fd5b505050506040513d60208110156200015557600080fd5b5051115b620001c557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b60678054600160a01b60ff02196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200027b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b606880546001600160a01b03191633179055606992909255606a55606b558051620002ae90607090602084019062000488565b50620002c7635b5e139f60e01b6200030260201b60201c565b50620002e06380ac58cd60e01b6200030260201b60201c565b620002f6866200036f60201b62002ff81760201c565b5050505050506200052a565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200033257600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620003915750620003916200048160201b60201c565b80620003a0575060015460ff16155b620003f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806200497d602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004cb57805160ff1916838001178555620004fb565b82800160010185558215620004fb579182015b82811115620004fb578251825591602001919060010190620004de565b50620005099291506200050d565b5090565b6200048591905b8082111562000509576000815560010162000514565b614443806200053a6000396000f3fe6080604052600436106103ce5760003560e01c806370a08231116101fd5780639b3f0b1711610118578063c1c98d03116100ab578063d42cfc411161007a578063d42cfc411461136e578063e985e9c514611383578063f2fde38b146113be578063f6e4641f146113f1578063f8faf94214611417576103ce565b8063c1c98d03146112d0578063c4d66de8146112e5578063c87b56dd14611318578063d1bbd49c14611342576103ce565b8063a843a4e7116100e7578063a843a4e714611139578063abdf82ce1461114e578063b88d4fde14611181578063b8968bb414611245576103ce565b80639b3f0b171461107d5780639d76ea58146110b65780639f98d3cb146110cb578063a22cb465146110fe576103ce565b80638d0361fc1161019057806393fd18441161015f57806393fd184414610fe757806395d89b4114610ffc578063970aaeb714611011578063994a8a7114611044576103ce565b80638d0361fc14610f6d5780638da5cb5b14610fa85780638f32d59b14610fbd5780638f98ce8f14610fd2576103ce565b806374b6c106116101cc57806374b6c10614610ddf578063782a4ade14610df45780637c7c425314610e6f57806383cb0fa914610f3a576103ce565b806370a0823114610d3f57806370efb77014610d72578063715018a614610da057806371d2ee6c14610db5576103ce565b806330176e13116102ed5780634bc5a135116102805780635fdb97e11161024f5780635fdb97e114610c9a578063627cdcb914610ccd5780636352211e14610ce25780636d8ea5b414610d0c576103ce565b80634bc5a13514610b8f5780634c7a12a014610bc257806352d6a8e414610bec578063550ef3a814610c1f576103ce565b80633d3359cb116102bc5780633d3359cb146108d45780634136aa351461090457806342842e0e1461091957806345e965cd1461094f576103ce565b806330176e13146107ff57806339f469861461087a5780633ba70e31146108aa5780633ccfd60b146108bf576103ce565b806310803b721161036557806318160ddd1161033457806318160ddd146107755780631f1ec0291461078a5780632009dc65146107b457806323b872dd146107c9576103ce565b806310803b72146105dd57806310e569731461065d57806311a4c03a14610672578063150b7a0214610687576103ce565b8063095ea7b3116103a1578063095ea7b31461055e5780630c79130f1461058c5780630ed3e2cc146105b35780630f15023b146105c8576103ce565b806301ffc9a71461041c578063025e7c271461046457806306fdde03146104aa578063081812fc14610534575b3480156103da57600080fd5b5060408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f46414c4c4241434b02604482015290519081900360640190fd5b34801561042857600080fd5b506104506004803603602081101561043f57600080fd5b50356001600160e01b031916611492565b604080519115158252519081900360200190f35b34801561047057600080fd5b5061048e6004803603602081101561048757600080fd5b50356114b5565b604080516001600160a01b039092168252519081900360200190f35b3480156104b657600080fd5b506104bf6114dc565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104f95781810151838201526020016104e1565b50505050905090810190601f1680156105265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561054057600080fd5b5061048e6004803603602081101561055757600080fd5b5035611573565b61058a6004803603604081101561057457600080fd5b506001600160a01b038135169060200135611584565b005b34801561059857600080fd5b506105a1611723565b60408051918252519081900360200190f35b3480156105bf57600080fd5b506105a1611729565b3480156105d457600080fd5b5061048e61172f565b3480156105e957600080fd5b5061060d6004803603604081101561060057600080fd5b508035906020013561173e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610649578181015183820152602001610631565b505050509050019250505060405180910390f35b34801561066957600080fd5b506105a1611863565b34801561067e57600080fd5b506105a1611869565b34801561069357600080fd5b50610758600480360360808110156106aa57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156106e457600080fd5b8201836020820111156106f657600080fd5b803590602001918460018302840111600160201b8311171561071757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061186f945050505050565b604080516001600160e01b03199092168252519081900360200190f35b34801561078157600080fd5b506105a1611883565b34801561079657600080fd5b5061058a600480360360208110156107ad57600080fd5b5035611889565b3480156107c057600080fd5b5061058a611937565b61058a600480360360608110156107df57600080fd5b506001600160a01b03813581169160208101359091169060400135611942565b34801561080b57600080fd5b5061058a6004803603602081101561082257600080fd5b810190602081018135600160201b81111561083c57600080fd5b82018360208201111561084e57600080fd5b803590602001918460018302840111600160201b8311171561086f57600080fd5b509092509050611ba4565b34801561088657600080fd5b5061058a6004803603604081101561089d57600080fd5b5080359060200135611bc6565b3480156108b657600080fd5b506105a1611c76565b3480156108cb57600080fd5b5061058a611c7c565b3480156108e057600080fd5b5061058a600480360360408110156108f757600080fd5b5080359060200135611cf4565b34801561091057600080fd5b50610450611da4565b61058a6004803603606081101561092f57600080fd5b506001600160a01b03813581169160208101359091169060400135611db4565b34801561095b57600080fd5b506104bf6004803603608081101561097257600080fd5b810190602081018135600160201b81111561098c57600080fd5b82018360208201111561099e57600080fd5b803590602001918460018302840111600160201b831117156109bf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1157600080fd5b820183602082011115610a2357600080fd5b803590602001918460018302840111600160201b83111715610a4457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a9657600080fd5b820183602082011115610aa857600080fd5b803590602001918460018302840111600160201b83111715610ac957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b1b57600080fd5b820183602082011115610b2d57600080fd5b803590602001918460018302840111600160201b83111715610b4e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611dcf945050505050565b348015610b9b57600080fd5b506105a160048036036020811015610bb257600080fd5b50356001600160a01b0316611f84565b348015610bce57600080fd5b506104bf60048036036020811015610be557600080fd5b5035611f96565b348015610bf857600080fd5b506105a160048036036020811015610c0f57600080fd5b50356001600160a01b031661205d565b348015610c2b57600080fd5b5061058a60048036036020811015610c4257600080fd5b810190602081018135600160201b811115610c5c57600080fd5b820183602082011115610c6e57600080fd5b803590602001918460018302840111600160201b83111715610c8f57600080fd5b509092509050612068565b348015610ca657600080fd5b506104bf60048036036020811015610cbd57600080fd5b50356001600160a01b0316612085565b348015610cd957600080fd5b5061058a61221d565b348015610cee57600080fd5b5061048e60048036036020811015610d0557600080fd5b5035612235565b348015610d1857600080fd5b5061045060048036036020811015610d2f57600080fd5b50356001600160a01b03166122b1565b348015610d4b57600080fd5b506105a160048036036020811015610d6257600080fd5b50356001600160a01b03166122d1565b61058a60048036036040811015610d8857600080fd5b506001600160a01b0381358116916020013516612346565b348015610dac57600080fd5b5061058a6123f7565b348015610dc157600080fd5b5061058a60048036036020811015610dd857600080fd5b5035612452565b348015610deb57600080fd5b506105a1612523565b348015610e0057600080fd5b5061058a60048036036020811015610e1757600080fd5b810190602081018135600160201b811115610e3157600080fd5b820183602082011115610e4357600080fd5b803590602001918460018302840111600160201b83111715610e6457600080fd5b509092509050612529565b348015610e7b57600080fd5b5061058a60048036036040811015610e9257600080fd5b810190602081018135600160201b811115610eac57600080fd5b820183602082011115610ebe57600080fd5b803590602001918460208302840111600160201b83111715610edf57600080fd5b919390929091602081019035600160201b811115610efc57600080fd5b820183602082011115610f0e57600080fd5b803590602001918460208302840111600160201b83111715610f2f57600080fd5b5090925090506125ab565b348015610f4657600080fd5b506105a160048036036020811015610f5d57600080fd5b50356001600160a01b031661260d565b348015610f7957600080fd5b506105a160048036036040811015610f9057600080fd5b506001600160a01b03813581169160200135166126d6565b348015610fb457600080fd5b5061048e61272d565b348015610fc957600080fd5b5061045061273c565b348015610fde57600080fd5b506105a161274d565b348015610ff357600080fd5b506105a1612753565b34801561100857600080fd5b506104bf612759565b34801561101d57600080fd5b506105a16004803603602081101561103457600080fd5b50356001600160a01b03166128e4565b34801561105057600080fd5b506104506004803603604081101561106757600080fd5b50803590602001356001600160a01b0316612954565b34801561108957600080fd5b5061058a600480360360408110156110a057600080fd5b506001600160a01b038135169060200135612975565b3480156110c257600080fd5b5061048e612990565b3480156110d757600080fd5b5061058a600480360360208110156110ee57600080fd5b50356001600160a01b031661299f565b34801561110a57600080fd5b5061058a6004803603604081101561112157600080fd5b506001600160a01b0381351690602001351515612a5c565b34801561114557600080fd5b5061058a612b73565b34801561115a57600080fd5b506105a16004803603602081101561117157600080fd5b50356001600160a01b0316612c32565b61058a6004803603608081101561119757600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156111d157600080fd5b8201836020820111156111e357600080fd5b803590602001918460018302840111600160201b8311171561120457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612cc4945050505050565b34801561125157600080fd5b5061058a6004803603604081101561126857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561129257600080fd5b8201836020820111156112a457600080fd5b803590602001918460018302840111600160201b831117156112c557600080fd5b509092509050612e67565b3480156112dc57600080fd5b5061058a612f48565b3480156112f157600080fd5b5061058a6004803603602081101561130857600080fd5b50356001600160a01b0316612ff8565b34801561132457600080fd5b506104bf6004803603602081101561133b57600080fd5b50356130e7565b34801561134e57600080fd5b50611357613308565b6040805161ffff9092168252519081900360200190f35b34801561137a57600080fd5b506105a161330d565b34801561138f57600080fd5b50610450600480360360408110156113a657600080fd5b506001600160a01b0381358116916020013516613313565b3480156113ca57600080fd5b5061058a600480360360208110156113e157600080fd5b50356001600160a01b0316613341565b61058a6004803603602081101561140757600080fd5b50356001600160a01b031661335b565b34801561142357600080fd5b5061058a6004803603604081101561143a57600080fd5b810190602081018135600160201b81111561145457600080fd5b82018360208201111561146657600080fd5b803590602001918460208302840111600160201b8311171561148757600080fd5b9193509150356133bc565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b606f81815481106114c257fe5b6000918252602090912001546001600160a01b0316905081565b60708054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115685780601f1061153d57610100808354040283529160200191611568565b820191906000526020600020905b81548152906001019060200180831161154b57829003601f168201915b505050505090505b90565b600061157e8261340b565b92915050565b606754600160a01b900460ff166115da5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806115e58133612954565b806115f557506115f58133613478565b8061160d575061160d61160782612235565b33613313565b6116615760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b336001600160a01b03841614156116b45760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b600082815260736020526040902080546001600160a01b0319166001600160a01b03851690811790915582906116e982612235565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60785481565b60775481565b6068546001600160a01b031681565b606f546060906117985760408051600160e51b62461bcd02815260206004820152601360248201527f4e4f5f4f55545354414e44494e475f4b45595300000000000000000000000000604482015290519081900360640190fd5b606f5482908482029060009082840111156117bb5750606f5481810392506117c0565b508082015b6060836040519080825280602002602001820160405280156117ec578160200160208202803883390190505b5090506000835b8381101561185657606f818154811061180857fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061183257fe5b6001600160a01b0390921660209283029190910190910152600191820191016117f3565b5090979650505050505050565b606a5481565b60695481565b600160e11b630a85bd01025b949350505050565b606c5490565b61189161273c565b61189a57600080fd5b606754600160a01b900460ff166118f05760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b61194033613499565b565b606754600160a01b900460ff166119985760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b826119a2816122b1565b6119e95760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b816119f48133612954565b80611a045750611a048133613478565b80611a165750611a1661160782612235565b611a6a5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b6001600160a01b038416611abd5760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b611ace611ac98661260d565b61350e565b6000611ad986613740565b90506000611ae686613740565b6001810154815491925090611b05578254808355611b0590889061375a565b428111611b29576001808401549083015582548255611b24878761375a565b611b46565b6001830154611b409042830363ffffffff6137e116565b60018301555b42600184015560008355611b59866137fa565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611bac61273c565b611bb557600080fd5b611bc160728383614351565b505050565b611bce61273c565b611bd757600080fd5b80611c1e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60775460785460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607791909155607855565b606c5481565b611c8461273c565b611c8d57600080fd5b6000611c9830613835565b905060008111611ce85760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1816138dc565b50565b611cfc61273c565b611d0557600080fd5b80611d4c5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b494e56414c49445f5241544502604482015290519081900360640190fd5b60755460765460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607591909155607655565b606754600160a01b900460ff1681565b611bc183838360405180602001604052806000815250612cc4565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f191660200182016040528015611e1b576020820181803883390190505b509050806000805b8751811015611e7457878181518110611e3857fe5b602001015160f81c60f81b838380600101945081518110611e5557fe5b60200101906001600160f81b031916908160001a905350600101611e23565b5060005b8651811015611ec957868181518110611e8d57fe5b602001015160f81c60f81b838380600101945081518110611eaa57fe5b60200101906001600160f81b031916908160001a905350600101611e78565b5060005b8551811015611f1e57858181518110611ee257fe5b602001015160f81c60f81b838380600101945081518110611eff57fe5b60200101906001600160f81b031916908160001a905350600101611ecd565b5060005b8451811015611f7357848181518110611f3757fe5b602001015160f81c60f81b838380600101945081518110611f5457fe5b60200101906001600160f81b031916908160001a905350600101611f22565b50909b9a5050505050505050505050565b60796020526000908152604090205481565b60608180611fc05750506040805180820190915260018152600160fc1b60030260208201526114b0565b8260005b8115611fd857600101600a82049150611fc4565b6060816040519080825280601f01601f191660200182016040528015612005576020820181803883390190505b50905060001982015b841561205357600a850660300160f81b8282806001900393508151811061203157fe5b60200101906001600160f81b031916908160001a905350600a8504945061200e565b5095945050505050565b600061157e82613926565b61207061273c565b61207957600080fd5b611bc160708383614351565b604080518082018252601081527f303132333435363738396162636465660000000000000000000000000000000060208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600160fc1b600302816000815181106120f957fe5b60200101906001600160f81b031916908160001a905350600160fb1b600f028160018151811061212557fe5b60200101906001600160f81b031916908160001a90535060005b6014811015612214578260048583600c016020811061215a57fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061217a57fe5b602001015160f81c60f81b82826002026002018151811061219757fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106121be57fe5b1a60f81b600f60f81b1660f81c60ff16815181106121d857fe5b602001015160f81c60f81b8282600202600301815181106121f557fe5b60200101906001600160f81b031916908160001a90535060010161213f565b50949350505050565b33600090815260796020526040902080546001019055565b6000818152606e602052604081205482906001600160a01b03166122945760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b50506000908152606e60205260409020546001600160a01b031690565b6001600160a01b03166000908152606d6020526040902060010154421090565b60006001600160a01b0382166123265760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b61232f826122b1565b61233a57600061233d565b60015b60ff1692915050565b606754600160a01b900460ff1661239c5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b806123a6816122b1565b6123ed5760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b611bc18383613a0b565b6123ff61273c565b61240857600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b61245a61273c565b61246357600080fd5b600081116124bb5760408051600160e51b62461bcd02815260206004820152601160248201527f475245415445525f5448414e5f5a45524f000000000000000000000000000000604482015290519081900360640190fd5b60006124c630613835565b9050818110156125165760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b61251f826138dc565b5050565b606b5481565b61253161273c565b61253a57600080fd5b61254660718383614351565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6125b361273c565b6125bc57600080fd5b60005b83811015612606576125fe8585838181106125d657fe5b905060200201356001600160a01b03168484848181106125f257fe5b90506020020135613cf1565b6001016125bf565b5050505050565b600081612619816122b1565b6126605760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061266b84613740565b905060004282600101540390506000606954821061268c5750606a546126ad565b606954606a546126a2908463ffffffff613e0716565b816126a957fe5b0490505b6076546075546126c490839063ffffffff613e0716565b816126cb57fe5b049695505050505050565b6001600160a01b0391821660009081526079602090815260409182902054825130606090811b8285015260348201929092529390941690931b60548301528051808303604801815260689092019052805191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60755481565b606f5490565b6071546060906002600019610100600184161502019091160461285257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156127c457600080fd5b505afa1580156127d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561280157600080fd5b810190808051600160201b81111561281857600080fd5b8201602081018481111561282b57600080fd5b8151600160201b81118282018710171561284457600080fd5b509094506115709350505050565b6071805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156128d85780601f106128ad576101008083540402835291602001916128d8565b820191906000526020600020905b8154815290600101906020018083116128bb57829003601f168201915b50505050509050611570565b6000816128f0816122b1565b6129375760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090205490565b6000918252606e6020526040909120546001600160a01b0391821691161490565b61297d61273c565b61298657600080fd5b61251f8282613cf1565b6067546001600160a01b031681565b6129a761273c565b6129b057600080fd5b806129ba816122b1565b612a015760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b6001600160a01b0382166000908152606d602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ab25760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6001600160a01b038216331415612b055760408051600160e51b62461bcd02815260206004820152600c6024820152600160a11b6b20a8282927ab22afa9a2a62302604482015290519081900360640190fd5b3360008181526074602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612b7b61273c565b612b8457600080fd5b606754600160a01b900460ff1615612be65760408051600160e51b62461bcd02815260206004820152600d60248201527f44495341424c455f464952535400000000000000000000000000000000000000604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612c2f33612c2a30613835565b613e2e565b33ff5b6001600160a01b0381166000908152606d60205260408120600101548290612ca45760408051600160e51b62461bcd02815260206004820152601360248201527f4841535f4e455645525f4f574e45445f4b455900000000000000000000000000604482015290519081900360640190fd5b50506001600160a01b03166000908152606d602052604090206001015490565b606754600160a01b900460ff16612d1a5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b81612d258133612954565b80612d355750612d358133613478565b80612d475750612d4761160782612235565b612d9b5760408051600160e51b62461bcd02815260206004820152601a60248201527f4f4e4c595f4b45595f4f574e45525f4f525f415050524f564544000000000000604482015290519081900360640190fd5b612da483612235565b612dad816122b1565b612df45760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b612dff868686611942565b612e0b86868686614049565b612e5f5760408051600160e51b62461bcd02815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612ec2612e86612e8186336126d6565b614182565b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141d392505050565b6001600160a01b031614612f205760408051600160e51b62461bcd02815260206004820152601160248201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038316600090815260796020526040902080546001019055611bc183613499565b612f5061273c565b612f5957600080fd5b606754600160a01b900460ff16612faf5760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805474ff000000000000000000000000000000000000000019169055565b600154610100900460ff168061301157506130116142c1565b8061301f575060015460ff16155b61305d57604051600160e51b62461bcd02815260040180806020018281038252602e8152602001806143ea602e913960400191505060405180910390fd5b6001805461010061ff00198216811760ff19168317909255603480546001600160a01b0319166001600160a01b0385811691909117918290556040519390920460ff16929116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180549115156101000261ff001990921691909117905550565b6000818152606e602052604090205460609082906001600160a01b03166131495760408051600160e51b62461bcd02815260206004820152600b6024820152600160a81b6a4e4f5f535543485f4b455902604482015290519081900360640190fd5b6072546060906002600019610100600184161502019091160461324257606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b1580156131b457600080fd5b505afa1580156131c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156131f157600080fd5b810190808051600160201b81111561320857600080fd5b8201602081018481111561321b57600080fd5b8151600160201b81118282018710171561323457600080fd5b509094506132d09350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156132c85780601f1061329d576101008083540402835291602001916132c8565b820191906000526020600020905b8154815290600101906020018083116132ab57829003601f168201915b505050505090505b61187b816132dd30612085565b604051806040016040528060018152602001600160f81b602f0281525061330388611f96565b611dcf565b600390565b60765481565b6001600160a01b03918216600090815260746020908152604080832093909416825291909152205460ff1690565b61334961273c565b61335257600080fd5b611cf1816142c7565b606754600160a01b900460ff166133b15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1313d0d2d7d11154149150d055115102604482015290519081900360640190fd5b611cf1816000613a0b565b6133c461273c565b6133cd57600080fd5b60005b82811015613405576133fd8484838181106133e757fe5b905060200201356001600160a01b031683613cf1565b6001016133d0565b50505050565b6000818152607360205260408120546001600160a01b03168061157e5760408051600160e51b62461bcd02815260206004820152600d60248201527f4e4f4e455f415050524f56454400000000000000000000000000000000000000604482015290519081900360640190fd5b600091825260736020526040909120546001600160a01b0391821691161490565b60006134a482613740565b905060006134b183613926565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611bc157611bc13382613e2e565b8015611cf1576067546001600160a01b031661357757803410156135725760408051600160e51b62461bcd0281526020600482015260106024820152600160801b6f4e4f545f454e4f5547485f46554e445302604482015290519081900360640190fd5b611cf1565b60675460408051600160e01b6370a0823102815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156135ca57600080fd5b505afa1580156135de573d6000803e3d6000fd5b505050506040513d60208110156135f457600080fd5b505160408051600160e01b6323b872dd0281523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561365257600080fd5b505af1158015613666573d6000803e3d6000fd5b505050506040513d602081101561367c57600080fd5b505060408051600160e01b6370a08231028152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156136ca57600080fd5b505afa1580156136de573d6000803e3d6000fd5b505050506040513d60208110156136f457600080fd5b505111611bc15760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b6001600160a01b03166000908152606d6020526040902090565b6000818152606e60205260409020546001600160a01b0383811691161461251f57606f8054600181019091557f39f2babe526038520877fc7c33d81accf578af4a06c5fa6b0d038cae36e127110180546001600160a01b0384166001600160a01b031991821681179092556000838152606e60205260409020805490911690911790555050565b6000828201838110156137f357600080fd5b9392505050565b6000818152607360205260409020546001600160a01b031615611cf157600090815260736020526040902080546001600160a01b0319169055565b6067546000906001600160a01b031661385957506001600160a01b038116316114b0565b60675460408051600160e01b6370a082310281526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156138a957600080fd5b505afa1580156138bd573d6000803e3d6000fd5b505050506040513d60208110156138d357600080fd5b505190506114b0565b6138ed6138e761272d565b82613e2e565b60408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b600081613932816122b1565b6139795760408051600160e51b62461bcd02815260206004820152600d60248201526001609a1b6c12d15657d393d517d59053125102604482015290519081900360640190fd5b600061398484613740565b9050600042826001015403905060695481106139a457606a5493506139c5565b606954606a546139ba908363ffffffff613e0716565b816139c157fe5b0493505b60006078546139e1607754606a54613e0790919063ffffffff16565b816139e857fe5b049050808511156139fd578085039450613a02565b600094505b50505050919050565b606c54606b5411613a665760408051600160e51b62461bcd02815260206004820152600d60248201527f4c4f434b5f534f4c445f4f555400000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038216613ab95760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b606a5460685460408051600160e01b630cb175e30281526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613b1557600080fd5b505afa158015613b29573d6000803e3d6000fd5b505050506040513d6040811015613b3f57600080fd5b50805160209091015190935091508080841115613b5e57506000613b63565b508281035b613b6c8161350e565b6000613b7787613740565b6001810154815491925090613bac57613b8f82614336565b613b9d88836000015461375a565b60695442016001830155613bc6565b606954613bc090829063ffffffff6137e116565b60018301555b8515613c3c5760685460408051600160e01b6336524663028152600481018990526024810188905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613c2357600080fd5b505af1158015613c37573d6000803e3d6000fd5b505050505b60685460408051600160e01b63939d9f1f028152600481018690526001600160a01b038a811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613c9457600080fd5b505af1158015613ca8573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038b1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050505050505050565b6001600160a01b038216613d445760408051600160e51b62461bcd02815260206004820152600f6024820152600160881b6e494e56414c49445f4144445245535302604482015290519081900360640190fd5b6000613d4f83613740565b905080600101548211613dac5760408051600160e51b62461bcd02815260206004820152601060248201527f414c52454144595f4f574e535f4b455900000000000000000000000000000000604482015290519081900360640190fd5b613db581614336565b613dc383826000015461375a565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082613e165750600061157e565b82820282848281613e2357fe5b04146137f357600080fd5b801561251f576067546001600160a01b0316613e80576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015613e7a573d6000803e3d6000fd5b5061251f565b60675460408051600160e01b6370a082310281526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613ed557600080fd5b505afa158015613ee9573d6000803e3d6000fd5b505050506040513d6020811015613eff57600080fd5b505160408051600160e01b63a9059cbb0281526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613f5a57600080fd5b505af1158015613f6e573d6000803e3d6000fd5b505050506040513d6020811015613f8457600080fd5b505060408051600160e01b6370a082310281526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613fd357600080fd5b505afa158015613fe7573d6000803e3d6000fd5b505050506040513d6020811015613ffd57600080fd5b5051116134055760408051600160e51b62461bcd02815260206004820152600f60248201526001608a1b6e1514905394d1915497d1905253115102604482015290519081900360640190fd5b600061405d846001600160a01b031661434b565b6140695750600161187b565b604051600160e11b630a85bd0102815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b838110156140e65781810151838201526020016140ce565b50505050905090810190601f1680156141135780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561413557600080fd5b505af1158015614149573d6000803e3d6000fd5b505050506040513d602081101561415f57600080fd5b50516001600160e01b031916600160e11b630a85bd010214915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b600081516041146141e65750600061157e565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561422c576000935050505061157e565b8060ff16601b1415801561424457508060ff16601c14155b15614255576000935050505061157e565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142ac573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b0381166142da57600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b8054611cf157606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143925782800160ff198235161785556143bf565b828001600101855582156143bf579182015b828111156143bf5782358255916020019190600101906143a4565b506143cb9291506143cf565b5090565b61157091905b808211156143cb57600081556001016143d556fe436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a7230582031474d01281aa90a56dde5554eed5c93cdafcfbf9c58bfb981584096593435520029436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a165627a7a72305820f809adf8c89c25b83b9c11ae79bd8a35345c3f519ec7b94f14e165e0a1b229670029", - "compiler": { - "name": "solc", - "version": "0.5.7+commit.6da8b019.Emscripten.clang" - }, - "schemaVersion": "3.0.9", - "updatedAt": "2019-05-21T02:16:43.435Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV4.json b/packages/contracts/src/abis/Unlock/UnlockV4.json deleted file mode 100644 index 5f2c527c312..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV4.json +++ /dev/null @@ -1,359 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "name": "deployed", - "type": "bool" - }, - { - "name": "totalSales", - "type": "uint256" - }, - { - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "payable": false, - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenURI", - "type": "string" - } - ], - "name": "NewTokenURI", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "tokenSymbol", - "type": "string" - } - ], - "name": "NewGlobalTokenSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_expirationDuration", - "type": "uint256" - }, - { - "name": "_tokenAddress", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - }, - { - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "name": "_lockName", - "type": "string" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_purchaser", - "type": "address" - }, - { - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "name": "discount", - "type": "uint256" - }, - { - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_discount", - "type": "uint256" - }, - { - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalBaseTokenURI", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_URI", - "type": "string" - } - ], - "name": "setGlobalBaseTokenURI", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalTokenSymbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_symbol", - "type": "string" - } - ], - "name": "setGlobalTokenSymbol", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b506158d0806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620001245760003560e01c80638da5cb5b11620000b1578063c4d66de8116200007b578063c4d66de814620003d4578063cf92a2b114620003fd578063d6e9e80314620004ca578063f2fde38b14620004d4578063f700b9e214620004fd5762000124565b80638da5cb5b14620003455780638f32d59b146200036b578063939d9f1f1462000389578063a082eb0e14620003b85762000124565b80634220bd4611620000f35780634220bd4614620002c75780635de9a13714620002e8578063715018a614620003315780637ff94bb2146200033b5762000124565b80630c8346d0146200015f5780630cb175e314620001d757806335a750de146200021f5780633652466314620002a1575b6040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b620001d5600480360360208110156200017757600080fd5b8101906020810181356401000000008111156200019357600080fd5b820183602082011115620001a657600080fd5b80359060200191846001830284011164010000000083111715620001c957600080fd5b50909250905062000573565b005b6200020660048036036040811015620001ef57600080fd5b506001600160a01b038135169060200135620005fa565b6040805192835260208301919091528051918290030190f35b6200022962000603565b6040805160208082528351818301528351919283929083019185019080838360005b83811015620002655781810151838201526020016200024b565b50505050905090810190601f168015620002935780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620001d560048036036040811015620002b957600080fd5b50803590602001356200069e565b620002d1620006fd565b6040805161ffff9092168252519081900360200190f35b62000311600480360360208110156200030057600080fd5b50356001600160a01b031662000702565b604080519315158452602084019290925282820152519081900360600190f35b620001d562000727565b6200022962000785565b6200034f620007e9565b604080516001600160a01b039092168252519081900360200190f35b62000375620007f8565b604080519115158252519081900360200190f35b620001d560048036036040811015620003a157600080fd5b50803590602001356001600160a01b031662000809565b620003c26200087f565b60408051918252519081900360200190f35b620001d560048036036020811015620003ec57600080fd5b50356001600160a01b031662000885565b620001d5600480360360a08110156200041557600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156200045257600080fd5b8201836020820111156200046557600080fd5b803590602001918460018302840111640100000000831117156200048857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506200093a945050505050565b620003c262000aae565b620001d560048036036020811015620004ec57600080fd5b50356001600160a01b031662000ab4565b620001d5600480360360208110156200051557600080fd5b8101906020810181356401000000008111156200053157600080fd5b8201836020820111156200054457600080fd5b803590602001918460018302840111640100000000831117156200056757600080fd5b50909250905062000ad6565b6200057d620007f8565b6200058757600080fd5b620005956069838362000ccc565b507f8eca6ea708f9bc34439b72366aa672afc86bb8b1294f1ba9637945c5dab8ea74828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b50600091829150565b606a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006935780601f10620006675761010080835404028352916020019162000693565b820191906000526020600020905b8154815290600101906020018083116200067557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff16620006f0576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b600490565b60686020526000908152604090208054600182015460029092015460ff909116919083565b62000731620007f8565b6200073b57600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006935780601f10620006675761010080835404028352916020019162000693565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff166200085b576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b600054610100900460ff1680620008a15750620008a162000b5d565b80620008b0575060005460ff16155b620008ed5760405162461bcd60e51b815260040180806020018281038252602e8152602001806200586e602e913960400191505060405180910390fd5b600054610100900460ff1615801562000919576000805460ff1961ff0019909116610100171660011790555b620009248262000b63565b8015620006f9576000805461ff00191690555050565b6000338686868686604051620009509062000d51565b80876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015620009ce578181015183820152602001620009b4565b50505050905090810190601f168015620009fc5780820380516001836020036101000a031916815260200191505b50975050505050505050604051809103906000f08015801562000a23573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3505050505050565b60665481565b62000abe620007f8565b62000ac857600080fd5b62000ad38162000c5c565b50565b62000ae0620007f8565b62000aea57600080fd5b62000af8606a838362000ccc565b507f5df60d9c07de4f51d515f589e0a9040f9734137499f203619d3092675226f049828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b303b1590565b600054610100900460ff168062000b7f575062000b7f62000b5d565b8062000b8e575060005460ff16155b62000bcb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806200586e602e913960400191505060405180910390fd5b600054610100900460ff1615801562000bf7576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015620006f9576000805461ff00191690555050565b6001600160a01b03811662000c7057600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000d0f5782800160ff1982351617855562000d3f565b8280016001018555821562000d3f579182015b8281111562000d3f57823582559160200191906001019062000d22565b5062000d4d92915062000d5f565b5090565b614af18062000d7d83390190565b6200069b91905b8082111562000d4d576000815560010162000d6656fe6080604052600060765560646077556001607855600a6079553480156200002557600080fd5b5060405162004af138038062004af1833981810160405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50909350839250889150879050858588620000fa7f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b6001600160a01b03811615806200017857506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200014857600080fd5b505afa1580156200015d573d6000803e3d6000fd5b505050506040513d60208110156200017457600080fd5b5051115b620001e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460ff60a01b196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200029757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054336001600160a01b031991821617909155606d80549091166001600160a01b039590951694909417909355606991909155606a55606b558051620002e790607190602084019062000565565b506200031c7f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b50620003517f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b62000367866200044260201b620030891760201c565b50505050505062000607565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200040557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620004675750620004676001600160e01b036200055e16565b8062000476575060015460ff16155b620004cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062004ac3602e913960400191505060405180910390fd5b600154610100900460ff16158015620004f8576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156200055a576001805461ff00191690555b5050565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005a857805160ff1916838001178555620005d8565b82800160010185558215620005d8579182015b82811115620005d8578251825591602001919060010190620005bb565b50620005e6929150620005ea565b5090565b6200056291905b80821115620005e65760008155600101620005f1565b6144ac80620006176000396000f3fe6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a723058206480e8af51e7228bcb8607a89ad85724811d26200329bad052bf9dacde65861c64736f6c63430005090032", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620001245760003560e01c80638da5cb5b11620000b1578063c4d66de8116200007b578063c4d66de814620003d4578063cf92a2b114620003fd578063d6e9e80314620004ca578063f2fde38b14620004d4578063f700b9e214620004fd5762000124565b80638da5cb5b14620003455780638f32d59b146200036b578063939d9f1f1462000389578063a082eb0e14620003b85762000124565b80634220bd4611620000f35780634220bd4614620002c75780635de9a13714620002e8578063715018a614620003315780637ff94bb2146200033b5762000124565b80630c8346d0146200015f5780630cb175e314620001d757806335a750de146200021f5780633652466314620002a1575b6040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b620001d5600480360360208110156200017757600080fd5b8101906020810181356401000000008111156200019357600080fd5b820183602082011115620001a657600080fd5b80359060200191846001830284011164010000000083111715620001c957600080fd5b50909250905062000573565b005b6200020660048036036040811015620001ef57600080fd5b506001600160a01b038135169060200135620005fa565b6040805192835260208301919091528051918290030190f35b6200022962000603565b6040805160208082528351818301528351919283929083019185019080838360005b83811015620002655781810151838201526020016200024b565b50505050905090810190601f168015620002935780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b620001d560048036036040811015620002b957600080fd5b50803590602001356200069e565b620002d1620006fd565b6040805161ffff9092168252519081900360200190f35b62000311600480360360208110156200030057600080fd5b50356001600160a01b031662000702565b604080519315158452602084019290925282820152519081900360600190f35b620001d562000727565b6200022962000785565b6200034f620007e9565b604080516001600160a01b039092168252519081900360200190f35b62000375620007f8565b604080519115158252519081900360200190f35b620001d560048036036040811015620003a157600080fd5b50803590602001356001600160a01b031662000809565b620003c26200087f565b60408051918252519081900360200190f35b620001d560048036036020811015620003ec57600080fd5b50356001600160a01b031662000885565b620001d5600480360360a08110156200041557600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156200045257600080fd5b8201836020820111156200046557600080fd5b803590602001918460018302840111640100000000831117156200048857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506200093a945050505050565b620003c262000aae565b620001d560048036036020811015620004ec57600080fd5b50356001600160a01b031662000ab4565b620001d5600480360360208110156200051557600080fd5b8101906020810181356401000000008111156200053157600080fd5b8201836020820111156200054457600080fd5b803590602001918460018302840111640100000000831117156200056757600080fd5b50909250905062000ad6565b6200057d620007f8565b6200058757600080fd5b620005956069838362000ccc565b507f8eca6ea708f9bc34439b72366aa672afc86bb8b1294f1ba9637945c5dab8ea74828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b50600091829150565b606a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006935780601f10620006675761010080835404028352916020019162000693565b820191906000526020600020905b8154815290600101906020018083116200067557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff16620006f0576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b600490565b60686020526000908152604090208054600182015460029092015460ff909116919083565b62000731620007f8565b6200073b57600080fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620006935780601f10620006675761010080835404028352916020019162000693565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff166200085b576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b50606680548201905533600090815260686020526040902060010180549091019055565b60675481565b600054610100900460ff1680620008a15750620008a162000b5d565b80620008b0575060005460ff16155b620008ed5760405162461bcd60e51b815260040180806020018281038252602e8152602001806200586e602e913960400191505060405180910390fd5b600054610100900460ff1615801562000919576000805460ff1961ff0019909116610100171660011790555b620009248262000b63565b8015620006f9576000805461ff00191690555050565b6000338686868686604051620009509062000d51565b80876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015620009ce578181015183820152602001620009b4565b50505050905090810190601f168015620009fc5780820380516001836020036101000a031916815260200191505b50975050505050505050604051809103906000f08015801562000a23573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350909133917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a3505050505050565b60665481565b62000abe620007f8565b62000ac857600080fd5b62000ad38162000c5c565b50565b62000ae0620007f8565b62000aea57600080fd5b62000af8606a838362000ccc565b507f5df60d9c07de4f51d515f589e0a9040f9734137499f203619d3092675226f049828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b303b1590565b600054610100900460ff168062000b7f575062000b7f62000b5d565b8062000b8e575060005460ff16155b62000bcb5760405162461bcd60e51b815260040180806020018281038252602e8152602001806200586e602e913960400191505060405180910390fd5b600054610100900460ff1615801562000bf7576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015620006f9576000805461ff00191690555050565b6001600160a01b03811662000c7057600080fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062000d0f5782800160ff1982351617855562000d3f565b8280016001018555821562000d3f579182015b8281111562000d3f57823582559160200191906001019062000d22565b5062000d4d92915062000d5f565b5090565b614af18062000d7d83390190565b6200069b91905b8082111562000d4d576000815560010162000d6656fe6080604052600060765560646077556001607855600a6079553480156200002557600080fd5b5060405162004af138038062004af1833981810160405260c08110156200004b57600080fd5b8151602083015160408401516060850151608086015160a087018051959794969395929491938201926401000000008111156200008757600080fd5b820160208101848111156200009b57600080fd5b8151640100000000811182820187101715620000b657600080fd5b50909350839250889150879050858588620000fa7f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b6001600160a01b03811615806200017857506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200014857600080fd5b505afa1580156200015d573d6000803e3d6000fd5b505050506040513d60208110156200017457600080fd5b5051115b620001e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f494e56414c49445f544f4b454e00000000000000000000000000000000000000604482015290519081900360640190fd5b6067805460ff60a01b196001600160a01b039093166001600160a01b031990911617919091167401000000000000000000000000000000000000000017905563bbf81e008311156200029757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f59454152530000000000000000604482015290519081900360640190fd5b60688054336001600160a01b031991821617909155606d80549091166001600160a01b039590951694909417909355606991909155606a55606b558051620002e790607190602084019062000565565b506200031c7f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b50620003517f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b036200037316565b62000367866200044260201b620030891760201c565b50505050505062000607565b7fffffffff0000000000000000000000000000000000000000000000000000000080821614156200040557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152602081905260409020805460ff19166001179055565b600154610100900460ff1680620004675750620004676001600160e01b036200055e16565b8062000476575060015460ff16155b620004cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018062004ac3602e913960400191505060405180910390fd5b600154610100900460ff16158015620004f8576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156200055a576001805461ff00191690555b5050565b303b155b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005a857805160ff1916838001178555620005d8565b82800160010185558215620005d8579182015b82811115620005d8578251825591602001919060010190620005bb565b50620005e6929150620005ea565b5090565b6200056291905b80821115620005e65760008155600101620005f1565b6144ac80620006176000396000f3fe6080604052600436106103e45760003560e01c80636d8ea5b4116102085780639d76ea5811610118578063c4d66de8116100ab578063e985e9c51161007a578063e985e9c5146113c6578063f2fde38b14611401578063f6e4641f14611434578063f8b2cb4f1461145a578063f8faf9421461148d576103e4565b8063c4d66de814611328578063c87b56dd1461135b578063d1bbd49c14611385578063d42cfc41146113b1576103e4565b8063abdf82ce116100e7578063abdf82ce14611191578063b88d4fde146111c4578063b8968bb414611288578063c1c98d0314611313576103e4565b80639d76ea58146110f95780639f98d3cb1461110e578063a22cb46514611141578063a843a4e71461117c576103e4565b80638d0361fc1161019b57806393fd18441161016a57806393fd18441461102a57806395d89b411461103f578063970aaeb714611054578063994a8a71146110875780639b3f0b17146110c0576103e4565b80638d0361fc14610fb05780638da5cb5b14610feb5780638f32d59b146110005780638f98ce8f14611015576103e4565b806374b6c106116101d757806374b6c10614610e22578063782a4ade14610e375780637c7c425314610eb257806383cb0fa914610f7d576103e4565b80636d8ea5b414610d7957806370a0823114610dac57806370efb77014610ddf578063715018a614610e0d576103e4565b806323b872dd1161030357806342842e0e1161029657806352d6a8e41161026557806352d6a8e414610c59578063550ef3a814610c8c5780635fdb97e114610d07578063627cdcb914610d3a5780636352211e14610d4f576103e4565b806342842e0e1461098657806345e965cd146109bc5780634bc5a13514610bfc5780634c7a12a014610c2f576103e4565b806339f46986116102d257806339f46986146108fc5780633ba70e311461092c5780633d3359cb146109415780634136aa3514610971576103e4565b806323b872dd1461080c5780632e1a7d4d1461084257806330176e131461086c57806338af3eed146108e7576103e4565b80630f15023b1161037b578063150b7a021161034a578063150b7a02146106ca57806318160ddd146107b85780631f1ec029146107cd5780632009dc65146107f7576103e4565b80630f15023b1461060b57806310803b721461062057806310e56973146106a057806311a4c03a146106b5576103e4565b8063095ea7b3116103b7578063095ea7b31461056e5780630aaffd2a1461059c5780630c79130f146105cf5780630ed3e2cc146105f6576103e4565b806301ffc9a71461042c578063025e7c271461047457806306fdde03146104ba578063081812fc14610544575b3480156103f057600080fd5b506040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f46414c4c4241434b60a81b604482015290519081900360640190fd5b34801561043857600080fd5b506104606004803603602081101561044f57600080fd5b50356001600160e01b031916611508565b604080519115158252519081900360200190f35b34801561048057600080fd5b5061049e6004803603602081101561049757600080fd5b503561152b565b604080516001600160a01b039092168252519081900360200190f35b3480156104c657600080fd5b506104cf611552565b6040805160208082528351818301528351919283929083019185019080838360005b838110156105095781810151838201526020016104f1565b50505050905090810190601f1680156105365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561055057600080fd5b5061049e6004803603602081101561056757600080fd5b50356115e9565b61059a6004803603604081101561058457600080fd5b506001600160a01b0381351690602001356115fa565b005b3480156105a857600080fd5b5061059a600480360360208110156105bf57600080fd5b50356001600160a01b0316611787565b3480156105db57600080fd5b506105e4611878565b60408051918252519081900360200190f35b34801561060257600080fd5b506105e461187e565b34801561061757600080fd5b5061049e611884565b34801561062c57600080fd5b506106506004803603604081101561064357600080fd5b5080359060200135611893565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561068c578181015183820152602001610674565b505050509050019250505060405180910390f35b3480156106ac57600080fd5b506105e46119ab565b3480156106c157600080fd5b506105e46119b1565b3480156106d657600080fd5b5061079b600480360360808110156106ed57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561072757600080fd5b82018360208201111561073957600080fd5b803590602001918460018302840111600160201b8311171561075a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506119b7945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156107c457600080fd5b506105e46119c8565b3480156107d957600080fd5b5061059a600480360360208110156107f057600080fd5b50356119ce565b34801561080357600080fd5b5061059a611a76565b61059a6004803603606081101561082257600080fd5b506001600160a01b03813581169160208101359091169060400135611a81565b34801561084e57600080fd5b5061059a6004803603602081101561086557600080fd5b5035611ccb565b34801561087857600080fd5b5061059a6004803603602081101561088f57600080fd5b810190602081018135600160201b8111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460018302840111600160201b831117156108dc57600080fd5b509092509050611e1f565b3480156108f357600080fd5b5061049e611e3c565b34801561090857600080fd5b5061059a6004803603604081101561091f57600080fd5b5080359060200135611e4b565b34801561093857600080fd5b506105e4611ef5565b34801561094d57600080fd5b5061059a6004803603604081101561096457600080fd5b5080359060200135611efb565b34801561097d57600080fd5b50610460611fa5565b61059a6004803603606081101561099c57600080fd5b506001600160a01b03813581169160208101359091169060400135611fb5565b3480156109c857600080fd5b506104cf600480360360808110156109df57600080fd5b810190602081018135600160201b8111156109f957600080fd5b820183602082011115610a0b57600080fd5b803590602001918460018302840111600160201b83111715610a2c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a7e57600080fd5b820183602082011115610a9057600080fd5b803590602001918460018302840111600160201b83111715610ab157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b0357600080fd5b820183602082011115610b1557600080fd5b803590602001918460018302840111600160201b83111715610b3657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b8857600080fd5b820183602082011115610b9a57600080fd5b803590602001918460018302840111600160201b83111715610bbb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fd0945050505050565b348015610c0857600080fd5b506105e460048036036020811015610c1f57600080fd5b50356001600160a01b0316612185565b348015610c3b57600080fd5b506104cf60048036036020811015610c5257600080fd5b5035612197565b348015610c6557600080fd5b506105e460048036036020811015610c7c57600080fd5b50356001600160a01b031661225b565b348015610c9857600080fd5b5061059a60048036036020811015610caf57600080fd5b810190602081018135600160201b811115610cc957600080fd5b820183602082011115610cdb57600080fd5b803590602001918460018302840111600160201b83111715610cfc57600080fd5b509092509050612266565b348015610d1357600080fd5b506104cf60048036036020811015610d2a57600080fd5b50356001600160a01b0316612283565b348015610d4657600080fd5b5061059a6123ff565b348015610d5b57600080fd5b5061049e60048036036020811015610d7257600080fd5b5035612417565b348015610d8557600080fd5b5061046060048036036020811015610d9c57600080fd5b50356001600160a01b031661248d565b348015610db857600080fd5b506105e460048036036020811015610dcf57600080fd5b50356001600160a01b03166124ad565b61059a60048036036040811015610df557600080fd5b506001600160a01b038135811691602001351661251c565b348015610e1957600080fd5b5061059a6125c1565b348015610e2e57600080fd5b506105e461261c565b348015610e4357600080fd5b5061059a60048036036020811015610e5a57600080fd5b810190602081018135600160201b811115610e7457600080fd5b820183602082011115610e8657600080fd5b803590602001918460018302840111600160201b83111715610ea757600080fd5b509092509050612622565b348015610ebe57600080fd5b5061059a60048036036040811015610ed557600080fd5b810190602081018135600160201b811115610eef57600080fd5b820183602082011115610f0157600080fd5b803590602001918460208302840111600160201b83111715610f2257600080fd5b919390929091602081019035600160201b811115610f3f57600080fd5b820183602082011115610f5157600080fd5b803590602001918460208302840111600160201b83111715610f7257600080fd5b5090925090506126a4565b348015610f8957600080fd5b506105e460048036036020811015610fa057600080fd5b50356001600160a01b0316612706565b348015610fbc57600080fd5b506105e460048036036040811015610fd357600080fd5b506001600160a01b03813581169160200135166127c9565b348015610ff757600080fd5b5061049e61282d565b34801561100c57600080fd5b5061046061283c565b34801561102157600080fd5b506105e461284d565b34801561103657600080fd5b506105e4612853565b34801561104b57600080fd5b506104cf612859565b34801561106057600080fd5b506105e46004803603602081101561107757600080fd5b50356001600160a01b03166129e4565b34801561109357600080fd5b50610460600480360360408110156110aa57600080fd5b50803590602001356001600160a01b0316612a4e565b3480156110cc57600080fd5b5061059a600480360360408110156110e357600080fd5b506001600160a01b038135169060200135612a6f565b34801561110557600080fd5b5061049e612a8e565b34801561111a57600080fd5b5061059a6004803603602081101561113157600080fd5b50356001600160a01b0316612a9d565b34801561114d57600080fd5b5061059a6004803603604081101561116457600080fd5b506001600160a01b0381351690602001351515612b54565b34801561118857600080fd5b5061059a612c5f565b34801561119d57600080fd5b506105e4600480360360208110156111b457600080fd5b50356001600160a01b0316612d0b565b61059a600480360360808110156111da57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561121457600080fd5b82018360208201111561122657600080fd5b803590602001918460018302840111600160201b8311171561124757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d90945050505050565b34801561129457600080fd5b5061059a600480360360408110156112ab57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156112d557600080fd5b8201836020820111156112e757600080fd5b803590602001918460018302840111600160201b8311171561130857600080fd5b509092509050612f1e565b34801561131f57600080fd5b5061059a612ff0565b34801561133457600080fd5b5061059a6004803603602081101561134b57600080fd5b50356001600160a01b0316613089565b34801561136757600080fd5b506104cf6004803603602081101561137e57600080fd5b5035613179565b34801561139157600080fd5b5061139a613391565b6040805161ffff9092168252519081900360200190f35b3480156113bd57600080fd5b506105e4613396565b3480156113d257600080fd5b50610460600480360360408110156113e957600080fd5b506001600160a01b038135811691602001351661339c565b34801561140d57600080fd5b5061059a6004803603602081101561142457600080fd5b50356001600160a01b03166133ca565b61059a6004803603602081101561144a57600080fd5b50356001600160a01b03166133e7565b34801561146657600080fd5b506105e46004803603602081101561147d57600080fd5b50356001600160a01b0316613442565b34801561149957600080fd5b5061059a600480360360408110156114b057600080fd5b810190602081018135600160201b8111156114ca57600080fd5b8201836020820111156114dc57600080fd5b803590602001918460208302840111600160201b831117156114fd57600080fd5b9193509150356134e6565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b6070818154811061153857fe5b6000918252602090912001546001600160a01b0316905081565b60718054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505090505b90565b60006115f482613535565b92915050565b606754600160a01b900460ff1661164a576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806116558133612a4e565b806116655750611665813361358f565b8061167d575061167d61167782612417565b3361339c565b6116cb576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b336001600160a01b0384161415611718576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b600082815260746020526040902080546001600160a01b0319166001600160a01b038516908117909155829061174d82612417565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b61178f61282d565b6001600160a01b0316336001600160a01b031614806117b85750606d546001600160a01b031633145b611809576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6001600160a01b038116611856576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606d80546001600160a01b0319166001600160a01b0392909216919091179055565b60795481565b60785481565b6068546001600160a01b031681565b6070546060906118e0576040805162461bcd60e51b81526020600482015260136024820152724e4f5f4f55545354414e44494e475f4b45595360681b604482015290519081900360640190fd5b607054829084820290600090828401111561190357506070548181039250611908565b508082015b606083604051908082528060200260200182016040528015611934578160200160208202803883390190505b5090506000835b8381101561199e576070818154811061195057fe5b9060005260206000200160009054906101000a90046001600160a01b031683838151811061197a57fe5b6001600160a01b03909216602092830291909101909101526001918201910161193b565b5090979650505050505050565b606a5481565b60695481565b630a85bd0160e11b5b949350505050565b606c5490565b6119d661283c565b6119df57600080fd5b606754600160a01b900460ff16611a2f576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b606a805490829055604080518281526020810184905281517f8aa4fa52648a6d15edce8a179c792c86f3719d0cc3c572cf90f91948f0f2cb68929181900390910190a15050565b611a7f336135b0565b565b606754600160a01b900460ff16611ad1576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b82611adb8161248d565b611b1c576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b81611b278133612a4e565b80611b375750611b37813361358f565b80611b495750611b4961167782612417565b611b97576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b6001600160a01b038416611be4576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b611bf5611bf086612706565b613625565b6000611c0086613842565b90506000611c0d86613842565b6001810154815491925090611c2c578254808355611c2c90889061385c565b428111611c50576001808401549083015582548255611c4b878761385c565b611c6d565b6001830154611c679042830363ffffffff6138e316565b60018301555b42600184015560008355611c8086613944565b85876001600160a01b0316896001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050505050565b611cd361282d565b6001600160a01b0316336001600160a01b03161480611cfc5750606d546001600160a01b031633145b611d4d576040805162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f4c4f434b5f4f574e45525f4f525f42454e45464943494152590000604482015290519081900360640190fd5b6000611d5830613442565b90506000821580611d6857508183115b15611dbc5760008211611db5576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b5080611dbf565b50815b606d546040805183815290516001600160a01b039092169133917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398919081900360200190a3606d54611e1a906001600160a01b03168261397f565b505050565b611e2761283c565b611e3057600080fd5b611e1a60738383614390565b606d546001600160a01b031681565b611e5361283c565b611e5c57600080fd5b80611e9d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60785460795460408051928352602083019190915281810184905260608201839052517fa7d13855fe99b8c8b2780f36ff9e06133878b66a664a951b2375fe2296cc00089181900360800190a1607891909155607955565b606c5481565b611f0361283c565b611f0c57600080fd5b80611f4d576040805162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f5241544560a01b604482015290519081900360640190fd5b60765460775460408051928352602083019190915281810184905260608201839052517ff0cc3b8bd450a20cce7720453e064b35cf490baa5d53c7c6ef8b2e1b02898a7d9181900360800190a1607691909155607755565b606754600160a01b900460ff1681565b611e1a83838360405180602001604052806000815250612d90565b606080859050606085905060608590506060859050606081518351855187510101016040519080825280601f01601f19166020018201604052801561201c576020820181803883390190505b509050806000805b87518110156120755787818151811061203957fe5b602001015160f81c60f81b83838060010194508151811061205657fe5b60200101906001600160f81b031916908160001a905350600101612024565b5060005b86518110156120ca5786818151811061208e57fe5b602001015160f81c60f81b8383806001019450815181106120ab57fe5b60200101906001600160f81b031916908160001a905350600101612079565b5060005b855181101561211f578581815181106120e357fe5b602001015160f81c60f81b83838060010194508151811061210057fe5b60200101906001600160f81b031916908160001a9053506001016120ce565b5060005b84518110156121745784818151811061213857fe5b602001015160f81c60f81b83838060010194508151811061215557fe5b60200101906001600160f81b031916908160001a905350600101612123565b50909b9a5050505050505050505050565b607a6020526000908152604090205481565b606081806121be5750506040805180820190915260018152600360fc1b6020820152611526565b8260005b81156121d657600101600a820491506121c2565b6060816040519080825280601f01601f191660200182016040528015612203576020820181803883390190505b50905060001982015b841561225157600a850660300160f81b8282806001900393508151811061222f57fe5b60200101906001600160f81b031916908160001a905350600a8504945061220c565b5095945050505050565b60006115f482613b8b565b61226e61283c565b61227757600080fd5b611e1a60718383614390565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b03851692918491602082018180388339019050509050600360fc1b816000815181106122e757fe5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061231057fe5b60200101906001600160f81b031916908160001a90535060005b60148110156123f6578260048583600c016020811061234557fe5b1a60f81b6001600160f81b031916901c60f81c60ff168151811061236557fe5b602001015160f81c60f81b82826002026002018151811061238257fe5b60200101906001600160f81b031916908160001a905350828482600c01602081106123a957fe5b825191901a600f169081106123ba57fe5b602001015160f81c60f81b8282600202600301815181106123d757fe5b60200101906001600160f81b031916908160001a90535060010161232a565b50949350505050565b336000908152607a6020526040902080546001019055565b6000818152606f602052604081205482906001600160a01b0316612470576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b50506000908152606f60205260409020546001600160a01b031690565b6001600160a01b03166000908152606e6020526040902060010154421090565b60006001600160a01b0382166124fc576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6125058261248d565b612510576000612513565b60015b60ff1692915050565b606754600160a01b900460ff1661256c576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b806125768161248d565b6125b7576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b611e1a8383613c6a565b6125c961283c565b6125d257600080fd5b6034546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603480546001600160a01b0319169055565b606b5481565b61262a61283c565b61263357600080fd5b61263f60728383614390565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb97828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6126ac61283c565b6126b557600080fd5b60005b838110156126ff576126f78585838181106126cf57fe5b905060200201356001600160a01b03168484848181106126eb57fe5b90506020020135613f35565b6001016126b8565b5050505050565b6000816127128161248d565b612753576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b600061275e84613842565b905060004282600101540390506000606954821061277f5750606a546127a0565b606954606a54612795908463ffffffff61403516565b8161279c57fe5b0490505b6077546076546127b790839063ffffffff61403516565b816127be57fe5b049695505050505050565b6001600160a01b03919091166000908152607a602090815260409182902054825130606090811b82850152603482019290925293901b6bffffffffffffffffffffffff19166054840152815180840360480181526068909301909152815191012090565b6034546001600160a01b031690565b6034546001600160a01b0316331490565b60765481565b60705490565b6072546060906002600019610100600184161502019091160461295257606860009054906101000a90046001600160a01b03166001600160a01b03166335a750de6040518163ffffffff1660e01b815260040160006040518083038186803b1580156128c457600080fd5b505afa1580156128d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561290157600080fd5b810190808051600160201b81111561291857600080fd5b8201602081018481111561292b57600080fd5b8151600160201b81118282018710171561294457600080fd5b509094506115e69350505050565b6072805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156129d85780601f106129ad576101008083540402835291602001916129d8565b820191906000526020600020905b8154815290600101906020018083116129bb57829003601f168201915b505050505090506115e6565b6000816129f08161248d565b612a31576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090205490565b6000918252606f6020526040909120546001600160a01b0391821691161490565b612a7761283c565b612a8057600080fd5b612a8a8282613f35565b5050565b6067546001600160a01b031681565b612aa561283c565b612aae57600080fd5b80612ab88161248d565b612af9576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152606e602090815260409182902042600182015580548351908152925190927f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79592908290030190a1505050565b606754600160a01b900460ff16612ba4576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6001600160a01b038216331415612bf1576040805162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b604482015290519081900360640190fd5b3360008181526075602090815260408083206001600160a01b03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b612c6761283c565b612c7057600080fd5b606754600160a01b900460ff1615612cbf576040805162461bcd60e51b815260206004820152600d60248201526c111254d050931157d1925494d5609a1b604482015290519081900360640190fd5b6040805130318152905133917fa053f2a7eceda47dde76e5939c5adf7b771e665fc84c8ef6feffc290a1eb1feb919081900360200190a2612d0833612d0330613442565b61397f565b33ff5b6001600160a01b0381166000908152606e60205260408120600101548290612d70576040805162461bcd60e51b81526020600482015260136024820152724841535f4e455645525f4f574e45445f4b455960681b604482015290519081900360640190fd5b50506001600160a01b03166000908152606e602052604090206001015490565b606754600160a01b900460ff16612de0576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b81612deb8133612a4e565b80612dfb5750612dfb813361358f565b80612e0d5750612e0d61167782612417565b612e5b576040805162461bcd60e51b815260206004820152601a60248201527913d3931657d2d15657d3d5d3915497d3d497d054141493d5915160321b604482015290519081900360640190fd5b612e6483612417565b612e6d8161248d565b612eae576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b612eb9868686611a81565b612ec58686868661408e565b612f16576040805162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f5245434549564552000000604482015290519081900360640190fd5b505050505050565b826001600160a01b0316612f79612f3d612f3886336127c9565b6141c1565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061421292505050565b6001600160a01b031614612fc8576040805162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b604482015290519081900360640190fd5b6001600160a01b0383166000908152607a6020526040902080546001019055611e1a836135b0565b612ff861283c565b61300157600080fd5b606754600160a01b900460ff16613051576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a16067805460ff60a01b19169055565b600154610100900460ff16806130a257506130a2614300565b806130b0575060015460ff16155b6130eb5760405162461bcd60e51b815260040180806020018281038252602e81526020018061444a602e913960400191505060405180910390fd5b600154610100900460ff16158015613115576001805460ff1961ff00199091166101001716811790555b603480546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015612a8a576001805461ff00191690555050565b6000818152606f602052604090205460609082906001600160a01b03166131d5576040805162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b604482015290519081900360640190fd5b607354606090600260001961010060018416150201909116046132ce57606860009054906101000a90046001600160a01b03166001600160a01b0316637ff94bb26040518163ffffffff1660e01b815260040160006040518083038186803b15801561324057600080fd5b505afa158015613254573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561327d57600080fd5b810190808051600160201b81111561329457600080fd5b820160208101848111156132a757600080fd5b8151600160201b8111828201871017156132c057600080fd5b5090945061335c9350505050565b6073805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156133545780601f1061332957610100808354040283529160200191613354565b820191906000526020600020905b81548152906001019060200180831161333757829003601f168201915b505050505090505b6119c08161336930612283565b604051806040016040528060018152602001602f60f81b81525061338c88612197565b611fd0565b600490565b60775481565b6001600160a01b03918216600090815260756020908152604080832093909416825291909152205460ff1690565b6133d261283c565b6133db57600080fd5b6133e481614306565b50565b606754600160a01b900460ff16613437576040805162461bcd60e51b815260206004820152600f60248201526e1313d0d2d7d11154149150d0551151608a1b604482015290519081900360640190fd5b6133e4816000613c6a565b6067546000906001600160a01b031661346657506001600160a01b03811631611526565b606754604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b1580156134b357600080fd5b505afa1580156134c7573d6000803e3d6000fd5b505050506040513d60208110156134dd57600080fd5b50519050611526565b6134ee61283c565b6134f757600080fd5b60005b8281101561352f5761352784848381811061351157fe5b905060200201356001600160a01b031683613f35565b6001016134fa565b50505050565b6000818152607460205260408120546001600160a01b0316806115f4576040805162461bcd60e51b815260206004820152600d60248201526c1393d39157d054141493d59151609a1b604482015290519081900360640190fd5b600091825260746020526040909120546001600160a01b0391821691161490565b60006135bb82613842565b905060006135c883613b8b565b825460408051838152905192935033926001600160a01b03871692917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce528919081900360200190a44260018301558015611e1a57611e1a338261397f565b80156133e4576067546001600160a01b03166136885780341015613683576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b604482015290519081900360640190fd5b6133e4565b606754604080516370a0823160e01b815230600482015290516001600160a01b039092169160009183916370a0823191602480820192602092909190829003018186803b1580156136d857600080fd5b505afa1580156136ec573d6000803e3d6000fd5b505050506040513d602081101561370257600080fd5b5051604080516323b872dd60e01b81523360048201523060248201526044810186905290519192506001600160a01b038416916323b872dd916064808201926020929091908290030181600087803b15801561375d57600080fd5b505af1158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5050604080516370a0823160e01b8152306004820152905182916001600160a01b038516916370a0823191602480820192602092909190829003018186803b1580156137d257600080fd5b505afa1580156137e6573d6000803e3d6000fd5b505050506040513d60208110156137fc57600080fd5b505111611e1a576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b6001600160a01b03166000908152606e6020526040902090565b6000818152606f60205260409020546001600160a01b03838116911614612a8a5760708054600181019091557f8f6b23ffa15f0465e3176e15ca644cf24f86dc1312fe715484e3c4aead5eb78b0180546001600160a01b0384166001600160a01b031991821681179092556000838152606f60205260409020805490911690911790555050565b60008282018381101561393d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000818152607460205260409020546001600160a01b0316156133e457600090815260746020526040902080546001600160a01b0319169055565b8015612a8a576067546001600160a01b03166139d1576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156139cb573d6000803e3d6000fd5b50612a8a565b606754604080516370a0823160e01b81526001600160a01b0385811660048301529151919092169160009183916370a08231916024808301926020929190829003018186803b158015613a2357600080fd5b505afa158015613a37573d6000803e3d6000fd5b505050506040513d6020811015613a4d57600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0387811660048301526024820187905291519293509084169163a9059cbb916044808201926020929091908290030181600087803b158015613aa557600080fd5b505af1158015613ab9573d6000803e3d6000fd5b505050506040513d6020811015613acf57600080fd5b5050604080516370a0823160e01b81526001600160a01b038681166004830152915183928516916370a08231916024808301926020929190829003018186803b158015613b1b57600080fd5b505afa158015613b2f573d6000803e3d6000fd5b505050506040513d6020811015613b4557600080fd5b50511161352f576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b600081613b978161248d565b613bd8576040805162461bcd60e51b815260206004820152600d60248201526c12d15657d393d517d590531251609a1b604482015290519081900360640190fd5b6000613be384613842565b905060004282600101540390506069548110613c0357606a549350613c24565b606954606a54613c19908363ffffffff61403516565b81613c2057fe5b0493505b6000607954613c40607854606a5461403590919063ffffffff16565b81613c4757fe5b04905080851115613c5c578085039450613c61565b600094505b50505050919050565b606c54606b5411613cb2576040805162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b604482015290519081900360640190fd5b6001600160a01b038216613cff576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b606a5460685460408051630cb175e360e01b81526001600160a01b03868116600483015260248201859052825160009586959094921692630cb175e3926044808301939192829003018186803b158015613d5857600080fd5b505afa158015613d6c573d6000803e3d6000fd5b505050506040513d6040811015613d8257600080fd5b50805160209091015190935091508080841115613da157506000613da6565b508281035b6000613db187613842565b8054909150613dd157613dc381614375565b613dd187826000015461385c565b42816001015410613dfd576069546001820154613df39163ffffffff6138e316565b6001820155613e08565b606954420160018201555b8415613e7b5760685460408051633652466360e01b8152600481018890526024810187905290516001600160a01b039092169163365246639160448082019260009290919082900301818387803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b505050505b6068546040805163939d9f1f60e01b8152600481018590526001600160a01b0389811660248301529151919092169163939d9f1f91604480830192600092919082900301818387803b158015613ed057600080fd5b505af1158015613ee4573d6000803e3d6000fd5b5050606c546040519092506001600160a01b038a1691506000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4613f2c82613625565b50505050505050565b6001600160a01b038216613f82576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f4144445245535360881b604482015290519081900360640190fd5b6000613f8d83613842565b905080600101548211613fda576040805162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b604482015290519081900360640190fd5b613fe381614375565b613ff183826000015461385c565b6001810182905580546040516001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b600082614044575060006115f4565b8282028284828161405157fe5b041461393d5760405162461bcd60e51b81526004018080602001828103825260218152602001806144296021913960400191505060405180910390fd5b60006140a2846001600160a01b031661438a565b6140ae575060016119c0565b604051630a85bd0160e11b815233600482018181526001600160a01b03888116602485015260448401879052608060648501908152865160848601528651600095928a169463150b7a029490938c938b938b939260a4019060208501908083838e5b83811015614128578181015183820152602001614110565b50505050905090810190601f1680156141555780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561417757600080fd5b505af115801561418b573d6000803e3d6000fd5b505050506040513d60208110156141a157600080fd5b50516001600160e01b031916630a85bd0160e11b14915050949350505050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c8083019490945282518083039094018452605c909101909152815191012090565b60008151604114614225575060006115f4565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561426b57600093505050506115f4565b8060ff16601b1415801561428357508060ff16601c14155b1561429457600093505050506115f4565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa1580156142eb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b303b1590565b6001600160a01b03811661431957600080fd5b6034546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603480546001600160a01b0319166001600160a01b0392909216919091179055565b80546133e457606c8054600101908190559055565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106143d15782800160ff198235161785556143fe565b828001600101855582156143fe579182015b828111156143fe5782358255916020019190600101906143e3565b5061440a92915061440e565b5090565b6115e691905b8082111561440a576000815560010161441456fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7230582047f15e51181351647a87d6980e0f8f20a1f88485a060e1fd9ce02eb8828eb7b464736f6c63430005090032436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a723058206480e8af51e7228bcb8607a89ad85724811d26200329bad052bf9dacde65861c64736f6c63430005090032", - "compiler": { - "name": "solc", - "version": "0.5.9+commit.e560f70d.Emscripten.clang" - }, - "schemaVersion": "3.0.10", - "updatedAt": "2019-06-05T17:55:27.566Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV5.json b/packages/contracts/src/abis/Unlock/UnlockV5.json deleted file mode 100644 index eb5431b16ff..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV5.json +++ /dev/null @@ -1,482 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "publicLockAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenSymbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenURI", - "type": "string" - } - ], - "name": "ConfigUnlock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "grossNetworkProduct", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiscountGranted", - "type": "uint256" - } - ], - "name": "ResetTrackedValue", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "globalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "internalType": "bool", - "name": "deployed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "totalSales", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "uniswapExchanges", - "outputs": [ - { - "internalType": "contract IUniswap", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - }, - { - "internalType": "bytes12", - "name": "_salt", - "type": "bytes12" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_purchaser", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "internalType": "uint256", - "name": "discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_publicLockAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "_URI", - "type": "string" - } - ], - "name": "configUnlock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_exchangeAddress", - "type": "address" - } - ], - "name": "setExchange", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_grossNetworkProduct", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalDiscountGranted", - "type": "uint256" - } - ], - "name": "resetTrackedValue", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x60806040526112b0806100136000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063963a9478116100ad578063cbdd9d8611610071578063cbdd9d861461047b578063cec410521461054d578063d6e9e80314610555578063f2fde38b1461055d578063f8328991146105835761012c565b8063963a94781461036d578063a082eb0e14610390578063a998e9fb146103aa578063bb60160e14610427578063c4d66de8146104555761012c565b8063715018a6116100f4578063715018a6146102d357806388fa91f9146102db5780638da5cb5b1461031d5780638f32d59b14610325578063939d9f1f146103415761012c565b80630cb175e31461013157806336524663146101765780634220bd461461019b57806342d92106146101ba5780635de9a1371461028d575b600080fd5b61015d6004803603604081101561014757600080fd5b506001600160a01b03813516906020013561058b565b6040805192835260208301919091528051918290030190f35b6101996004803603604081101561018c57600080fd5b5080359060200135610594565b005b6101a36105f2565b6040805161ffff9092168252519081900360200190f35b610199600480360360c08110156101d057600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561020c57600080fd5b82018360208201111561021e57600080fd5b8035906020019184600183028401116401000000008311171561024057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506105f89050565b6102b3600480360360208110156102a357600080fd5b50356001600160a01b03166107fc565b604080519315158452602084019290925282820152519081900360600190f35b610199610821565b610301600480360360208110156102f157600080fd5b50356001600160a01b03166108b2565b604080516001600160a01b039092168252519081900360200190f35b6103016108cd565b61032d6108dc565b604080519115158252519081900360200190f35b6101996004803603604081101561035757600080fd5b50803590602001356001600160a01b0316610902565b6101996004803603604081101561038357600080fd5b5080359060200135610aa1565b610398610b31565b60408051918252519081900360200190f35b6103b2610b37565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103ec5781810151838201526020016103d4565b50505050905090810190601f1680156104195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101996004803603604081101561043d57600080fd5b506001600160a01b0381358116916020013516610bc5565b6101996004803603602081101561046b57600080fd5b50356001600160a01b0316610c3a565b6101996004803603606081101561049157600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156104bc57600080fd5b8201836020820111156104ce57600080fd5b803590602001918460018302840111640100000000831117156104f057600080fd5b91939092909160208101903564010000000081111561050e57600080fd5b82018360208201111561052057600080fd5b8035906020019184600183028401116401000000008311171561054257600080fd5b509092509050610ce5565b6103b2610e0e565b610398610e69565b6101996004803603602081101561057357600080fd5b50356001600160a01b0316610e6f565b610301610ec2565b50600091829150565b3360009081526068602052604090205460ff166105e5576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b60055b90565b606b546001600160a01b031661064d576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b54600090610666906001600160a01b031683610ed1565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561070b5781810151838201526020016106f3565b50505050905090810190601f1680156107385780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561075c57600080fd5b505af1158015610770573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6108296108dc565b610868576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b03166108f3610fd3565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610953576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156105ee57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801561099557600080fd5b505afa1580156109a9573d6000803e3d6000fd5b505050506040513d60208110156109bf57600080fd5b505190506001600160a01b03811615610a77576001600160a01b038082166000908152606c6020526040902054168015610a6c57806001600160a01b03166395b68fe7866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610a3957600080fd5b505af1158015610a4d573d6000803e3d6000fd5b505050506040513d6020811015610a6357600080fd5b50519250610a71565b600092505b50610a7b565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610aa96108dc565b610ae8576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bbd5780601f10610b9257610100808354040283529160200191610bbd565b820191906000526020600020905b815481529060010190602001808311610ba057829003601f168201915b505050505081565b610bcd6108dc565b610c0c576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610c535750610c53610fd7565b80610c61575060005460ff16155b610c9c5760405162461bcd60e51b815260040180806020018281038252602e81526020018061124e602e913960400191505060405180910390fd5b600054610100900460ff16158015610cc7576000805460ff1961ff0019909116610100171660011790555b610cd082610fdd565b80156105ee576000805461ff00191690555050565b610ced6108dc565b610d2c576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b606b80546001600160a01b0319166001600160a01b038716179055610d53606a858561116f565b50610d606069838361116f565b507fcd64a32e52b6b3ef25429757f08a77c9b72b7184c121b57603db7248c3b0b59c858585858560405180866001600160a01b03166001600160a01b0316815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a15050505050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bbd5780601f10610b9257610100808354040283529160200191610bbd565b60665481565b610e776108dc565b610eb6576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b610ebf816110ce565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b60008114610f6a5760009350610f79565b6101008301516037846000f593505b5050506001600160a01b038116610fcd576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff1680610ff65750610ff6610fd7565b80611004575060005460ff16155b61103f5760405162461bcd60e51b815260040180806020018281038252602e81526020018061124e602e913960400191505060405180910390fd5b600054610100900460ff1615801561106a576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156105ee576000805461ff00191690555050565b6001600160a01b0381166111135760405162461bcd60e51b81526004018080602001828103825260268152602001806112086026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106111b05782800160ff198235161785556111dd565b828001600101855582156111dd579182015b828111156111dd5782358255916020019190600101906111c2565b506111e99291506111ed565b5090565b6105f591905b808211156111e957600081556001016111f356fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820dad4a5e4fe7e4a80aaf3a036dc78e5e4c123f2301d9514e0f15a63efa505e15e64736f6c634300050c0032", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063963a9478116100ad578063cbdd9d8611610071578063cbdd9d861461047b578063cec410521461054d578063d6e9e80314610555578063f2fde38b1461055d578063f8328991146105835761012c565b8063963a94781461036d578063a082eb0e14610390578063a998e9fb146103aa578063bb60160e14610427578063c4d66de8146104555761012c565b8063715018a6116100f4578063715018a6146102d357806388fa91f9146102db5780638da5cb5b1461031d5780638f32d59b14610325578063939d9f1f146103415761012c565b80630cb175e31461013157806336524663146101765780634220bd461461019b57806342d92106146101ba5780635de9a1371461028d575b600080fd5b61015d6004803603604081101561014757600080fd5b506001600160a01b03813516906020013561058b565b6040805192835260208301919091528051918290030190f35b6101996004803603604081101561018c57600080fd5b5080359060200135610594565b005b6101a36105f2565b6040805161ffff9092168252519081900360200190f35b610199600480360360c08110156101d057600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561020c57600080fd5b82018360208201111561021e57600080fd5b8035906020019184600183028401116401000000008311171561024057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506105f89050565b6102b3600480360360208110156102a357600080fd5b50356001600160a01b03166107fc565b604080519315158452602084019290925282820152519081900360600190f35b610199610821565b610301600480360360208110156102f157600080fd5b50356001600160a01b03166108b2565b604080516001600160a01b039092168252519081900360200190f35b6103016108cd565b61032d6108dc565b604080519115158252519081900360200190f35b6101996004803603604081101561035757600080fd5b50803590602001356001600160a01b0316610902565b6101996004803603604081101561038357600080fd5b5080359060200135610aa1565b610398610b31565b60408051918252519081900360200190f35b6103b2610b37565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103ec5781810151838201526020016103d4565b50505050905090810190601f1680156104195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101996004803603604081101561043d57600080fd5b506001600160a01b0381358116916020013516610bc5565b6101996004803603602081101561046b57600080fd5b50356001600160a01b0316610c3a565b6101996004803603606081101561049157600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156104bc57600080fd5b8201836020820111156104ce57600080fd5b803590602001918460018302840111640100000000831117156104f057600080fd5b91939092909160208101903564010000000081111561050e57600080fd5b82018360208201111561052057600080fd5b8035906020019184600183028401116401000000008311171561054257600080fd5b509092509050610ce5565b6103b2610e0e565b610398610e69565b6101996004803603602081101561057357600080fd5b50356001600160a01b0316610e6f565b610301610ec2565b50600091829150565b3360009081526068602052604090205460ff166105e5576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b60055b90565b606b546001600160a01b031661064d576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b54600090610666906001600160a01b031683610ed1565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561070b5781810151838201526020016106f3565b50505050905090810190601f1680156107385780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561075c57600080fd5b505af1158015610770573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6108296108dc565b610868576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b03166108f3610fd3565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610953576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156105ee57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801561099557600080fd5b505afa1580156109a9573d6000803e3d6000fd5b505050506040513d60208110156109bf57600080fd5b505190506001600160a01b03811615610a77576001600160a01b038082166000908152606c6020526040902054168015610a6c57806001600160a01b03166395b68fe7866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610a3957600080fd5b505af1158015610a4d573d6000803e3d6000fd5b505050506040513d6020811015610a6357600080fd5b50519250610a71565b600092505b50610a7b565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610aa96108dc565b610ae8576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bbd5780601f10610b9257610100808354040283529160200191610bbd565b820191906000526020600020905b815481529060010190602001808311610ba057829003601f168201915b505050505081565b610bcd6108dc565b610c0c576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610c535750610c53610fd7565b80610c61575060005460ff16155b610c9c5760405162461bcd60e51b815260040180806020018281038252602e81526020018061124e602e913960400191505060405180910390fd5b600054610100900460ff16158015610cc7576000805460ff1961ff0019909116610100171660011790555b610cd082610fdd565b80156105ee576000805461ff00191690555050565b610ced6108dc565b610d2c576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b606b80546001600160a01b0319166001600160a01b038716179055610d53606a858561116f565b50610d606069838361116f565b507fcd64a32e52b6b3ef25429757f08a77c9b72b7184c121b57603db7248c3b0b59c858585858560405180866001600160a01b03166001600160a01b0316815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a15050505050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bbd5780601f10610b9257610100808354040283529160200191610bbd565b60665481565b610e776108dc565b610eb6576040805162461bcd60e51b8152602060048201819052602482015260008051602061122e833981519152604482015290519081900360640190fd5b610ebf816110ce565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b60008114610f6a5760009350610f79565b6101008301516037846000f593505b5050506001600160a01b038116610fcd576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff1680610ff65750610ff6610fd7565b80611004575060005460ff16155b61103f5760405162461bcd60e51b815260040180806020018281038252602e81526020018061124e602e913960400191505060405180910390fd5b600054610100900460ff1615801561106a576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156105ee576000805461ff00191690555050565b6001600160a01b0381166111135760405162461bcd60e51b81526004018080602001828103825260268152602001806112086026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106111b05782800160ff198235161785556111dd565b828001600101855582156111dd579182015b828111156111dd5782358255916020019190600101906111c2565b506111e99291506111ed565b5090565b6105f591905b808211156111e957600081556001016111f356fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820dad4a5e4fe7e4a80aaf3a036dc78e5e4c123f2301d9514e0f15a63efa505e15e64736f6c634300050c0032", - "compiler": { - "name": "solc", - "version": "0.5.12+commit.7709ece9.Emscripten.clang" - }, - "schemaVersion": "3.0.19", - "updatedAt": "2019-12-05T19:29:02.410Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV6.json b/packages/contracts/src/abis/Unlock/UnlockV6.json deleted file mode 100644 index 32d9f76db74..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV6.json +++ /dev/null @@ -1,482 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "publicLockAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenSymbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenURI", - "type": "string" - } - ], - "name": "ConfigUnlock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "grossNetworkProduct", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiscountGranted", - "type": "uint256" - } - ], - "name": "ResetTrackedValue", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "globalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "internalType": "bool", - "name": "deployed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "totalSales", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "uniswapExchanges", - "outputs": [ - { - "internalType": "contract IUniswap", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - }, - { - "internalType": "bytes12", - "name": "_salt", - "type": "bytes12" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_purchaser", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "internalType": "uint256", - "name": "discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_tokens", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_publicLockAddress", - "type": "address" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "_URI", - "type": "string" - } - ], - "name": "configUnlock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_exchangeAddress", - "type": "address" - } - ], - "name": "setExchange", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_grossNetworkProduct", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalDiscountGranted", - "type": "uint256" - } - ], - "name": "resetTrackedValue", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x6080604052611346806100136000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063963a9478116100ad578063cbdd9d8611610071578063cbdd9d861461047b578063cec410521461054d578063d6e9e80314610555578063f2fde38b1461055d578063f8328991146105835761012c565b8063963a94781461036d578063a082eb0e14610390578063a998e9fb146103aa578063bb60160e14610427578063c4d66de8146104555761012c565b8063715018a6116100f4578063715018a6146102d357806388fa91f9146102db5780638da5cb5b1461031d5780638f32d59b14610325578063939d9f1f146103415761012c565b80630cb175e31461013157806336524663146101765780634220bd461461019b57806342d92106146101ba5780635de9a1371461028d575b600080fd5b61015d6004803603604081101561014757600080fd5b506001600160a01b03813516906020013561058b565b6040805192835260208301919091528051918290030190f35b6101996004803603604081101561018c57600080fd5b5080359060200135610594565b005b6101a36105f2565b6040805161ffff9092168252519081900360200190f35b610199600480360360c08110156101d057600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561020c57600080fd5b82018360208201111561021e57600080fd5b8035906020019184600183028401116401000000008311171561024057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506105f89050565b6102b3600480360360208110156102a357600080fd5b50356001600160a01b0316610802565b604080519315158452602084019290925282820152519081900360600190f35b610199610827565b610301600480360360208110156102f157600080fd5b50356001600160a01b03166108b8565b604080516001600160a01b039092168252519081900360200190f35b6103016108d3565b61032d6108e2565b604080519115158252519081900360200190f35b6101996004803603604081101561035757600080fd5b50803590602001356001600160a01b0316610908565b6101996004803603604081101561038357600080fd5b5080359060200135610aa7565b610398610b37565b60408051918252519081900360200190f35b6103b2610b3d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103ec5781810151838201526020016103d4565b50505050905090810190601f1680156104195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101996004803603604081101561043d57600080fd5b506001600160a01b0381358116916020013516610bcb565b6101996004803603602081101561046b57600080fd5b50356001600160a01b0316610c40565b6101996004803603606081101561049157600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156104bc57600080fd5b8201836020820111156104ce57600080fd5b803590602001918460018302840111640100000000831117156104f057600080fd5b91939092909160208101903564010000000081111561050e57600080fd5b82018360208201111561052057600080fd5b8035906020019184600183028401116401000000008311171561054257600080fd5b509092509050610ceb565b6103b2610e68565b610398610ec3565b6101996004803603602081101561057357600080fd5b50356001600160a01b0316610ec9565b610301610f1c565b50600091829150565b3360009081526068602052604090205460ff166105e5576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b60065b90565b606b546001600160a01b031661064d576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b5460009061066c906001600160a01b03168363ffffffff610f2b16565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107115781810151838201526020016106f9565b50505050905090810190601f16801561073e5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561076257600080fd5b505af1158015610776573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b61082f6108e2565b61086e576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b03166108f961102d565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610959576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156105ee57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801561099b57600080fd5b505afa1580156109af573d6000803e3d6000fd5b505050506040513d60208110156109c557600080fd5b505190506001600160a01b03811615610a7d576001600160a01b038082166000908152606c6020526040902054168015610a7257806001600160a01b03166395b68fe7866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610a3f57600080fd5b505af1158015610a53573d6000803e3d6000fd5b505050506040513d6020811015610a6957600080fd5b50519250610a77565b600092505b50610a81565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610aaf6108e2565b610aee576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bc35780601f10610b9857610100808354040283529160200191610bc3565b820191906000526020600020905b815481529060010190602001808311610ba657829003601f168201915b505050505081565b610bd36108e2565b610c12576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610c595750610c59611031565b80610c67575060005460ff16155b610ca25760405162461bcd60e51b815260040180806020018281038252602e8152602001806112e4602e913960400191505060405180910390fd5b600054610100900460ff16158015610ccd576000805460ff1961ff0019909116610100171660011790555b610cd682611037565b80156105ee576000805461ff00191690555050565b610cf36108e2565b610d32576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b610d44856001600160a01b0316611128565b610d86576040805162461bcd60e51b815260206004820152600e60248201526d1393d517d057d0d3d395149050d560921b604482015290519081900360640190fd5b606b80546001600160a01b0319166001600160a01b038716179055610dad606a8585611205565b50610dba60698383611205565b507fcd64a32e52b6b3ef25429757f08a77c9b72b7184c121b57603db7248c3b0b59c858585858560405180866001600160a01b03166001600160a01b0316815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a15050505050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bc35780601f10610b9857610100808354040283529160200191610bc3565b60665481565b610ed16108e2565b610f10576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b610f1981611164565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b60008114610fc45760009350610fd3565b6101008301516037846000f593505b5050506001600160a01b038116611027576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff16806110505750611050611031565b8061105e575060005460ff16155b6110995760405162461bcd60e51b815260040180806020018281038252602e8152602001806112e4602e913960400191505060405180910390fd5b600054610100900460ff161580156110c4576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156105ee576000805461ff00191690555050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470811580159061115c5750808214155b949350505050565b6001600160a01b0381166111a95760405162461bcd60e51b815260040180806020018281038252602681526020018061129e6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106112465782800160ff19823516178555611273565b82800160010185558215611273579182015b82811115611273578235825591602001919060010190611258565b5061127f929150611283565b5090565b6105f591905b8082111561127f576000815560010161128956fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a723158209e34a1a348ffb3ad548b11d437d45726143464f5940bf756ceb1884d3969062a64736f6c634300050e0032", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063963a9478116100ad578063cbdd9d8611610071578063cbdd9d861461047b578063cec410521461054d578063d6e9e80314610555578063f2fde38b1461055d578063f8328991146105835761012c565b8063963a94781461036d578063a082eb0e14610390578063a998e9fb146103aa578063bb60160e14610427578063c4d66de8146104555761012c565b8063715018a6116100f4578063715018a6146102d357806388fa91f9146102db5780638da5cb5b1461031d5780638f32d59b14610325578063939d9f1f146103415761012c565b80630cb175e31461013157806336524663146101765780634220bd461461019b57806342d92106146101ba5780635de9a1371461028d575b600080fd5b61015d6004803603604081101561014757600080fd5b506001600160a01b03813516906020013561058b565b6040805192835260208301919091528051918290030190f35b6101996004803603604081101561018c57600080fd5b5080359060200135610594565b005b6101a36105f2565b6040805161ffff9092168252519081900360200190f35b610199600480360360c08110156101d057600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561020c57600080fd5b82018360208201111561021e57600080fd5b8035906020019184600183028401116401000000008311171561024057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506105f89050565b6102b3600480360360208110156102a357600080fd5b50356001600160a01b0316610802565b604080519315158452602084019290925282820152519081900360600190f35b610199610827565b610301600480360360208110156102f157600080fd5b50356001600160a01b03166108b8565b604080516001600160a01b039092168252519081900360200190f35b6103016108d3565b61032d6108e2565b604080519115158252519081900360200190f35b6101996004803603604081101561035757600080fd5b50803590602001356001600160a01b0316610908565b6101996004803603604081101561038357600080fd5b5080359060200135610aa7565b610398610b37565b60408051918252519081900360200190f35b6103b2610b3d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103ec5781810151838201526020016103d4565b50505050905090810190601f1680156104195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101996004803603604081101561043d57600080fd5b506001600160a01b0381358116916020013516610bcb565b6101996004803603602081101561046b57600080fd5b50356001600160a01b0316610c40565b6101996004803603606081101561049157600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156104bc57600080fd5b8201836020820111156104ce57600080fd5b803590602001918460018302840111640100000000831117156104f057600080fd5b91939092909160208101903564010000000081111561050e57600080fd5b82018360208201111561052057600080fd5b8035906020019184600183028401116401000000008311171561054257600080fd5b509092509050610ceb565b6103b2610e68565b610398610ec3565b6101996004803603602081101561057357600080fd5b50356001600160a01b0316610ec9565b610301610f1c565b50600091829150565b3360009081526068602052604090205460ff166105e5576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b60065b90565b606b546001600160a01b031661064d576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b5460009061066c906001600160a01b03168363ffffffff610f2b16565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107115781810151838201526020016106f9565b50505050905090810190601f16801561073e5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561076257600080fd5b505af1158015610776573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b61082f6108e2565b61086e576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b03166108f961102d565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610959576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156105ee57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801561099b57600080fd5b505afa1580156109af573d6000803e3d6000fd5b505050506040513d60208110156109c557600080fd5b505190506001600160a01b03811615610a7d576001600160a01b038082166000908152606c6020526040902054168015610a7257806001600160a01b03166395b68fe7866040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015610a3f57600080fd5b505af1158015610a53573d6000803e3d6000fd5b505050506040513d6020811015610a6957600080fd5b50519250610a77565b600092505b50610a81565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610aaf6108e2565b610aee576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bc35780601f10610b9857610100808354040283529160200191610bc3565b820191906000526020600020905b815481529060010190602001808311610ba657829003601f168201915b505050505081565b610bd36108e2565b610c12576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610c595750610c59611031565b80610c67575060005460ff16155b610ca25760405162461bcd60e51b815260040180806020018281038252602e8152602001806112e4602e913960400191505060405180910390fd5b600054610100900460ff16158015610ccd576000805460ff1961ff0019909116610100171660011790555b610cd682611037565b80156105ee576000805461ff00191690555050565b610cf36108e2565b610d32576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b610d44856001600160a01b0316611128565b610d86576040805162461bcd60e51b815260206004820152600e60248201526d1393d517d057d0d3d395149050d560921b604482015290519081900360640190fd5b606b80546001600160a01b0319166001600160a01b038716179055610dad606a8585611205565b50610dba60698383611205565b507fcd64a32e52b6b3ef25429757f08a77c9b72b7184c121b57603db7248c3b0b59c858585858560405180866001600160a01b03166001600160a01b0316815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f1916909201829003995090975050505050505050a15050505050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610bc35780601f10610b9857610100808354040283529160200191610bc3565b60665481565b610ed16108e2565b610f10576040805162461bcd60e51b815260206004820181905260248201526000805160206112c4833981519152604482015290519081900360640190fd5b610f1981611164565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b60008114610fc45760009350610fd3565b6101008301516037846000f593505b5050506001600160a01b038116611027576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff16806110505750611050611031565b8061105e575060005460ff16155b6110995760405162461bcd60e51b815260040180806020018281038252602e8152602001806112e4602e913960400191505060405180910390fd5b600054610100900460ff161580156110c4576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156105ee576000805461ff00191690555050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470811580159061115c5750808214155b949350505050565b6001600160a01b0381166111a95760405162461bcd60e51b815260040180806020018281038252602681526020018061129e6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106112465782800160ff19823516178555611273565b82800160010185558215611273579182015b82811115611273578235825591602001919060010190611258565b5061127f929150611283565b5090565b6105f591905b8082111561127f576000815560010161128956fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a723158209e34a1a348ffb3ad548b11d437d45726143464f5940bf756ceb1884d3969062a64736f6c634300050e0032", - "compiler": { - "name": "solc", - "version": "0.5.14+commit.01f1aaa4.Emscripten.clang" - }, - "schemaVersion": "3.0.20", - "updatedAt": "2020-01-15T23:36:50.902Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV7.json b/packages/contracts/src/abis/Unlock/UnlockV7.json deleted file mode 100644 index 58c025f4f0b..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV7.json +++ /dev/null @@ -1,529 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "globalTokenSymbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenURI", - "type": "string" - } - ], - "name": "ConfigUnlock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "grossNetworkProduct", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiscountGranted", - "type": "uint256" - } - ], - "name": "ResetTrackedValue", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "publicLockAddress", - "type": "address" - } - ], - "name": "SetLockTemplate", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "globalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "internalType": "bool", - "name": "deployed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "totalSales", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "uniswapExchanges", - "outputs": [ - { - "internalType": "contract IUniswapExchange", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_unlockOwner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - }, - { - "internalType": "bytes12", - "name": "_salt", - "type": "bytes12" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "internalType": "uint256", - "name": "discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "_URI", - "type": "string" - } - ], - "name": "configUnlock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "_publicLockAddress", - "type": "address" - } - ], - "name": "setLockTemplate", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_exchangeAddress", - "type": "address" - } - ], - "name": "setExchange", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_grossNetworkProduct", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalDiscountGranted", - "type": "uint256" - } - ], - "name": "resetTrackedValue", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x6080604052611533806100136000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c80638f32d59b116100c3578063c4d66de81161007c578063c4d66de814610548578063cec410521461056e578063d6e9e80314610576578063ef67fde61461057e578063f2fde38b146105a4578063f8328991146105ca5761014d565b80638f32d59b1461048d578063939d9f1f146104a9578063963a9478146104d5578063a082eb0e146104f8578063a998e9fb14610512578063bb60160e1461051a5761014d565b806348abfe061161011557806348abfe061461032b5780635de9a137146103ed578063715018a6146104335780637ff94bb21461043b57806388fa91f9146104435780638da5cb5b146104855761014d565b80630cb175e31461015257806335a750de1461019757806336524663146102145780634220bd461461023957806342d9210614610258575b600080fd5b61017e6004803603604081101561016857600080fd5b506001600160a01b0381351690602001356105d2565b6040805192835260208301919091528051918290030190f35b61019f6105db565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101d95781810151838201526020016101c1565b50505050905090810190601f1680156102065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102376004803603604081101561022a57600080fd5b5080359060200135610672565b005b6102416106d0565b6040805161ffff9092168252519081900360200190f35b610237600480360360c081101561026e57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460018302840111640100000000831117156102de57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506106d59050565b6102376004803603604081101561034157600080fd5b81019060208101813564010000000081111561035c57600080fd5b82018360208201111561036e57600080fd5b8035906020019184600183028401116401000000008311171561039057600080fd5b9193909290916020810190356401000000008111156103ae57600080fd5b8201836020820111156103c057600080fd5b803590602001918460018302840111640100000000831117156103e257600080fd5b5090925090506108df565b6104136004803603602081101561040357600080fd5b50356001600160a01b03166109d2565b604080519315158452602084019290925282820152519081900360600190f35b6102376109f7565b61019f610a88565b6104696004803603602081101561045957600080fd5b50356001600160a01b0316610ae9565b604080516001600160a01b039092168252519081900360200190f35b610469610b04565b610495610b13565b604080519115158252519081900360200190f35b610237600480360360408110156104bf57600080fd5b50803590602001356001600160a01b0316610b39565b610237600480360360408110156104eb57600080fd5b5080359060200135610cd6565b610500610d66565b60408051918252519081900360200190f35b61019f610d6c565b6102376004803603604081101561053057600080fd5b506001600160a01b0381358116916020013516610dfa565b6102376004803603602081101561055e57600080fd5b50356001600160a01b0316610e6f565b61019f610f1a565b610500610f75565b6102376004803603602081101561059457600080fd5b50356001600160a01b0316610f7b565b610237600480360360208110156105ba57600080fd5b50356001600160a01b03166110f2565b610469611145565b50600091829150565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106675780601f1061063c57610100808354040283529160200191610667565b820191906000526020600020905b81548152906001019060200180831161064a57829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff166106c3576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b600790565b606b546001600160a01b031661072a576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b54600090610749906001600160a01b03168363ffffffff61115416565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107ee5781810151838201526020016107d6565b50505050905090810190601f16801561081b5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561083f57600080fd5b505af1158015610853573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b6108e7610b13565b610926576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b610932606a85856113f2565b5061093f606983836113f2565b507f8aa531e44dec83ce65dbc6550e12e82a91729f35d427130d6b52aeb2c0acbe20848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6109ff610b13565b610a3e576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106675780601f1061063c57610100808354040283529160200191610667565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b0316610b2a611256565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610b8a576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156106cc57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610bcc57600080fd5b505afa158015610be0573d6000803e3d6000fd5b505050506040513d6020811015610bf657600080fd5b505190506001600160a01b03811615610cac576001600160a01b038082166000908152606c6020526040902054168015610ca157806001600160a01b03166395b68fe7866040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610c6e57600080fd5b505afa158015610c82573d6000803e3d6000fd5b505050506040513d6020811015610c9857600080fd5b50519250610ca6565b600092505b50610cb0565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610cde610b13565b610d1d576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610df25780601f10610dc757610100808354040283529160200191610df2565b820191906000526020600020905b815481529060010190602001808311610dd557829003601f168201915b505050505081565b610e02610b13565b610e41576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610e885750610e8861125a565b80610e96575060005460ff16155b610ed15760405162461bcd60e51b815260040180806020018281038252602e8152602001806114d1602e913960400191505060405180910390fd5b600054610100900460ff16158015610efc576000805460ff1961ff0019909116610100171660011790555b610f0582611260565b80156106cc576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610df25780601f10610dc757610100808354040283529160200191610df2565b60665481565b610f83610b13565b610fc2576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561103257600080fd5b505af1158015611046573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108557600080fd5b505af1158015611099573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b6110fa610b13565b611139576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b61114281611351565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146111ed57600093506111fc565b6101008301516037846000f593505b5050506001600160a01b038116611250576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff1680611279575061127961125a565b80611287575060005460ff16155b6112c25760405162461bcd60e51b815260040180806020018281038252602e8152602001806114d1602e913960400191505060405180910390fd5b600054610100900460ff161580156112ed576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156106cc576000805461ff00191690555050565b6001600160a01b0381166113965760405162461bcd60e51b815260040180806020018281038252602681526020018061148b6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114335782800160ff19823516178555611460565b82800160010185558215611460579182015b82811115611460578235825591602001919060010190611445565b5061146c929150611470565b5090565b61066f91905b8082111561146c576000815560010161147656fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7231582071e6790cc9e25671ad7d5298a655164f2f8797dc2b236e3b7f560292f64243e764736f6c63430005110032", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061014d5760003560e01c80638f32d59b116100c3578063c4d66de81161007c578063c4d66de814610548578063cec410521461056e578063d6e9e80314610576578063ef67fde61461057e578063f2fde38b146105a4578063f8328991146105ca5761014d565b80638f32d59b1461048d578063939d9f1f146104a9578063963a9478146104d5578063a082eb0e146104f8578063a998e9fb14610512578063bb60160e1461051a5761014d565b806348abfe061161011557806348abfe061461032b5780635de9a137146103ed578063715018a6146104335780637ff94bb21461043b57806388fa91f9146104435780638da5cb5b146104855761014d565b80630cb175e31461015257806335a750de1461019757806336524663146102145780634220bd461461023957806342d9210614610258575b600080fd5b61017e6004803603604081101561016857600080fd5b506001600160a01b0381351690602001356105d2565b6040805192835260208301919091528051918290030190f35b61019f6105db565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101d95781810151838201526020016101c1565b50505050905090810190601f1680156102065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102376004803603604081101561022a57600080fd5b5080359060200135610672565b005b6102416106d0565b6040805161ffff9092168252519081900360200190f35b610237600480360360c081101561026e57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a0810160808201356401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460018302840111640100000000831117156102de57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03191691506106d59050565b6102376004803603604081101561034157600080fd5b81019060208101813564010000000081111561035c57600080fd5b82018360208201111561036e57600080fd5b8035906020019184600183028401116401000000008311171561039057600080fd5b9193909290916020810190356401000000008111156103ae57600080fd5b8201836020820111156103c057600080fd5b803590602001918460018302840111640100000000831117156103e257600080fd5b5090925090506108df565b6104136004803603602081101561040357600080fd5b50356001600160a01b03166109d2565b604080519315158452602084019290925282820152519081900360600190f35b6102376109f7565b61019f610a88565b6104696004803603602081101561045957600080fd5b50356001600160a01b0316610ae9565b604080516001600160a01b039092168252519081900360200190f35b610469610b04565b610495610b13565b604080519115158252519081900360200190f35b610237600480360360408110156104bf57600080fd5b50803590602001356001600160a01b0316610b39565b610237600480360360408110156104eb57600080fd5b5080359060200135610cd6565b610500610d66565b60408051918252519081900360200190f35b61019f610d6c565b6102376004803603604081101561053057600080fd5b506001600160a01b0381358116916020013516610dfa565b6102376004803603602081101561055e57600080fd5b50356001600160a01b0316610e6f565b61019f610f1a565b610500610f75565b6102376004803603602081101561059457600080fd5b50356001600160a01b0316610f7b565b610237600480360360208110156105ba57600080fd5b50356001600160a01b03166110f2565b610469611145565b50600091829150565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106675780601f1061063c57610100808354040283529160200191610667565b820191906000526020600020905b81548152906001019060200180831161064a57829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff166106c3576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b600790565b606b546001600160a01b031661072a576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b606b54600090610749906001600160a01b03168363ffffffff61115416565b9050806001600160a01b0316636eadde433389898989896040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107ee5781810151838201526020016107d6565b50505050905090810190601f16801561081b5780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561083f57600080fd5b505af1158015610853573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a350505050505050565b6108e7610b13565b610926576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b610932606a85856113f2565b5061093f606983836113f2565b507f8aa531e44dec83ce65dbc6550e12e82a91729f35d427130d6b52aeb2c0acbe20848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6109ff610b13565b610a3e576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106675780601f1061063c57610100808354040283529160200191610667565b606c602052600090815260409020546001600160a01b031681565b6033546001600160a01b031690565b6033546000906001600160a01b0316610b2a611256565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610b8a576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b81156106cc57600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610bcc57600080fd5b505afa158015610be0573d6000803e3d6000fd5b505050506040513d6020811015610bf657600080fd5b505190506001600160a01b03811615610cac576001600160a01b038082166000908152606c6020526040902054168015610ca157806001600160a01b03166395b68fe7866040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610c6e57600080fd5b505afa158015610c82573d6000803e3d6000fd5b505050506040513d6020811015610c9857600080fd5b50519250610ca6565b600092505b50610cb0565b8391505b506066805482019055336000908152606860205260409020600101805490910190555050565b610cde610b13565b610d1d576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610df25780601f10610dc757610100808354040283529160200191610df2565b820191906000526020600020905b815481529060010190602001808311610dd557829003601f168201915b505050505081565b610e02610b13565b610e41576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b6001600160a01b039182166000908152606c6020526040902080546001600160a01b03191691909216179055565b600054610100900460ff1680610e885750610e8861125a565b80610e96575060005460ff16155b610ed15760405162461bcd60e51b815260040180806020018281038252602e8152602001806114d1602e913960400191505060405180910390fd5b600054610100900460ff16158015610efc576000805460ff1961ff0019909116610100171660011790555b610f0582611260565b80156106cc576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610df25780601f10610dc757610100808354040283529160200191610df2565b60665481565b610f83610b13565b610fc2576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561103257600080fd5b505af1158015611046573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108557600080fd5b505af1158015611099573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b6110fa610b13565b611139576040805162461bcd60e51b815260206004820181905260248201526000805160206114b1833981519152604482015290519081900360640190fd5b61114281611351565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b6028820152603781203360601b610100830152836101148301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146111ed57600093506111fc565b6101008301516037846000f593505b5050506001600160a01b038116611250576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b303b1590565b600054610100900460ff1680611279575061127961125a565b80611287575060005460ff16155b6112c25760405162461bcd60e51b815260040180806020018281038252602e8152602001806114d1602e913960400191505060405180910390fd5b600054610100900460ff161580156112ed576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156106cc576000805461ff00191690555050565b6001600160a01b0381166113965760405162461bcd60e51b815260040180806020018281038252602681526020018061148b6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114335782800160ff19823516178555611460565b82800160010185558215611460579182015b82811115611460578235825591602001919060010190611445565b5061146c929150611470565b5090565b61066f91905b8082111561146c576000815560010161147656fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7231582071e6790cc9e25671ad7d5298a655164f2f8797dc2b236e3b7f560292f64243e764736f6c63430005110032", - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13.Emscripten.clang" - }, - "schemaVersion": "3.0.23", - "updatedAt": "2020-03-26T17:11:58.391Z" -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV8.json b/packages/contracts/src/abis/Unlock/UnlockV8.json deleted file mode 100644 index d0d69421021..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV8.json +++ /dev/null @@ -1,607 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "udt", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "weth", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "estimatedGasForPurchase", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenSymbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenURI", - "type": "string" - } - ], - "name": "ConfigUnlock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "grossNetworkProduct", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiscountGranted", - "type": "uint256" - } - ], - "name": "ResetTrackedValue", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "publicLockAddress", - "type": "address" - } - ], - "name": "SetLockTemplate", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "estimatedGasForPurchase", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "internalType": "bool", - "name": "deployed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "totalSales", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "udt", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "uniswapOracles", - "outputs": [ - { - "internalType": "contract IUniswapOracle", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "weth", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_unlockOwner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - }, - { - "internalType": "bytes12", - "name": "_salt", - "type": "bytes12" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "internalType": "uint256", - "name": "discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_udt", - "type": "address" - }, - { - "internalType": "address", - "name": "_weth", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_estimatedGasForPurchase", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "_URI", - "type": "string" - } - ], - "name": "configUnlock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "_publicLockAddress", - "type": "address" - } - ], - "name": "setLockTemplate", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracleAddress", - "type": "address" - } - ], - "name": "setOracle", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_grossNetworkProduct", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalDiscountGranted", - "type": "uint256" - } - ], - "name": "resetTrackedValue", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x6080604052611ad9806100136000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063c4d66de811610097578063ef67fde611610071578063ef67fde614610515578063f2fde38b1461053b578063f832899114610561578063fddfc6e1146105695761018e565b8063c4d66de8146104df578063cec4105214610505578063d6e9e8031461050d5761018e565b80638da5cb5b1461045c5780638f32d59b14610464578063939d9f1f14610480578063963a9478146104ac578063a082eb0e146104cf578063a998e9fb146104d75761018e565b806342d921061161014b5780636bced5a2116101255780636bced5a21461040c578063715018a614610432578063743bbc2f1461043a5780637ff94bb2146104545761018e565b806342d92106146102c55780635c38eb3a146103985780635de9a137146103c65761018e565b80630cb175e314610193578063262d0a85146101d857806335a750de146101fc57806336524663146102795780633fc8cef31461029e5780634220bd46146102a6575b600080fd5b6101bf600480360360408110156101a957600080fd5b506001600160a01b03813516906020013561064b565b6040805192835260208301919091528051918290030190f35b6101e0610654565b604080516001600160a01b039092168252519081900360200190f35b610204610663565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561023e578181015183820152602001610226565b50505050905090810190601f16801561026b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61029c6004803603604081101561028f57600080fd5b50803590602001356106fa565b005b6101e0610758565b6102ae610767565b6040805161ffff9092168252519081900360200190f35b61029c600480360360c08110156102db57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561031757600080fd5b82018360208201111561032957600080fd5b8035906020019184600183028401116401000000008311171561034b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061076c9050565b61029c600480360360408110156103ae57600080fd5b506001600160a01b0381358116916020013516610988565b6103ec600480360360208110156103dc57600080fd5b50356001600160a01b0316610a73565b604080519315158452602084019290925282820152519081900360600190f35b6101e06004803603602081101561042257600080fd5b50356001600160a01b0316610a98565b61029c610ab3565b610442610b44565b60408051918252519081900360200190f35b610204610b4a565b6101e0610bab565b61046c610bba565b604080519115158252519081900360200190f35b61029c6004803603604081101561049657600080fd5b50803590602001356001600160a01b0316610be0565b61029c600480360360408110156104c257600080fd5b50803590602001356110b9565b610442611149565b61020461114f565b61029c600480360360208110156104f557600080fd5b50356001600160a01b03166111dd565b610204611288565b6104426112e3565b61029c6004803603602081101561052b57600080fd5b50356001600160a01b03166112e9565b61029c6004803603602081101561055157600080fd5b50356001600160a01b0316611460565b6101e06114b3565b61029c600480360360a081101561057f57600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156105ba57600080fd5b8201836020820111156105cc57600080fd5b803590602001918460018302840111640100000000831117156105ee57600080fd5b91939092909160208101903564010000000081111561060c57600080fd5b82018360208201111561061e57600080fd5b8035906020019184600183028401116401000000008311171561064057600080fd5b5090925090506114c2565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ef5780601f106106c4576101008083540402835291602001916106ef565b820191906000526020600020905b8154815290600101906020018083116106d257829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661074b576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600890565b606b546001600160a01b03166107c1576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b546000906107f1906001600160a01b03168363ffffffff61162916565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561089657818101518382015260200161087e565b50505050905090810190601f1680156108c35780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b1580156108e757600080fd5b505af11580156108fb573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b610990610bba565b6109cf576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561075457606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a5757600080fd5b505af1158015610a6b573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610abb610bba565b610afa576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ef5780601f106106c4576101008083540402835291602001916106ef565b6033546001600160a01b031690565b6033546000906001600160a01b0316610bd1611721565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610c31576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561075457600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7357600080fd5b505afa158015610c87573d6000803e3d6000fd5b505050506040513d6020811015610c9d57600080fd5b505190506001600160a01b03811615801590610cc75750606d546001600160a01b03828116911614155b15610d80576001600160a01b038082166000908152606c6020526040902054168015610d7a57606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610d4b57600080fd5b505af1158015610d5f573d6000803e3d6000fd5b505050506040513d6020811015610d7557600080fd5b505192505b50610d84565b8391505b606654610d97908363ffffffff61172516565b6066553360009081526068602052604090206001018054830190556001600160a01b038316156110b357606e546001600160a01b039081166000908152606c60205260409020541680156110b157606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610e4c57600080fd5b505af1158015610e60573d6000803e3d6000fd5b505050506040513d6020811015610e7657600080fd5b5051606f549091506000908290606490610ea1903a026806c6b935b8bbd4000063ffffffff61178616565b81610ea857fe5b0481610eb057fe5b04905060006066546002610f4688606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f0e57600080fd5b505af1158015610f22573d6000803e3d6000fd5b505050506040513d6020811015610f3857600080fd5b50519063ffffffff61178616565b81610f4d57fe5b0481610f5557fe5b04905080821115610f64578091505b81156110ad5760006064610f7f84601463ffffffff61178616565b81610f8657fe5b606e54604080516340c10f1960e01b81526001600160a01b038d8116600483015294909304808803602485015290519094509216916340c10f19916044808201926020929091908290030181600087803b158015610fe357600080fd5b505af1158015610ff7573d6000803e3d6000fd5b505050506040513d602081101561100d57600080fd5b505080156110ab57606e546001600160a01b03166340c10f1961102e610bab565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561107e57600080fd5b505af1158015611092573d6000803e3d6000fd5b505050506040513d60208110156110a857600080fd5b50505b505b5050505b505b50505050565b6110c1610bba565b611100576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156111d55780601f106111aa576101008083540402835291602001916111d5565b820191906000526020600020905b8154815290600101906020018083116111b857829003601f168201915b505050505081565b600054610100900460ff16806111f657506111f66117df565b80611204575060005460ff16155b61123f5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a77602e913960400191505060405180910390fd5b600054610100900460ff1615801561126a576000805460ff1961ff0019909116610100171660011790555b611273826117e5565b8015610754576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156111d55780601f106111aa576101008083540402835291602001916111d5565b60665481565b6112f1610bba565b611330576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b1580156113a057600080fd5b505af11580156113b4573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611468610bba565b6114a7576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6114b0816118d6565b50565b606b546001600160a01b031681565b6114ca610bba565b611509576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808a166001600160a01b031992831617909255606d805492891692909116919091179055606f85905561154a606a8585611977565b5061155760698383611977565b507fa8e624b38c74d695c4e1775bf583e933c34972da8bc62686ae80c0f8c279492a8787878787878760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b0316815260200186815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a150505050505050565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146116b857600093506116c7565b6101008301516037846000f593505b5050506001600160a01b03811661171b576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b60008282018381101561177f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826117955750600061171b565b828202828482816117a257fe5b041461177f5760405162461bcd60e51b8152600401808060200182810382526021815260200180611a366021913960400191505060405180910390fd5b303b1590565b600054610100900460ff16806117fe57506117fe6117df565b8061180c575060005460ff16155b6118475760405162461bcd60e51b815260040180806020018281038252602e815260200180611a77602e913960400191505060405180910390fd5b600054610100900460ff16158015611872576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610754576000805461ff00191690555050565b6001600160a01b03811661191b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611a106026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106119b85782800160ff198235161785556119e5565b828001600101855582156119e5579182015b828111156119e55782358255916020019190600101906119ca565b506119f19291506119f5565b5090565b6106f791905b808211156119f157600081556001016119fb56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820cc838d017c2a8d24d62e36d2d87b3ceb232702ee3fe4f7de5a35efb94435fccd64736f6c63430005110032", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063c4d66de811610097578063ef67fde611610071578063ef67fde614610515578063f2fde38b1461053b578063f832899114610561578063fddfc6e1146105695761018e565b8063c4d66de8146104df578063cec4105214610505578063d6e9e8031461050d5761018e565b80638da5cb5b1461045c5780638f32d59b14610464578063939d9f1f14610480578063963a9478146104ac578063a082eb0e146104cf578063a998e9fb146104d75761018e565b806342d921061161014b5780636bced5a2116101255780636bced5a21461040c578063715018a614610432578063743bbc2f1461043a5780637ff94bb2146104545761018e565b806342d92106146102c55780635c38eb3a146103985780635de9a137146103c65761018e565b80630cb175e314610193578063262d0a85146101d857806335a750de146101fc57806336524663146102795780633fc8cef31461029e5780634220bd46146102a6575b600080fd5b6101bf600480360360408110156101a957600080fd5b506001600160a01b03813516906020013561064b565b6040805192835260208301919091528051918290030190f35b6101e0610654565b604080516001600160a01b039092168252519081900360200190f35b610204610663565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561023e578181015183820152602001610226565b50505050905090810190601f16801561026b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61029c6004803603604081101561028f57600080fd5b50803590602001356106fa565b005b6101e0610758565b6102ae610767565b6040805161ffff9092168252519081900360200190f35b61029c600480360360c08110156102db57600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561031757600080fd5b82018360208201111561032957600080fd5b8035906020019184600183028401116401000000008311171561034b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061076c9050565b61029c600480360360408110156103ae57600080fd5b506001600160a01b0381358116916020013516610988565b6103ec600480360360208110156103dc57600080fd5b50356001600160a01b0316610a73565b604080519315158452602084019290925282820152519081900360600190f35b6101e06004803603602081101561042257600080fd5b50356001600160a01b0316610a98565b61029c610ab3565b610442610b44565b60408051918252519081900360200190f35b610204610b4a565b6101e0610bab565b61046c610bba565b604080519115158252519081900360200190f35b61029c6004803603604081101561049657600080fd5b50803590602001356001600160a01b0316610be0565b61029c600480360360408110156104c257600080fd5b50803590602001356110b9565b610442611149565b61020461114f565b61029c600480360360208110156104f557600080fd5b50356001600160a01b03166111dd565b610204611288565b6104426112e3565b61029c6004803603602081101561052b57600080fd5b50356001600160a01b03166112e9565b61029c6004803603602081101561055157600080fd5b50356001600160a01b0316611460565b6101e06114b3565b61029c600480360360a081101561057f57600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156105ba57600080fd5b8201836020820111156105cc57600080fd5b803590602001918460018302840111640100000000831117156105ee57600080fd5b91939092909160208101903564010000000081111561060c57600080fd5b82018360208201111561061e57600080fd5b8035906020019184600183028401116401000000008311171561064057600080fd5b5090925090506114c2565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ef5780601f106106c4576101008083540402835291602001916106ef565b820191906000526020600020905b8154815290600101906020018083116106d257829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661074b576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600890565b606b546001600160a01b03166107c1576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b546000906107f1906001600160a01b03168363ffffffff61162916565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561089657818101518382015260200161087e565b50505050905090810190601f1680156108c35780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b1580156108e757600080fd5b505af11580156108fb573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b610990610bba565b6109cf576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561075457606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a5757600080fd5b505af1158015610a6b573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610abb610bba565b610afa576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ef5780601f106106c4576101008083540402835291602001916106ef565b6033546001600160a01b031690565b6033546000906001600160a01b0316610bd1611721565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610c31576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561075457600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610c7357600080fd5b505afa158015610c87573d6000803e3d6000fd5b505050506040513d6020811015610c9d57600080fd5b505190506001600160a01b03811615801590610cc75750606d546001600160a01b03828116911614155b15610d80576001600160a01b038082166000908152606c6020526040902054168015610d7a57606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610d4b57600080fd5b505af1158015610d5f573d6000803e3d6000fd5b505050506040513d6020811015610d7557600080fd5b505192505b50610d84565b8391505b606654610d97908363ffffffff61172516565b6066553360009081526068602052604090206001018054830190556001600160a01b038316156110b357606e546001600160a01b039081166000908152606c60205260409020541680156110b157606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610e4c57600080fd5b505af1158015610e60573d6000803e3d6000fd5b505050506040513d6020811015610e7657600080fd5b5051606f549091506000908290606490610ea1903a026806c6b935b8bbd4000063ffffffff61178616565b81610ea857fe5b0481610eb057fe5b04905060006066546002610f4688606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f0e57600080fd5b505af1158015610f22573d6000803e3d6000fd5b505050506040513d6020811015610f3857600080fd5b50519063ffffffff61178616565b81610f4d57fe5b0481610f5557fe5b04905080821115610f64578091505b81156110ad5760006064610f7f84601463ffffffff61178616565b81610f8657fe5b606e54604080516340c10f1960e01b81526001600160a01b038d8116600483015294909304808803602485015290519094509216916340c10f19916044808201926020929091908290030181600087803b158015610fe357600080fd5b505af1158015610ff7573d6000803e3d6000fd5b505050506040513d602081101561100d57600080fd5b505080156110ab57606e546001600160a01b03166340c10f1961102e610bab565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561107e57600080fd5b505af1158015611092573d6000803e3d6000fd5b505050506040513d60208110156110a857600080fd5b50505b505b5050505b505b50505050565b6110c1610bba565b611100576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156111d55780601f106111aa576101008083540402835291602001916111d5565b820191906000526020600020905b8154815290600101906020018083116111b857829003601f168201915b505050505081565b600054610100900460ff16806111f657506111f66117df565b80611204575060005460ff16155b61123f5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a77602e913960400191505060405180910390fd5b600054610100900460ff1615801561126a576000805460ff1961ff0019909116610100171660011790555b611273826117e5565b8015610754576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156111d55780601f106111aa576101008083540402835291602001916111d5565b60665481565b6112f1610bba565b611330576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b1580156113a057600080fd5b505af11580156113b4573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113f357600080fd5b505af1158015611407573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611468610bba565b6114a7576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b6114b0816118d6565b50565b606b546001600160a01b031681565b6114ca610bba565b611509576040805162461bcd60e51b81526020600482018190526024820152600080516020611a57833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808a166001600160a01b031992831617909255606d805492891692909116919091179055606f85905561154a606a8585611977565b5061155760698383611977565b507fa8e624b38c74d695c4e1775bf583e933c34972da8bc62686ae80c0f8c279492a8787878787878760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b0316815260200186815260200180602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039b50909950505050505050505050a150505050505050565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146116b857600093506116c7565b6101008301516037846000f593505b5050506001600160a01b03811661171b576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b60008282018381101561177f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826117955750600061171b565b828202828482816117a257fe5b041461177f5760405162461bcd60e51b8152600401808060200182810382526021815260200180611a366021913960400191505060405180910390fd5b303b1590565b600054610100900460ff16806117fe57506117fe6117df565b8061180c575060005460ff16155b6118475760405162461bcd60e51b815260040180806020018281038252602e815260200180611a77602e913960400191505060405180910390fd5b600054610100900460ff16158015611872576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610754576000805461ff00191690555050565b6001600160a01b03811661191b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611a106026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106119b85782800160ff198235161785556119e5565b828001600101855582156119e5579182015b828111156119e55782358255916020019190600101906119ca565b506119f19291506119f5565b5090565b6106f791905b808211156119f157600081556001016119fb56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820cc838d017c2a8d24d62e36d2d87b3ceb232702ee3fe4f7de5a35efb94435fccd64736f6c63430005110032", - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13.Emscripten.clang" - }, - "schemaVersion": "3.2.0", - "updatedAt": "2020-07-11T18:54:37.084Z" -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV4.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV4.sol deleted file mode 100644 index 274d399d9ac..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV4.sol +++ /dev/null @@ -1,490 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLockV4 { - ///=================================================================== - /// Events - event Destroy(uint balance, address indexed owner); - - event Disable(); - - event Withdrawal( - address indexed sender, - address indexed beneficiary, - uint amount - ); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ); - - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event ExpireKey(uint indexed tokenId); - - event NewLockSymbol(string symbol); - - event TransferFeeChanged( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ); - - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - ///=================================================================== - - /// Functions - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint16); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than the owner. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @notice Used to clean up old lock contracts from the blockchain. - * TODO: add a check to ensure all keys are INVALID! - * @dev Throws if called by other than owner. - * @dev Throws if lock has not yet been disabled. - */ - function destroyLock() external; - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than the owner or beneficiary - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` - * use case. - */ - function withdraw(uint _amount) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - * @dev Throws if called by other than owner - * @dev Throws if lock has been disabled - * @param _keyPrice The new price to set for keys - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than owner of beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * A function which lets the owner of the lock expire a users' key. - * @dev Throws if called by other than lock owner - * @dev Throws if key owner does not have a valid key - * @param _owner The address of the key owner - */ - function expireKeyFor(address _owner) external; - - /** - * Checks if the user has a non-expired key. - * @param _owner The address of the key owner - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - * @dev Throws if key owner does not have a valid key - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _owner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - * @dev Throws if owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - * @dev Throws if called by other than the lock owner - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than the lock-owner - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external; - - /** - * @dev Key Purchase function - * @param _recipient address of the recipient of the purchased key - * @dev Throws if lock is disabled. - */ - function purchaseFor(address _recipient) external payable; - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @dev Throws if lock is disabled, or if referrer doesn't have a valid key. - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable; - - /** - * Allow the Lock owner to change the transfer fee. - * @dev Throws if called by other than lock-owner - * Ex: 200 bps = 2% - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _owner does not have a valid key - * @param _owner The owner of the key check the transfer fee for. - * @return The transfer fee in basis-points(bps). - */ - function getTransferFee(address _owner) external view returns (uint); - - /** - * @notice Destroys the msg.sender's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external; - - /** - * Allow the owner to change the refund penalty. - * @dev Throws if called by other than owner - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _owner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - function keyOwnerToNonce(address) external view returns (uint256); - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - * @param _keyOwner The key owner's address - * @param _txSender The address cancelling the key on behalf of the key-owner - * @return approvalHash The returned hash - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) external view returns (bytes32 approvalHash); - - /** - *@notice A utility function for erc721 metadata - * @param _a String 1 - * @param _b String 2 - * @param _c String 3 - * @param _d String 4 - * @return _concatenatedString The returned string - */ - function strConcat( - string calldata _a, - string calldata _b, - string calldata _c, - string calldata _d - ) external pure returns (string memory _concatenatedString); - - /** - * @notice A utility function for erc721 metadata - * @param _i A uint to convert - * @return _uintAsString the returned string - */ - function uint2Str( - uint256 _i - ) external pure returns (string memory _uintAsString); - - /** - * @notice A utility function for erc721 metadata - * @param _addr An address to convert - * @return A string - */ - function address2Str(address _addr) external pure returns (string memory); - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function unlockProtocol() external view returns (address); - - ///=================================================================== - - /// From Openzeppelin's IERC721.sol - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @dev Throws if lock is disabled, or if _to == msg.sender. - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external; - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - * @dev Throws if _owner = address(0) - * @param _owner The address of the key owner - */ - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /** - * Will return the approved recipient for a key, if any. - * @param _tokenId The ID of the token we're inquiring about. - * @return address The approved address (if any) - */ - function getApproved(uint _tokenId) external view returns (address); - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From IERC721Enumerable - function totalSupply() external view returns (uint256); - - ///=================================================================== - - /// From Openzeppelin's Ownable.sol - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function renounceOwnership() external; - - function transferOwnership(address newOwner) external; - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - ///=================================================================== -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV5.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV5.sol deleted file mode 100644 index 602baf78171..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV5.sol +++ /dev/null @@ -1,579 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -/** - * @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); -} - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// import '@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol'; -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -/** - * @title The PublicLock Interface - */ - -contract IPublicLockV5 is IERC721Enumerable { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - ///=================================================================== - /// Events - event Destroy(uint balance, address indexed owner); - - event Disable(); - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event ExpireKey(uint indexed tokenId); - - event NewLockSymbol(string symbol); - - event TransferFeeChanged(uint transferFeeBasisPoints); - - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyOwner, uint nextAvailableNonce); - - ///=================================================================== - - /// Functions - - function initialize( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than the owner. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @notice Used to clean up old lock contracts from the blockchain. - * TODO: add a check to ensure all keys are INVALID! - * @dev Throws if called by other than owner. - * @dev Throws if lock has not yet been disabled. - */ - function destroyLock() external; - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than the owner or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `fullRefund` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - * @dev Throws if called by other than owner - * @dev Throws if lock has been disabled - * @param _keyPrice The new price to set for keys - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than owner of beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * A function which lets the owner of the lock expire a users' key. - * @dev Throws if called by other than lock owner - * @dev Throws if key owner does not have a valid key - * @param _owner The address of the key owner - */ - function expireKeyFor(address _owner) external; - - /** - * Checks if the user has a non-expired key. - * @param _owner The address of the key owner - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - * @dev Throws if key owner does not have a valid key - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _owner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - * @dev Throws if owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - * @dev Throws if called by other than the lock owner - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than the lock-owner - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * Allow the Lock owner to change the transfer fee. - * @dev Throws if called by other than lock-owner - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _owner does not have a valid key - * @param _owner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _owner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by the lock owner to destroy the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than owner - * @dev Throws if _keyOwner does not have a valid key - */ - function fullRefund(address _keyOwner, uint amount) external; - - /** - * @notice Destroys the msg.sender's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow the owner to change the refund penalty. - * @dev Throws if called by other than owner - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _owner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - function keyOwnerToNonce(address) external view returns (uint256); - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - * @param _keyOwner The key owner's address - * @param _txSender The address cancelling the key on behalf of the key-owner - * @return approvalHash The returned hash - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) external view returns (bytes32 approvalHash); - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function erc1820() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyCancelInterfaceId() external view returns (bytes32); - - function keySoldInterfaceId() external view returns (bytes32); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function BASIS_POINTS_DEN() external view returns (uint256); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From Openzeppelin's Ownable.sol - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function renounceOwnership() external; - - function transferOwnership(address newOwner) external; - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - ///=================================================================== -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV6.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV6.sol deleted file mode 100644 index 71f278c254e..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV6.sol +++ /dev/null @@ -1,593 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -/** - * @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); -} - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// import '@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol'; -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -/** - * @title The PublicLock Interface - */ - -contract IPublicLockV6 is IERC721Enumerable { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Events - event Destroy(uint balance, address indexed owner); - - event Disable(); - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - event ExpireKey(uint indexed tokenId); - - event NewLockSymbol(string symbol); - - event TransferFeeChanged(uint transferFeeBasisPoints); - - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyOwner, uint nextAvailableNonce); - - ///=================================================================== - - /// Functions - - function initialize( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than the owner. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @notice Used to clean up old lock contracts from the blockchain. - * TODO: add a check to ensure all keys are INVALID! - * @dev Throws if called by other than owner. - * @dev Throws if lock has not yet been disabled. - */ - function destroyLock() external; - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than the owner or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `fullRefund` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - * @dev Throws if called by other than owner - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than owner of beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * A function which lets the owner of the lock expire a users' key. - * @dev Throws if called by other than lock owner - * @dev Throws if key owner does not have a valid key - * @param _owner The address of the key owner - */ - function expireKeyFor(address _owner) external; - - /** - * Checks if the user has a non-expired key. - * @param _owner The address of the key owner - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - * @dev Throws if key owner does not have a valid key - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _owner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - * @dev Throws if owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - * @dev Throws if called by other than the lock owner - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than the lock-owner - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * Allow the Lock owner to change the transfer fee. - * @dev Throws if called by other than lock-owner - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _owner does not have a valid key - * @param _owner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _owner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by the lock owner to destroy the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than owner - * @dev Throws if _keyOwner does not have a valid key - */ - function fullRefund(address _keyOwner, uint amount) external; - - /** - * @notice Destroys the msg.sender's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - uint8 _v, - bytes32 _r, - bytes32 _s - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow the owner to change the refund penalty. - * @dev Throws if called by other than owner - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _owner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - function keyOwnerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyOwner The key owner's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) external view returns (bytes32 approvalHash); - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function erc1820() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyCancelInterfaceId() external view returns (bytes32); - - function keySoldInterfaceId() external view returns (bytes32); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function BASIS_POINTS_DEN() external view returns (uint256); - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - function CANCEL_TYPEHASH() external view returns (bytes32); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From Openzeppelin's Ownable.sol - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function renounceOwnership() external; - - function transferOwnership(address newOwner) external; - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - ///=================================================================== -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV7.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV7.sol deleted file mode 100644 index d627a636309..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV7.sol +++ /dev/null @@ -1,467 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLockV7 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV7Sol6.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV7Sol6.sol deleted file mode 100644 index 150c5d3dc91..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV7Sol6.sol +++ /dev/null @@ -1,469 +0,0 @@ -pragma solidity ^0.6.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLockV7Sol6 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - receive() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * external function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) external view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - function approve(address to, uint256 tokenId) external; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return operator The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint256 _tokenId - ) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address _owner, - address operator - ) external view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - - function totalSupply() external view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) external view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) external view returns (uint256); -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV8.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV8.sol deleted file mode 100644 index a19bfa6809c..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV8.sol +++ /dev/null @@ -1,485 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLockV8Sol5 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV8Sol6.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV8Sol6.sol deleted file mode 100644 index 9fbe9bdb967..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV8Sol6.sol +++ /dev/null @@ -1,487 +0,0 @@ -pragma solidity ^0.6.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLockV8Sol6 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - receive() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) external view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - function approve(address to, uint256 tokenId) external; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return operator The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint256 _tokenId - ) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address _owner, - address operator - ) external view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) external; - - function totalSupply() external view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) external view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) external view returns (uint256); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV8sol8.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV8sol8.sol deleted file mode 100644 index e8b21f19045..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV8sol8.sol +++ /dev/null @@ -1,439 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.5.17 <0.9.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLockV8 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - // roles - function DEFAULT_ADMIN_ROLE() external pure returns (bytes32 role); - - function KEY_GRANTER_ROLE() external pure returns (bytes32 role); - - function LOCK_MANAGER_ROLE() external pure returns (bytes32 role); - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) external view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - function approve(address to, uint256 tokenId) external; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return operator The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint256 _tokenId - ) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address _owner, - address operator - ) external view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - - function totalSupply() external view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) external view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) external view returns (uint256); - - /** - * Innherited from Open Zeppelin AccessControl.sol - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - function grantRole(bytes32 role, address account) external; - - function revokeRole(bytes32 role, address account) external; - - function renounceRole(bytes32 role, address account) external; - - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV5.sol b/packages/contracts/src/contracts/Unlock/IUnlockV5.sol deleted file mode 100644 index ba26443d1a3..00000000000 --- a/packages/contracts/src/contracts/Unlock/IUnlockV5.sol +++ /dev/null @@ -1,93 +0,0 @@ -pragma solidity 0.5.12; - -/** - * @title The Unlock Interface - **/ - -interface IUnlockV5 { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address publicLockAddress, - string globalTokenSymbol, - string globalTokenURI - ); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock( - address _publicLockAddress, - string calldata _symbol, - string calldata _URI - ) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; -} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV6.sol b/packages/contracts/src/contracts/Unlock/IUnlockV6.sol deleted file mode 100644 index 9d7bd43a480..00000000000 --- a/packages/contracts/src/contracts/Unlock/IUnlockV6.sol +++ /dev/null @@ -1,93 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title The Unlock Interface - **/ - -interface IUnlockV6 { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address publicLockAddress, - string globalTokenSymbol, - string globalTokenURI - ); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock( - address _publicLockAddress, - string calldata _symbol, - string calldata _URI - ) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; -} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV7.sol b/packages/contracts/src/contracts/Unlock/IUnlockV7.sol deleted file mode 100644 index 826df388b05..00000000000 --- a/packages/contracts/src/contracts/Unlock/IUnlockV7.sol +++ /dev/null @@ -1,147 +0,0 @@ -pragma solidity >=0.5.0; - -/** - * @title The Unlock Interface - **/ - -interface IUnlockV7 { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock(string calldata _symbol, string calldata _URI) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapExchanges(address) external view returns (address); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - // allows the owner to set the exchange address to use for value conversions - // setting the _exchangeAddress to address(0) removes support for the token - function setExchange( - address _tokenAddress, - address _exchangeAddress - ) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV8.sol b/packages/contracts/src/contracts/Unlock/IUnlockV8.sol deleted file mode 100644 index 2f5bc03ae35..00000000000 --- a/packages/contracts/src/contracts/Unlock/IUnlockV8.sol +++ /dev/null @@ -1,162 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title The Unlock Interface - **/ - -interface IUnlockV8 { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI - ) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV0.sol b/packages/contracts/src/contracts/Unlock/UnlockV0.sol deleted file mode 100644 index ac677aecd00..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV0.sol +++ /dev/null @@ -1,1255 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File zos-lib/contracts/Initializable.sol@v2.1.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipRenounced(address indexed previousOwner); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipRenounced(_owner); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File contracts/interfaces/ILockCore.sol - -pragma solidity 0.4.25; - -/** - * @title The Lock interface core methods for a Lock - * @author HardlyDifficult (unlock-protocol.com) - */ -interface ILockCore { - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - */ - function purchaseFor(address _recipient, bytes _data) external payable; - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data optional marker for the key - */ - function purchaseForFrom( - address _recipient, - address _referrer, - bytes _data - ) external payable; - - /** - * @dev Called by owner to withdraw all funds from the lock. - */ - function withdraw() external; - - /** - * @dev Called by owner to partially withdraw funds from the lock. - */ - function partialWithdraw(uint _amount) external; - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than outstandingKeys. - */ - function numberOfOwners() external view returns (uint); - - /** - * Public function which returns the total number of keys (both expired and valid) - */ - function outstandingKeys() external view returns (uint); - - /** - * @dev Returns the key's data field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyDataFor(address _owner) external view returns (bytes data); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[]); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.4.25; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * Return type `ILockCore` is the most specific interface from which all lock types inherit. - */ - function createLock( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) external returns (ILockCore lock); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); -} - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.4.25; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - // function safeTransferFrom(address _from, address _to, uint _tokenId, bytes data) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to "" - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - // function safeTransferFrom(address _from, address _to, uint _tokenId) external payable; - - /// @notice Enable or disable approval for a third party ("operator") to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - // function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - // function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} - -// interface ERC721TokenReceiver { -// /// @notice Handle the receipt of an NFT -// /// @dev The ERC721 smart contract calls this function on the -// /// recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return -// /// of other than the magic value MUST result in the transaction being reverted. -// /// @notice The contract address is always the message sender. -// /// @param _operator The address which called `safeTransferFrom` function -// /// @param _from The address which previously owned the token -// /// @param _tokenId The NFT identifier which is being transferred -// /// @param _data Additional data with no specified format -// /// @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` -// /// unless throwing -// function onERC721Received( -// address _operator, -// address _from, -// uint _tokenId, -// bytes _data -// ) -// external -// returns(bytes4); -// } - -// File contracts/interfaces/IERC721Receiver.sol - -pragma solidity 0.4.25; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -interface IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint tokenId, - bytes data - ) public returns (bytes4); -} - -// File openzeppelin-eth/contracts/introspection/IERC165.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title IERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-eth/contracts/introspection/ERC165.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is Initializable, IERC165 { - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - function initialize() public initializer { - _registerInterface(_InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) public view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } - - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/math/SafeMath.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title SafeMath - * @dev Math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two numbers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0); // Solidity only automatically asserts when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two numbers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two numbers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.4.25; - -/** - * TODO: consider error codes rather than strings - */ - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ -contract PublicLock is ILockCore, ERC165, IERC721, IERC721Receiver, Ownable { - using SafeMath for uint; - - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - bytes data; // Note: This can be expensive? - } - - // Events - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Fields - // Unlock Protocol address - // TODO: should we make that private/internal? - address public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) internal ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) internal approved; - - /** - * MODIFIERS - */ - // Ensures that an owner has a key - modifier hasKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > 0, "No such key"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > now, "Key is not valid"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(ownerByTokenId[_tokenId] == msg.sender); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "No such key"); - _; - } - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - ownerByTokenId[_tokenId] == msg.sender || - _getApproved(_tokenId) == msg.sender, - "Only key owner or approved owner" - ); - _; - } - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require( - maxNumberOfKeys > numberOfKeysSold, - "Maximum number of keys already sold" - ); - _; - } - - // Constructor - constructor( - address _owner, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) public { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "Expiration duration exceeds 100 years" - ); - unlockProtocol = msg.sender; // Make sure we link back to Unlock's smart contract. - Ownable.initialize(_owner); - ERC165.initialize(); - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - */ - function purchaseFor(address _recipient, bytes _data) external payable { - return _purchaseFor(_recipient, address(0), _data); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data optional marker for the key - */ - function purchaseForFrom( - address _recipient, - address _referrer, - bytes _data - ) external payable hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer, _data); - } - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - external - payable - notSoldOut - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0)); - - uint previousExpiration = keyByOwner[_recipient].expirationTimestamp; - - if (previousExpiration == 0) { - // The recipient did not have a key previously - owners.push(_recipient); - // Note: not using the tokenId above since ATM we do not transfer tokenId's - // this will change when we decouple tokenId from address - ownerByTokenId[uint(_recipient)] = _recipient; - // At the moment tokenId is the user's address, but as we work towards ERC721 - // support this will change to a sequenceId assigned at purchase. - keyByOwner[_recipient].tokenId = uint(_recipient); - } - - if (previousExpiration <= now) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - keyByOwner[_recipient].expirationTimestamp = keyByOwner[_from] - .expirationTimestamp; - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - now` cannot underflow - keyByOwner[_recipient].expirationTimestamp = keyByOwner[_from] - .expirationTimestamp - .add(previousExpiration - now); - } - // Overwite data in all cases - keyByOwner[_recipient].data = keyByOwner[_from].data; - - // Effectively expiring the key for the previous owner - keyByOwner[_from].expirationTimestamp = now; - - // Clear any previous approvals - approved[_tokenId] = address(0); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = address(this).balance; - require(balance > 0, "Not enough funds"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "Must request an amount greater than 0"); - uint256 balance = address(this).balance; - require(balance > 0 && balance >= _amount, "Not enough funds"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyKeyOwner(_tokenId) { - require(_approved != address(0)); - require(msg.sender != _approved, "You can't approve yourself"); - - approved[_tokenId] = _approved; - emit Approval(ownerByTokenId[_tokenId], _approved, _tokenId); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "Invalid address"); - return keyByOwner[_owner].expirationTimestamp > 0 ? 1 : 0; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) external view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than outstandingKeys. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function outstandingKeys() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[]) { - require(outstandingKeys() > 0, "No keys to retrieve"); - uint _startIndex = _page * _pageSize; - require( - _startIndex >= 0 && _startIndex < outstandingKeys(), - "Index must be in-bounds" - ); - uint endOfPageIndex; - - if (_startIndex + _pageSize > owners.length) { - endOfPageIndex = owners.length; - _pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + _pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](_pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - keyByOwner[_owner].expirationTimestamp = now; // Effectively expiring the key - } - - /** - * @dev Returns the key's data field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyDataFor( - address _owner - ) public view hasKey(_owner) returns (bytes memory data) { - return keyByOwner[_owner].data; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view hasKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` - */ - function onERC721Received( - address operator, // solhint-disable-line no-unused-vars - address from, // solhint-disable-line no-unused-vars - uint tokenId, // solhint-disable-line no-unused-vars - bytes data // solhint-disable-line no-unused-vars - ) public returns (bytes4) { - return this.onERC721Received.selector; - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer, - bytes memory _data - ) internal notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0)); - - // Let's get the actual price for the key from the Unlock smart contract - IUnlock unlock = IUnlock(unlockProtocol); - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlock.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts to allow "donations" or partial refunds after - // discounts (TODO implement partial refunds) - require(msg.value >= netPrice, "Insufficient funds"); - // TODO: If there is more than the required price, then let's return whatever is extra - // extra (CAREFUL: re-entrancy!) - - // Assign the key - uint previousExpiration = keyByOwner[_recipient].expirationTimestamp; - if (previousExpiration < now) { - if (previousExpiration == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension - numberOfKeysSold++; - owners.push(_recipient); - // Note: for ERC721 support we will be changing tokenId to be a sequence id instead - ownerByTokenId[uint(_recipient)] = _recipient; - // At the moment tokenId is the user's address, but as we work towards ERC721 - // support this will change to a sequenceId assigned at purchase. - keyByOwner[_recipient].tokenId = uint(_recipient); - } - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - keyByOwner[_recipient].expirationTimestamp = now + expirationDuration; - } else { - // This is an existing owner trying to extend their key - keyByOwner[_recipient].expirationTimestamp = previousExpiration.add( - expirationDuration - ); - } - // Overwite data in all cases - keyByOwner[_recipient].data = _data; - - if (discount > 0) { - unlock.recordConsumedDiscount(discount, tokens); - } - - unlock.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - uint(_recipient) // Note: since each user can own a single token, we use the current - // owner (new!) for the token id - ); - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "No approved recipient exists"); - return approvedRecipient; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - Ownable.owner().transfer(_amount); - emit Withdrawal(msg.sender, _amount); - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.4.25; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including "frozen" tokens (which have been used to claim - * discounts and cannot be used/transfered for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, Initializable, Ownable { - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "Only from previously deployed locks"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - grossNetworkProduct = 0; - totalDiscountGranted = 0; - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - */ - function createLock( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) public returns (ILockCore lock) { - // create lock - PublicLock newPublicLock = new PublicLock( - msg.sender, - _expirationDuration, - _keyPrice, - _maxNumberOfKeys - ); - - // Assign the new Lock - locks[address(newPublicLock)] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, address(newPublicLock)); - - // return the created lock - return newPublicLock; - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - grossNetworkProduct += _value; - return; - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV1.sol b/packages/contracts/src/contracts/Unlock/UnlockV1.sol deleted file mode 100644 index 70c857c4be5..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV1.sol +++ /dev/null @@ -1,1957 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File zos-lib/contracts/Initializable.sol@v2.2.2 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.7; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File contracts/interfaces/ILockCore.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock interface core methods for a Lock - * @author HardlyDifficult (unlock-protocol.com) - */ -interface ILockCore { - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable; - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable; - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Called by owner to withdraw all funds from the lock. - */ - function withdraw() external; - - /** - * @dev Called by owner to partially withdraw funds from the lock. - */ - function partialWithdraw(uint _amount) external; - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract. - * @dev Reverts if called by anyone but the owner. - * @dev Reverts if isAlive == false - * @dev Should emit Disable event. - */ - function disableLock() external; - - /** - * @dev Used to clean up old lock contracts from the blockchain by using selfdestruct. - * @dev Reverts if called by anyone but the owner. - * @dev Reverts if isAlive == true - * @dev Should emit Destroy event. - */ - function destroyLock() external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Public function which returns the total number of keys (both expired and valid) - * - * This function signature is from the ERC-721 enumerable extension. - * https://eips.ethereum.org/EIPS/eip-721 - * @notice Count NFTs tracked by this contract - * @return A count of valid NFTs tracked by this contract, where each one of - * them has an assigned and queryable owner not equal to the zero address - */ - function totalSupply() external view returns (uint); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title IERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is IERC165 { - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() internal { - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev internal method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.1.3 - -pragma solidity ^0.5.0; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - emit Destroy(address(this).balance, msg.sender); - selfdestruct(msg.sender); - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * Return type `ILockCore` is the most specific interface from which all lock types inherit. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys - ) external returns (ILockCore lock); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC20 interface - * @dev see https://github.com/ethereum/EIPs/issues/20 - */ -interface IERC20 { - function transfer(address to, uint256 value) external returns (bool); - - function approve(address spender, uint256 value) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool); - - function totalSupply() external view returns (uint256); - - function balanceOf(address who) external view returns (uint256); - - function allowance( - address owner, - address spender - ) external view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint256 value); - - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.7; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - - /** - * Gets the current balance of the account provided. - */ - function _getBalance(address _account) internal view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // The version number for this lock contract, - uint public publicLockVersion; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - constructor( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys, - uint _version - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - publicLockVersion = _version; - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = _getBalance(address(this)); - require(balance > 0, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "GREATER_THAN_ZERO"); - uint balance = _getBalance(address(this)); - require(balance >= _amount, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - _transfer(Ownable.owner(), _amount); - emit Withdrawal(msg.sender, _amount); - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner has a key - modifier hasKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > 0, "NO_SUCH_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return keyByOwner[_owner].expirationTimestamp > 0 ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view hasKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is IERC721, Ownable { - /// A descriptive name for a collection of NFTs in this contract - string private lockName; - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title SafeMath - * @dev Unsigned math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two unsigned integers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two unsigned integers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts of ETH to allow 'donations' - _chargeAtLeast(netPrice); - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - uint previousExpiration = toKey.expirationTimestamp; - if (previousExpiration < block.timestamp) { - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } else { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = previousExpiration.add(expirationDuration); - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.7; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - event CancelKey(uint indexed tokenId, address indexed owner, uint refund); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - Key storage key = _getKeyFor(msg.sender); - - uint refund = _getCancelAndRefundValue(msg.sender); - - emit CancelKey(key.tokenId, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * Utility library of inline functions on addresses - */ -library Address { - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param account address of the account to check - * @return whether the target address is a contract - */ - function isContract(address account) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - // TODO: this value is currently ignored and no fee is charged yet! - uint public transferFeeNumerator = 5; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - } - _recordOwner(_recipient, toKey.tokenId); - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - toKey.expirationTimestamp = fromKey.expirationTimestamp; - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - MixinNoFallback, - ERC721Holder, - IERC721, - ILockCore, - ERC165, - Ownable, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinGrantKeys, - MixinApproval, - MixinLockMetadata, - MixinRefunds, - MixinPurchase, - MixinTransfer -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_expirationDuration, _keyPrice, _maxNumberOfKeys, 1) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transfered for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is MixinNoFallback, IUnlock, Initializable, Ownable { - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys - ) public returns (ILockCore lock) { - // create lock - ILockCore newLock = new PublicLock( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys - ); - - // Assign the new Lock - locks[address(newLock)] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, address(newLock)); - - // return the created lock - return newLock; - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - grossNetworkProduct += _value; - return; - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV2.sol b/packages/contracts/src/contracts/Unlock/UnlockV2.sol deleted file mode 100644 index 2ddc5ce892b..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV2.sol +++ /dev/null @@ -1,2 +0,0 @@ -// Error HH603: Hardhat flatten doesn't support cyclic dependencies. -// For more info go to https://hardhat.org/HH603 or run Hardhat with --show-stack-traces \ No newline at end of file diff --git a/packages/contracts/src/contracts/Unlock/UnlockV3.sol b/packages/contracts/src/contracts/Unlock/UnlockV3.sol deleted file mode 100644 index 8ce1599daac..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV3.sol +++ /dev/null @@ -1,2232 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File zos-lib/contracts/Initializable.sol@v2.2.3 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.7; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title IERC165 - * @dev https://eips.ethereum.org/EIPS/eip-165 - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is IERC165 { - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - /* - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() internal { - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev internal method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.2.0 - -pragma solidity ^0.5.2; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC20 interface - * @dev see https://eips.ethereum.org/EIPS/eip-20 - */ -interface IERC20 { - function transfer(address to, uint256 value) external returns (bool); - - function approve(address spender, uint256 value) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool); - - function totalSupply() external view returns (uint256); - - function balanceOf(address who) external view returns (uint256); - - function allowance( - address owner, - address spender - ) external view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint256 value); - - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.7; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (_price > 0) { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (_amount > 0) { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - } - - /** - * Gets the current balance of the account provided. - */ - function _getBalance(address _account) internal view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - - emit Destroy(address(this).balance, msg.sender); - - // this will send any ETH or ERC20 held by the lock to the owner - _transfer(msg.sender, _getBalance(address(this))); - selfdestruct(msg.sender); - - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory); - - /** Function to set the globalTokenURI field. - * Should throw if called by other than owner - */ - function setGlobalBaseTokenURI(string calldata _URI) external; - - // Function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function to set the globalTokenSymbol field. - * Should throw if called by other than owner. - */ - function setGlobalTokenSymbol(string calldata _symbol) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - constructor( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = _getBalance(address(this)); - require(balance > 0, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "GREATER_THAN_ZERO"); - uint balance = _getBalance(address(this)); - require(balance >= _amount, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - _transfer(Ownable.owner(), _amount); - emit Withdrawal(msg.sender, _amount); - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _owner) { - require(keyByOwner[_owner].expirationTimestamp > 0, "HAS_NEVER_OWNED_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_owner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasValidKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.7; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -contract UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) public pure returns (string memory _concatenatedString) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - string memory abcd = new string( - _ba.length + _bb.length + _bc.length + _bd.length - ); - bytes memory babcd = bytes(abcd); - uint k = 0; - uint i = 0; - for (i = 0; i < _ba.length; i++) { - babcd[k++] = _ba[i]; - } - for (i = 0; i < _bb.length; i++) { - babcd[k++] = _bb[i]; - } - for (i = 0; i < _bc.length; i++) { - babcd[k++] = _bc[i]; - } - for (i = 0; i < _bd.length; i++) { - babcd[k++] = _bd[i]; - } - return string(babcd); - } - - function uint2Str(uint _i) public pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721, - ERC165, - Ownable, - MixinLockCore, - UnlockUtils, - MixinKeys -{ - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string private lockName; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - constructor(string memory _lockName) internal { - lockName = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol(string calldata _lockSymbol) external onlyOwner { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.getGlobalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external onlyOwner { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.getGlobalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return - UnlockUtils.strConcat( - URI, - UnlockUtils.address2Str(address(this)), - "/", - UnlockUtils.uint2Str(_tokenId) - ); - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title SafeMath - * @dev Unsigned math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two unsigned integers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two unsigned integers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts of ETH to allow 'donations' - _chargeAtLeast(netPrice); - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - uint previousExpiration = toKey.expirationTimestamp; - if (toKey.tokenId == 0) { - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } else { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = previousExpiration.add(expirationDuration); - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - } -} - -// File openzeppelin-solidity/contracts/cryptography/ECDSA.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title Elliptic curve signature operations - * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d - * TODO Remove this library once solidity supports passing a signature to ecrecover. - * See https://github.com/ethereum/solidity/issues/864 - */ - -library ECDSA { - /** - * @dev Recover signer address from a message by using their signature - * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. - * @param signature bytes signature, the signature is generated using web3.eth.sign() - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * toEthSignedMessageHash - * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" - * and hash the result - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.7; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyOwnerToNonce; - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - _cancelAndRefund(msg.sender); - } - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external { - require( - ECDSA.recover( - ECDSA.toEthSignedMessageHash( - getCancelAndRefundApprovalHash(_keyOwner, msg.sender) - ), - _signature - ) == _keyOwner, - "INVALID_SIGNATURE" - ); - - keyOwnerToNonce[_keyOwner]++; - _cancelAndRefund(_keyOwner); - } - - /** - * @dev Increments the current nonce for the msg.sender. - * This can be used to invalidate a previously signed message. - */ - function incrementNonce() external { - keyOwnerToNonce[msg.sender]++; - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // Approval enables only one cancel call - keyOwnerToNonce[_keyOwner], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner) internal { - Key storage key = _getKeyFor(_keyOwner); - - uint refund = _getCancelAndRefundValue(_keyOwner); - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * Utility library of inline functions on addresses - */ -library Address { - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param account address of the account to check - * @return whether the target address is a contract - */ - function isContract(address account) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - uint public transferFeeNumerator = 0; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - _chargeAtLeast(getTransferFee(_from)); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, toKey.tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _owner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _owner - ) public view hasValidKey(_owner) returns (uint) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - uint fee; - if (timeRemaining >= expirationDuration) { - // Max the potential impact of this fee for keys with long durations remaining - fee = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - fee = keyPrice.mul(timeRemaining) / expirationDuration; - } - return fee.mul(transferFeeNumerator) / transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IERC721, - MixinNoFallback, - ERC165, - Ownable, - ERC721Holder, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinGrantKeys, - MixinPurchase, - MixinApproval, - MixinTransfer, - MixinRefunds -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_expirationDuration, _keyPrice, _maxNumberOfKeys) - MixinLockMetadata(_lockName) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - // The version number of the current implementation on this network - function publicLockVersion() external pure returns (uint16) { - return 3; - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transfered for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, MixinNoFallback, Initializable, Ownable { - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string private globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string private globalTokenSymbol; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) public { - // create lock - address newLock = address( - new PublicLock( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ) - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me (discount tokens) - grossNetworkProduct += _value; - locks[msg.sender].totalSales += _value; - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 3; - } - - // function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory) { - return globalBaseTokenURI; - } - - // function to set the globalTokenURI field. - function setGlobalBaseTokenURI(string calldata _URI) external onlyOwner { - globalBaseTokenURI = _URI; - emit NewTokenURI(_URI); - } - - // function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory) { - return globalTokenSymbol; - } - - // function to set the globalTokenSymbol field. - function setGlobalTokenSymbol(string calldata _symbol) external onlyOwner { - globalTokenSymbol = _symbol; - emit NewGlobalTokenSymbol(_symbol); - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV4.sol b/packages/contracts/src/contracts/Unlock/UnlockV4.sol deleted file mode 100644 index 5bc5af8f299..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV4.sol +++ /dev/null @@ -1,2387 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File zos-lib/contracts/Initializable.sol@v2.3.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.9; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC165 standard, as defined in the - * [EIP](https://eips.ethereum.org/EIPS/eip-165). - * - * 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 - * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) - * 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); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Implementation of the `IERC165` interface. - * - * Contracts may inherit from this and call `_registerInterface` to declare - * their support of an interface. - */ -contract ERC165 is IERC165 { - /* - * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 - */ - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - constructor() internal { - // Derived contracts need only register support for their own interfaces, - // we register support for ERC165 itself here - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev See `IERC165.supportsInterface`. - * - * Time complexity O(1), guaranteed to always use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See `IERC165.supportsInterface`. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.3.0 - -pragma solidity ^0.5.0; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. Does not include - * the optional functions; to access them see `ERC20Detailed`. - */ -interface IERC20 { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a `Transfer` event. - */ - function transfer(address recipient, 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. - * - * > 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.9; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Gets the current balance of the account provided. - */ - function getBalance(address _account) public view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (_price > 0) { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (_amount > 0) { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - - emit Destroy(address(this).balance, msg.sender); - - // this will send any ETH or ERC20 held by the lock to the owner - _transfer(msg.sender, getBalance(address(this))); - selfdestruct(msg.sender); - - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.9; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory); - - /** Function to set the globalTokenURI field. - * Should throw if called by other than owner - */ - function setGlobalBaseTokenURI(string calldata _URI) external; - - // Function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function to set the globalTokenSymbol field. - * Should throw if called by other than owner. - */ - function setGlobalTokenSymbol(string calldata _symbol) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal( - address indexed sender, - address indexed beneficiary, - uint amount - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // The account which will receive funds on withdrawal - address public beneficiary; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyOwnerOrBeneficiary() { - require( - msg.sender == owner() || msg.sender == beneficiary, - "ONLY_LOCK_OWNER_OR_BENEFICIARY" - ); - _; - } - - constructor( - address _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` use case. - */ - function withdraw(uint _amount) external onlyOwnerOrBeneficiary { - uint balance = getBalance(address(this)); - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(beneficiary, amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary( - address _beneficiary - ) external onlyOwnerOrBeneficiary { - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _owner) { - require(keyByOwner[_owner].expirationTimestamp > 0, "HAS_NEVER_OWNED_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_owner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasValidKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.9; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -contract UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) public pure returns (string memory _concatenatedString) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - string memory abcd = new string( - _ba.length + _bb.length + _bc.length + _bd.length - ); - bytes memory babcd = bytes(abcd); - uint k = 0; - uint i = 0; - for (i = 0; i < _ba.length; i++) { - babcd[k++] = _ba[i]; - } - for (i = 0; i < _bb.length; i++) { - babcd[k++] = _bb[i]; - } - for (i = 0; i < _bc.length; i++) { - babcd[k++] = _bc[i]; - } - for (i = 0; i < _bd.length; i++) { - babcd[k++] = _bd[i]; - } - return string(babcd); - } - - function uint2Str(uint _i) public pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721, - ERC165, - Ownable, - MixinLockCore, - UnlockUtils, - MixinKeys -{ - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string private lockName; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - constructor(string memory _lockName) internal { - lockName = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol(string calldata _lockSymbol) external onlyOwner { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.getGlobalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external onlyOwner { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.getGlobalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return - UnlockUtils.strConcat( - URI, - UnlockUtils.address2Str(address(this)), - "/", - UnlockUtils.uint2Str(_tokenId) - ); - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - - if (toKey.tokenId == 0) { - // Assign a new tokenId (if a new owner or previously transfered) - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - } - - if (toKey.expirationTimestamp >= block.timestamp) { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = toKey.expirationTimestamp.add( - expirationDuration - ); - } else { - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - - // We explicitly allow for greater amounts of ETH to allow 'donations' - // Security: last line to minimize risk of re-entrancy - _chargeAtLeast(netPrice); - } -} - -// File openzeppelin-solidity/contracts/cryptography/ECDSA.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * (.note) This call _does not revert_ if the signature is invalid, or - * if the signer is otherwise unable to be retrieved. In those scenarios, - * the zero address is returned. - * - * (.warning) `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise) - * be too long), and then calling `toEthSignedMessageHash` on it. - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) - * JSON-RPC method. - * - * See `recover`. - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.9; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyOwnerToNonce; - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - _cancelAndRefund(msg.sender); - } - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external { - require( - ECDSA.recover( - ECDSA.toEthSignedMessageHash( - getCancelAndRefundApprovalHash(_keyOwner, msg.sender) - ), - _signature - ) == _keyOwner, - "INVALID_SIGNATURE" - ); - - keyOwnerToNonce[_keyOwner]++; - _cancelAndRefund(_keyOwner); - } - - /** - * @dev Increments the current nonce for the msg.sender. - * This can be used to invalidate a previously signed message. - */ - function incrementNonce() external { - keyOwnerToNonce[msg.sender]++; - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // Approval enables only one cancel call - keyOwnerToNonce[_keyOwner], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner) internal { - Key storage key = _getKeyFor(_keyOwner); - - uint refund = _getCancelAndRefundValue(_keyOwner); - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Collection of functions related to the address type, - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing a contract. - * - * > It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - uint public transferFeeNumerator = 0; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - _chargeAtLeast(getTransferFee(_from)); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, toKey.tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _owner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _owner - ) public view hasValidKey(_owner) returns (uint) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - uint fee; - if (timeRemaining >= expirationDuration) { - // Max the potential impact of this fee for keys with long durations remaining - fee = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - fee = keyPrice.mul(timeRemaining) / expirationDuration; - } - return fee.mul(transferFeeNumerator) / transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.9; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IERC721, - MixinNoFallback, - ERC165, - Ownable, - ERC721Holder, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinGrantKeys, - MixinPurchase, - MixinApproval, - MixinTransfer, - MixinRefunds -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_owner, _expirationDuration, _keyPrice, _maxNumberOfKeys) - MixinLockMetadata(_lockName) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - // The version number of the current implementation on this network - function publicLockVersion() external pure returns (uint16) { - return 4; - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.9; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transfered for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, MixinNoFallback, Initializable, Ownable { - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string private globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string private globalTokenSymbol; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) public { - // create lock - address newLock = address( - new PublicLock( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ) - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me (discount tokens) - grossNetworkProduct += _value; - locks[msg.sender].totalSales += _value; - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 4; - } - - // function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory) { - return globalBaseTokenURI; - } - - // function to set the globalTokenURI field. - function setGlobalBaseTokenURI(string calldata _URI) external onlyOwner { - globalBaseTokenURI = _URI; - emit NewTokenURI(_URI); - } - - // function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory) { - return globalTokenSymbol; - } - - // function to set the globalTokenSymbol field. - function setGlobalTokenSymbol(string calldata _symbol) external onlyOwner { - globalTokenSymbol = _symbol; - emit NewGlobalTokenSymbol(_symbol); - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV5.sol b/packages/contracts/src/contracts/Unlock/UnlockV5.sol deleted file mode 100644 index 2ddc5ce892b..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV5.sol +++ /dev/null @@ -1,2 +0,0 @@ -// Error HH603: Hardhat flatten doesn't support cyclic dependencies. -// For more info go to https://hardhat.org/HH603 or run Hardhat with --show-stack-traces \ No newline at end of file diff --git a/packages/contracts/src/contracts/Unlock/UnlockV6.sol b/packages/contracts/src/contracts/Unlock/UnlockV6.sol deleted file mode 100644 index 31fe8739b11..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV6.sol +++ /dev/null @@ -1,1212 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.6.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.4.0 - -pragma solidity ^0.5.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 GSN 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. - */ -contract Context is Initializable { - // Empty internal constructor, to prevent people from mistakenly deploying - // an instance of this contract, which should be used via inheritance. - constructor() internal {} - - // solhint-disable-previous-line no-empty-blocks - - function _msgSender() internal view returns (address payable) { - return msg.sender; - } - - function _msgData() internal view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @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. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Initializable, Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return _msgSender() == _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 onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = 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 onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File hardlydifficult-ethereum-contracts/contracts/proxies/Clone2Factory.sol@v0.7.12 - -pragma solidity ^0.5.0; - -// From https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol -// Updated to support Solidity 5, switch to `create2` and revert on fail -library Clone2Factory { - /** - * @notice Uses create2 to deploy a clone to a pre-determined address. - * @param target the address of the template contract, containing the logic for this contract. - * @param salt a salt used to determine the contract address before the transaction is mined, - * may be random or sequential. - * @return proxyAddress the address of the newly deployed contract. - * @dev Using `bytes12` for the salt saves 6 gas over using `uint96` (requires another shift). - * Will revert on fail. - */ - function _createClone2( - address target, - bytes12 salt - ) internal returns (address proxyAddress) { - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - - // Create the bytecode for deployment based on the Minimal Proxy Standard (EIP-1167) - // bytecode: 0x0 - mstore( - pointer, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - mstore(add(pointer, 0x14), shl(96, target)) - mstore( - add(pointer, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - - // `create2` consumes all available gas if called with a salt that's already been consumed - // we check if the address is available first so that doesn't happen - // Costs ~958 gas - - // Calculate the hash - let contractCodeHash := keccak256(pointer, 0x37) - - // salt: 0x100 - // The salt to use with the create2 call is `msg.sender+salt` - // this prevents at attacker from front-running another user's deployment - mstore(add(pointer, 0x100), shl(96, caller)) - mstore(add(pointer, 0x114), salt) - - // addressSeed: 0x40 - // 0xff - mstore( - add(pointer, 0x40), - 0xff00000000000000000000000000000000000000000000000000000000000000 - ) - // this - mstore(add(pointer, 0x41), shl(96, address)) - // salt - mstore(add(pointer, 0x55), mload(add(pointer, 0x100))) - // hash - mstore(add(pointer, 0x75), contractCodeHash) - - proxyAddress := keccak256(add(pointer, 0x40), 0x55) - - switch extcodesize(proxyAddress) - case 0 { - // Deploy the contract, returning the address or 0 on fail - proxyAddress := create2(0, pointer, 0x37, mload(add(pointer, 0x100))) - } - default { - proxyAddress := 0 - } - } - - // Revert if the deployment fails (possible if salt was already used) - require(proxyAddress != address(0), "PROXY_DEPLOY_FAILED"); - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/IERC165.sol@v2.4.0 - -pragma solidity ^0.5.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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity ^0.5.0; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock is IERC721Enumerable { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Events - event Destroy(uint balance, address indexed owner); - - event Disable(); - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - event ExpireKey(uint indexed tokenId); - - event NewLockSymbol(string symbol); - - event TransferFeeChanged(uint transferFeeBasisPoints); - - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyOwner, uint nextAvailableNonce); - - ///=================================================================== - - /// Functions - - function initialize( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than the owner. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @notice Used to clean up old lock contracts from the blockchain. - * TODO: add a check to ensure all keys are INVALID! - * @dev Throws if called by other than owner. - * @dev Throws if lock has not yet been disabled. - */ - function destroyLock() external; - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than the owner or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `fullRefund` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - * @dev Throws if called by other than owner - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than owner of beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * A function which lets the owner of the lock expire a users' key. - * @dev Throws if called by other than lock owner - * @dev Throws if key owner does not have a valid key - * @param _owner The address of the key owner - */ - function expireKeyFor(address _owner) external; - - /** - * Checks if the user has a non-expired key. - * @param _owner The address of the key owner - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - * @dev Throws if key owner does not have a valid key - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _owner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - * @dev Throws if owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - * @dev Throws if called by other than the lock owner - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than the lock-owner - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * Allow the Lock owner to change the transfer fee. - * @dev Throws if called by other than lock-owner - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _owner does not have a valid key - * @param _owner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _owner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by the lock owner to destroy the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than owner - * @dev Throws if _keyOwner does not have a valid key - */ - function fullRefund(address _keyOwner, uint amount) external; - - /** - * @notice Destroys the msg.sender's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - uint8 _v, - bytes32 _r, - bytes32 _s - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow the owner to change the refund penalty. - * @dev Throws if called by other than owner - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _owner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - function keyOwnerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyOwner The key owner's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) external view returns (bytes32 approvalHash); - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function erc1820() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyCancelInterfaceId() external view returns (bytes32); - - function keySoldInterfaceId() external view returns (bytes32); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function BASIS_POINTS_DEN() external view returns (uint256); - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - function CANCEL_TYPEHASH() external view returns (bytes32); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From Openzeppelin's Ownable.sol - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function renounceOwnership() external; - - function transferOwnership(address newOwner) external; - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - ///=================================================================== -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.14; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address publicLockAddress, - string globalTokenSymbol, - string globalTokenURI - ); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock( - address _publicLockAddress, - string calldata _symbol, - string calldata _URI - ) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; -} - -// File contracts/interfaces/IUniswap.sol - -pragma solidity 0.5.14; - -/// @title Functions from the uniswap contract interface - -interface IUniswap { - function getTokenToEthInputPrice(uint tokens_sold) external returns (uint256); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.4.0 - -pragma solidity ^0.5.5; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing 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. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != 0x0 && codehash != accountHash); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.14; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transferred for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, Initializable, Ownable { - using Address for address; - using Clone2Factory for address; - - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string public globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string public globalTokenSymbol; - - // The address of the public lock template, used when `createLock` is called - address public publicLockAddress; - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - mapping(address => IUniswap) public uniswapExchanges; - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName, - bytes12 _salt - ) public { - require(publicLockAddress != address(0), "MISSING_LOCK_TEMPLATE"); - - // create lock - address newLock = publicLockAddress._createClone2(_salt); - IPublicLock(newLock).initialize( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - if (_value > 0) { - uint valueInETH; - address tokenAddress = IPublicLock(msg.sender).tokenAddress(); - if (tokenAddress != address(0)) { - // If priced in an ERC-20 token, find the supported uniswap exchange - IUniswap exchange = uniswapExchanges[tokenAddress]; - if (address(exchange) != address(0)) { - valueInETH = exchange.getTokenToEthInputPrice(_value); - } else { - // If the token type is not supported, assume 0 value - valueInETH = 0; - } - } else { - // If priced in ETH (or value is 0), no conversion is required - valueInETH = _value; - } - - grossNetworkProduct += valueInETH; - locks[msg.sender].totalSales += valueInETH; - } - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 6; - } - - // function for the owner to update configuration variables - function configUnlock( - address _publicLockAddress, - string calldata _symbol, - string calldata _URI - ) external onlyOwner { - // ensure that this is an address to which a contract has been deployed. - require(_publicLockAddress.isContract(), "NOT_A_CONTRACT"); - publicLockAddress = _publicLockAddress; - globalTokenSymbol = _symbol; - globalBaseTokenURI = _URI; - - emit ConfigUnlock(_publicLockAddress, _symbol, _URI); - } - - // allows the owner to set the exchange address to use for value conversions - // setting the _exchangeAddress to address(0) removes support for the token - function setExchange( - address _tokenAddress, - address _exchangeAddress - ) external onlyOwner { - uniswapExchanges[_tokenAddress] = IUniswap(_exchangeAddress); - } - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external onlyOwner { - grossNetworkProduct = _grossNetworkProduct; - totalDiscountGranted = _totalDiscountGranted; - - emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV7.sol b/packages/contracts/src/contracts/Unlock/UnlockV7.sol deleted file mode 100644 index 3270144a866..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV7.sol +++ /dev/null @@ -1,1438 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.7.1 - -pragma solidity >=0.4.24 <0.7.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.4.0 - -pragma solidity ^0.5.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 GSN 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. - */ -contract Context is Initializable { - // Empty internal constructor, to prevent people from mistakenly deploying - // an instance of this contract, which should be used via inheritance. - constructor() internal {} - - // solhint-disable-previous-line no-empty-blocks - - function _msgSender() internal view returns (address payable) { - return msg.sender; - } - - function _msgData() internal view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @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. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Initializable, Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return _msgSender() == _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 onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = 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 onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File hardlydifficult-ethereum-contracts/contracts/proxies/Clone2Factory.sol@v0.9.3 - -pragma solidity ^0.5.0; - -// From https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol -// Updated to support Solidity 5, switch to `create2` and revert on fail -library Clone2Factory { - /** - * @notice Uses create2 to deploy a clone to a pre-determined address. - * @param target the address of the template contract, containing the logic for this contract. - * @param salt a salt used to determine the contract address before the transaction is mined, - * may be random or sequential. - * @return proxyAddress the address of the newly deployed contract. - * @dev Using `bytes12` for the salt saves 6 gas over using `uint96` (requires another shift). - * Will revert on fail. - */ - function _createClone2( - address target, - bytes12 salt - ) internal returns (address proxyAddress) { - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - - // Create the bytecode for deployment based on the Minimal Proxy Standard (EIP-1167) - // bytecode: 0x0 - mstore( - pointer, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - mstore(add(pointer, 0x14), shl(96, target)) - mstore( - add(pointer, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - - // `create2` consumes all available gas if called with a salt that's already been consumed - // we check if the address is available first so that doesn't happen - // Costs ~958 gas - - // Calculate the hash - let contractCodeHash := keccak256(pointer, 0x37) - - // salt: 0x100 - // The salt to use with the create2 call is `msg.sender+salt` - // this prevents at attacker from front-running another user's deployment - mstore(add(pointer, 0x100), shl(96, caller)) - mstore(add(pointer, 0x114), salt) - - // addressSeed: 0x40 - // 0xff - mstore( - add(pointer, 0x40), - 0xff00000000000000000000000000000000000000000000000000000000000000 - ) - // this - mstore(add(pointer, 0x41), shl(96, address)) - // salt - mstore(add(pointer, 0x55), mload(add(pointer, 0x100))) - // hash - mstore(add(pointer, 0x75), contractCodeHash) - - proxyAddress := keccak256(add(pointer, 0x40), 0x55) - - switch extcodesize(proxyAddress) - case 0 { - // Deploy the contract, returning the address or 0 on fail - proxyAddress := create2(0, pointer, 0x37, mload(add(pointer, 0x100))) - } - default { - proxyAddress := 0 - } - } - - // Revert if the deployment fails (possible if salt was already used) - require(proxyAddress != address(0), "PROXY_DEPLOY_FAILED"); - } -} - -// File hardlydifficult-ethereum-contracts/contracts/interfaces/IUniswapExchange.sol@v0.9.3 - -pragma solidity ^0.5.0; - -// Source: https://github.com/Uniswap/contracts-vyper/blob/master/contracts/uniswap_exchange.vy -// The fallback function is payable and calls `ethToTokenInput` -interface IUniswapExchange { - // Events - event AddLiquidity( - address indexed provider, - uint indexed eth_amount, - uint indexed token_amount - ); - event Approval(address indexed _owner, address indexed _spender, uint _value); - event EthPurchase( - address indexed buyer, - uint indexed tokens_sold, - uint eth_bought - ); - event RemoveLiquidity( - address indexed provider, - uint indexed eth_amount, - uint indexed token_amount - ); - event TokenPurchase( - address indexed buyer, - uint indexed eth_sold, - uint indexed tokens_bought - ); - event Transfer(address indexed _from, address indexed _to, uint _value); - - // Read-only - function allowance( - address _owner, - address _spender - ) external view returns (uint); - - function balanceOf(address _owner) external view returns (uint); - - function decimals() external view returns (uint); - - function factoryAddress() external view returns (address); - - function getEthToTokenInputPrice(uint eth_sold) external view returns (uint); - - function getEthToTokenOutputPrice( - uint tokens_bought - ) external view returns (uint); - - function getTokenToEthInputPrice( - uint tokens_sold - ) external view returns (uint); - - function getTokenToEthOutputPrice( - uint eth_bought - ) external view returns (uint); - - function name() external view returns (bytes32); - - function symbol() external view returns (bytes32); - - function tokenAddress() external view returns (address); - - function totalSupply() external view returns (uint); - - // Transactions - function setup(address token_addr) external; - - function addLiquidity( - uint min_liquidity, - uint max_tokens, - uint deadline - ) external payable returns (uint); - - function removeLiquidity( - uint amount, - uint min_eth, - uint min_tokens, - uint deadline - ) external returns (uint, uint); - - function ethToTokenSwapInput( - uint min_tokens, - uint deadline - ) external payable returns (uint); - - function ethToTokenTransferInput( - uint min_tokens, - uint deadline, - address recipient - ) external payable returns (uint); - - function ethToTokenSwapOutput( - uint tokens_bought, - uint deadline - ) external payable returns (uint); - - function ethToTokenTransferOutput( - uint tokens_bought, - uint deadline, - address recipient - ) external payable returns (uint); - - function tokenToEthSwapInput( - uint tokens_sold, - uint min_eth, - uint deadline - ) external returns (uint); - - function tokenToEthTransferInput( - uint tokens_sold, - uint min_eth, - uint deadline, - address recipient - ) external returns (uint); - - function tokenToEthSwapOutput( - uint eth_bought, - uint max_tokens, - uint deadline - ) external returns (uint); - - function tokenToEthTransferOutput( - uint eth_bought, - uint max_tokens, - uint deadline, - address recipient - ) external returns (uint); - - function tokenToTokenSwapInput( - uint tokens_sold, - uint min_tokens_bought, - uint min_eth_bought, - uint deadline, - address token_addr - ) external returns (uint); - - function tokenToTokenTransferInput( - uint tokens_sold, - uint min_tokens_bought, - uint min_eth_bought, - uint deadline, - address recipient, - address token_addr - ) external returns (uint); - - function tokenToTokenSwapOutput( - uint tokens_bought, - uint max_tokens_sold, - uint max_eth_sold, - uint deadline, - address token_addr - ) external returns (uint); - - function tokenToTokenTransferOutput( - uint tokens_bought, - uint max_tokens_sold, - uint max_eth_sold, - uint deadline, - address recipient, - address token_addr - ) external returns (uint); - - function tokenToExchangeSwapInput( - uint tokens_sold, - uint min_tokens_bought, - uint min_eth_bought, - uint deadline, - address exchange_addr - ) external returns (uint); - - function tokenToExchangeTransferInput( - uint tokens_sold, - uint min_tokens_bought, - uint min_eth_bought, - uint deadline, - address recipient, - address exchange_addr - ) external returns (uint); - - function tokenToExchangeSwapOutput( - uint tokens_bought, - uint max_tokens_sold, - uint max_eth_sold, - uint deadline, - address exchange_addr - ) external returns (uint); - - function tokenToExchangeTransferOutput( - uint tokens_bought, - uint max_tokens_sold, - uint max_eth_sold, - uint deadline, - address recipient, - address exchange_addr - ) external returns (uint); - - function transfer(address _to, uint _value) external returns (bool); - - function transferFrom( - address _from, - address _to, - uint _value - ) external returns (bool); - - function approve(address _spender, uint _value) external returns (bool); -} - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock(string calldata _symbol, string calldata _URI) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapExchanges(address) external view returns (address); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - // allows the owner to set the exchange address to use for value conversions - // setting the _exchangeAddress to address(0) removes support for the token - function setExchange( - address _tokenAddress, - address _exchangeAddress - ) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.4.0 - -pragma solidity ^0.5.5; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing 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. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != 0x0 && codehash != accountHash); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transferred for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, Initializable, Ownable { - using Address for address; - using Clone2Factory for address; - - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string public globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string public globalTokenSymbol; - - // The address of the public lock template, used when `createLock` is called - address public publicLockAddress; - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - mapping(address => IUniswapExchange) public uniswapExchanges; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock(string globalTokenSymbol, string globalTokenURI); - - event SetLockTemplate(address publicLockAddress); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _unlockOwner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_unlockOwner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName, - bytes12 _salt - ) public { - require(publicLockAddress != address(0), "MISSING_LOCK_TEMPLATE"); - - // create lock - address payable newLock = address( - uint160(publicLockAddress._createClone2(_salt)) - ); - IPublicLock(newLock).initialize( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address /* _purchaser */, - uint /* _keyPrice */ - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address /* _referrer */ - ) public onlyFromDeployedLock { - if (_value > 0) { - uint valueInETH; - address tokenAddress = IPublicLock(msg.sender).tokenAddress(); - if (tokenAddress != address(0)) { - // If priced in an ERC-20 token, find the supported uniswap exchange - IUniswapExchange exchange = uniswapExchanges[tokenAddress]; - if (address(exchange) != address(0)) { - valueInETH = exchange.getTokenToEthInputPrice(_value); - } else { - // If the token type is not supported, assume 0 value - valueInETH = 0; - } - } else { - // If priced in ETH (or value is 0), no conversion is required - valueInETH = _value; - } - - grossNetworkProduct += valueInETH; - locks[msg.sender].totalSales += valueInETH; - } - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint /* _tokens */ - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 7; - } - - // function for the owner to update configuration variables - function configUnlock( - string calldata _symbol, - string calldata _URI - ) external onlyOwner { - // ensure that this is an address to which a contract has been deployed. - globalTokenSymbol = _symbol; - globalBaseTokenURI = _URI; - - emit ConfigUnlock(_symbol, _URI); - } - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate( - address payable _publicLockAddress - ) external onlyOwner { - // First claim the template so that no-one else could - // this will revert if the template was already initialized. - IPublicLock(_publicLockAddress).initialize( - address(this), - 0, - address(0), - 0, - 0, - "" - ); - IPublicLock(_publicLockAddress).renounceLockManager(); - - publicLockAddress = _publicLockAddress; - - emit SetLockTemplate(_publicLockAddress); - } - - // allows the owner to set the exchange address to use for value conversions - // setting the _exchangeAddress to address(0) removes support for the token - function setExchange( - address _tokenAddress, - address _exchangeAddress - ) external onlyOwner { - uniswapExchanges[_tokenAddress] = IUniswapExchange(_exchangeAddress); - } - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external onlyOwner { - grossNetworkProduct = _grossNetworkProduct; - totalDiscountGranted = _totalDiscountGranted; - - emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); - } - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory) { - return globalBaseTokenURI; - } - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory) { - return globalTokenSymbol; - } -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV8.sol b/packages/contracts/src/contracts/Unlock/UnlockV8.sol deleted file mode 100644 index 44771ea8a1d..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV8.sol +++ /dev/null @@ -1,1540 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.8.0 - -pragma solidity >=0.4.24 <0.7.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.5.0 - -pragma solidity ^0.5.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 GSN 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. - */ -contract Context is Initializable { - // Empty internal constructor, to prevent people from mistakenly deploying - // an instance of this contract, which should be used via inheritance. - constructor() internal {} - - // solhint-disable-previous-line no-empty-blocks - - function _msgSender() internal view returns (address payable) { - return msg.sender; - } - - function _msgData() internal view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @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. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Initializable, Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return _msgSender() == _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 onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = 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 onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File hardlydifficult-ethereum-contracts/contracts/proxies/Clone2Factory.sol@v0.11.1 - -pragma solidity ^0.5.0; - -// From https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol -// Updated to support Solidity 5, switch to `create2` and revert on fail -library Clone2Factory { - /** - * @notice Uses create2 to deploy a clone to a pre-determined address. - * @param target the address of the template contract, containing the logic for this contract. - * @param salt a salt used to determine the contract address before the transaction is mined, - * may be random or sequential. - * The salt to use with the create2 call can be `msg.sender+salt` in order to - * prevent an attacker from front-running another user's deployment. - * @return proxyAddress the address of the newly deployed contract. - * @dev Using `bytes12` for the salt saves 6 gas over using `uint96` (requires another shift). - * Will revert on fail. - */ - function createClone2( - address target, - bytes32 salt - ) internal returns (address proxyAddress) { - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - - // Create the bytecode for deployment based on the Minimal Proxy Standard (EIP-1167) - // bytecode: 0x0 - mstore( - pointer, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - mstore(add(pointer, 0x14), shl(96, target)) - mstore( - add(pointer, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - - // `create2` consumes all available gas if called with a salt that's already been consumed - // we check if the address is available first so that doesn't happen - // Costs ~958 gas - - // Calculate the hash - let contractCodeHash := keccak256(pointer, 0x37) - - // salt: 0x100 - mstore(add(pointer, 0x100), salt) - - // addressSeed: 0x40 - // 0xff - mstore( - add(pointer, 0x40), - 0xff00000000000000000000000000000000000000000000000000000000000000 - ) - // this - mstore(add(pointer, 0x41), shl(96, address)) - // salt - mstore(add(pointer, 0x55), mload(add(pointer, 0x100))) - // hash - mstore(add(pointer, 0x75), contractCodeHash) - - proxyAddress := keccak256(add(pointer, 0x40), 0x55) - - switch extcodesize(proxyAddress) - case 0 { - // Deploy the contract, returning the address or 0 on fail - proxyAddress := create2(0, pointer, 0x37, mload(add(pointer, 0x100))) - } - default { - proxyAddress := 0 - } - } - - // Revert if the deployment fails (possible if salt was already used) - require(proxyAddress != address(0), "PROXY_DEPLOY_FAILED"); - } -} - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI - ) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.5.0 - -pragma solidity ^0.5.5; - -/** - * @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 - * ==== - */ - function isContract(address account) internal view returns (bool) { - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != accountHash && codehash != 0x0); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File hardlydifficult-eth/contracts/protocols/Uniswap/IUniswapOracle.sol@v1.1.1 - -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0; - -interface IUniswapOracle { - function PERIOD() external returns (uint); - - function factory() external returns (address); - - function update(address _tokenIn, address _tokenOut) external; - - function consult( - address _tokenIn, - uint _amountIn, - address _tokenOut - ) external view returns (uint _amountOut); - - function updateAndConsult( - address _tokenIn, - uint _amountIn, - address _tokenOut - ) external returns (uint _amountOut); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - * - * _Available since v2.4.0._ - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} - -// File contracts/interfaces/IMintableERC20.sol - -pragma solidity 0.5.17; - -interface IMintableERC20 { - function mint(address account, uint256 amount) external returns (bool); - - function totalSupply() external returns (uint); -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transferred for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, Initializable, Ownable { - using Address for address; - using Clone2Factory for address; - using SafeMath for uint; - - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string public globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string public globalTokenSymbol; - - // The address of the public lock template, used when `createLock` is called - address public publicLockAddress; - - // Map token address to oracle contract address if the token is supported - // Used for GDP calculations - mapping(address => IUniswapOracle) public uniswapOracles; - - // The WETH token address, used for value calculations - address public weth; - - // The UDT token address, used to mint tokens on referral - address public udt; - - // The approx amount of gas required to purchase a key - uint public estimatedGasForPurchase; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address udt, - address weth, - uint estimatedGasForPurchase, - string globalTokenSymbol, - string globalTokenURI - ); - - event SetLockTemplate(address publicLockAddress); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _unlockOwner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_unlockOwner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName, - bytes12 _salt - ) public { - require(publicLockAddress != address(0), "MISSING_LOCK_TEMPLATE"); - - // create lock - bytes32 salt; - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - // The salt is the msg.sender - mstore(pointer, shl(96, caller)) - // followed by the _salt provided - mstore(add(pointer, 0x14), _salt) - salt := mload(pointer) - } - address payable newLock = address( - uint160(publicLockAddress.createClone2(salt)) - ); - IPublicLock(newLock).initialize( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address /* _purchaser */, - uint /* _keyPrice */ - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer - ) public onlyFromDeployedLock { - if (_value > 0) { - uint valueInETH; - address tokenAddress = IPublicLock(msg.sender).tokenAddress(); - if (tokenAddress != address(0) && tokenAddress != weth) { - // If priced in an ERC-20 token, find the supported uniswap oracle - IUniswapOracle oracle = uniswapOracles[tokenAddress]; - if (address(oracle) != address(0)) { - valueInETH = oracle.updateAndConsult(tokenAddress, _value, weth); - } - } else { - // If priced in ETH (or value is 0), no conversion is required - valueInETH = _value; - } - - grossNetworkProduct = grossNetworkProduct.add(valueInETH); - // If GNP does not overflow, the lock totalSales should be safe - locks[msg.sender].totalSales += valueInETH; - - // Mint UDT - if (_referrer != address(0)) { - IUniswapOracle udtOracle = uniswapOracles[udt]; - if (address(udtOracle) != address(0)) { - // Get the value of 1 UDT (w/ 18 decimals) in ETH - uint udtPrice = udtOracle.updateAndConsult(udt, 10 ** 18, weth); - - // tokensToMint is either == to the gas cost times 1.25 to cover the 20% dev cut - uint tokensToMint = (estimatedGasForPurchase * tx.gasprice).mul( - 125 * 10 ** 18 - ) / - 100 / - udtPrice; - // or tokensToMint is capped by percent growth - uint maxTokens = IMintableERC20(udt).totalSupply().mul(valueInETH) / - 2 / - grossNetworkProduct; - if (tokensToMint > maxTokens) { - tokensToMint = maxTokens; - } - - if (tokensToMint > 0) { - // 80% goes to the referrer, 20% to the Unlock dev - round in favor of the referrer - uint devReward = tokensToMint.mul(20) / 100; - IMintableERC20(udt).mint(_referrer, tokensToMint - devReward); - if (devReward > 0) { - IMintableERC20(udt).mint(owner(), devReward); - } - } - } - } - } - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint /* _tokens */ - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 8; - } - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI - ) external onlyOwner { - udt = _udt; - weth = _weth; - estimatedGasForPurchase = _estimatedGasForPurchase; - - globalTokenSymbol = _symbol; - globalBaseTokenURI = _URI; - - emit ConfigUnlock(_udt, _weth, _estimatedGasForPurchase, _symbol, _URI); - } - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate( - address payable _publicLockAddress - ) external onlyOwner { - // First claim the template so that no-one else could - // this will revert if the template was already initialized. - IPublicLock(_publicLockAddress).initialize( - address(this), - 0, - address(0), - 0, - 0, - "" - ); - IPublicLock(_publicLockAddress).renounceLockManager(); - - publicLockAddress = _publicLockAddress; - - emit SetLockTemplate(_publicLockAddress); - } - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle( - address _tokenAddress, - address _oracleAddress - ) external onlyOwner { - uniswapOracles[_tokenAddress] = IUniswapOracle(_oracleAddress); - if (_oracleAddress != address(0)) { - IUniswapOracle(_oracleAddress).update(_tokenAddress, weth); - } - } - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external onlyOwner { - grossNetworkProduct = _grossNetworkProduct; - totalDiscountGranted = _totalDiscountGranted; - - emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); - } - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory) { - return globalBaseTokenURI; - } - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory) { - return globalTokenSymbol; - } -} From feb0450020472cab2f436d2a500129c65213b7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Thu, 20 Jun 2024 17:48:06 +0200 Subject: [PATCH 03/27] add script to check versions --- governance/helpers/subgraph.js | 31 +++++ governance/scripts/lock/listManagers.js | 28 +---- governance/scripts/lock/outdated.js | 145 ++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 governance/helpers/subgraph.js create mode 100644 governance/scripts/lock/outdated.js diff --git a/governance/helpers/subgraph.js b/governance/helpers/subgraph.js new file mode 100644 index 00000000000..5928244c911 --- /dev/null +++ b/governance/helpers/subgraph.js @@ -0,0 +1,31 @@ +const { networks } = require('@unlock-protocol/networks') + +const fetchFromSubgraph = async ({ chainId, query }) => { + const { subgraph } = networks[chainId] + + if (!subgraph || !subgraph.endpoint) { + console.log( + 'Missing subGraphURI for this network. Can not fetch from The Graph' + ) + return [] + } + + const q = await fetch(subgraph.endpoint, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + query, + }), + }) + + const { data, errors } = await q.json() + if (errors) { + console.log('SUBGRAPH > [Error] while fetching the graph', errors) + return [] + } + return data +} + +module.exports = { + fetchFromSubgraph, +} diff --git a/governance/scripts/lock/listManagers.js b/governance/scripts/lock/listManagers.js index ab1823c3123..81cb376ea79 100644 --- a/governance/scripts/lock/listManagers.js +++ b/governance/scripts/lock/listManagers.js @@ -1,19 +1,11 @@ const { ethers } = require('hardhat') -const { networks } = require('@unlock-protocol/networks') +const { fetchFromSubgraph } = require('../../helpers/subgraph') async function main({ lockAddress }) { const PublicLock = await ethers.getContractFactory('PublicLock') const lock = PublicLock.attach(lockAddress) const { chainId } = await ethers.provider.getNetwork() - const { subgraph } = networks[chainId] - - if (!subgraph || !subgraph.endpoint) { - console.log( - 'Missing subGraphURI for this network. Can not fetch from The Graph' - ) - return [] - } const query = ` { @@ -27,25 +19,11 @@ async function main({ lockAddress }) { } ` - const q = await fetch(subgraph.endpoint, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - query, - }), - }) - - const { data, errors } = await q.json() - if (errors) { - console.log('LOCK > Error while fetching the graph', errors) - return [] - } - const { locks: [{ LockManagers }], - } = data - const managers = LockManagers.map((m) => m.address) + } = await fetchFromSubgraph({ chainId, query }) + const managers = LockManagers.map((m) => m.address) console.log( `LOCK > managers for the lock '${await lock.name()}' (${lockAddress}):` ) diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js new file mode 100644 index 00000000000..bbaf66dc176 --- /dev/null +++ b/governance/scripts/lock/outdated.js @@ -0,0 +1,145 @@ +const { fetchFromSubgraph } = require('../../helpers/subgraph') +const { networks } = require('@unlock-protocol/networks') + +async function getAllReceipts({ timeLimit, chainId }) { + const limit = 1000 + let skip = 0 + let more = true + const receipts = [] + while (more) { + // console.log(`fetching results from ${skip} to ${limit}`) + const receiptsQuery = ` + { + receipts( + skip: ${skip} + first: ${limit} + where:{ + timestamp_gte: ${timeLimit} + } + ) { + lockAddress + } + } +` + const { receipts: results } = await fetchFromSubgraph({ + chainId, + query: receiptsQuery, + }) + + if (results.length < limit) { + more = false + } else { + skip += limit + } + receipts.push(...results) + } + return receipts +} + +async function getLockVersions({ chainId, lockAddresses }) { + const versionsQuery = ` + { + locks( + orderBy: version + sortDirection: DESC + where:{ + address_in: ${JSON.stringify(lockAddresses)} + + } + ) { + version + address + } + } + ` + + const { locks } = await fetchFromSubgraph({ + chainId, + query: versionsQuery, + }) + + // append chainId + return locks.map((lock) => ({ ...lock, chainId })) +} + +async function getAllLockVersionInfo({ chainId, timeLimit }) { + // get all receipts before the date + const receipts = await getAllReceipts({ chainId, timeLimit }) + + // parse all addresses + const lockAddresses = receipts + .map(({ lockAddress }) => lockAddress) + .reduce((prev, curr) => (!prev.includes(curr) ? [...prev, curr] : prev), []) + + // get all receipts before the date + const versions = await getLockVersions({ chainId, lockAddresses }) + const count = versions.reduce( + (prev, { version }) => ((prev[version] = (prev[version] || 0) + 1), prev), + {} + ) + const earliest = Object.keys(count)[0] + const earliestLocks = versions.filter(({ version }) => version == earliest) + return { + chainId, + receipts, + lockAddresses, + earliest, + earliestLocks, + count, + } +} + +function logLocks({ + chainId, + receipts, + lockAddresses, + earliest, + earliestLocks, + count, +}) { + const { name } = networks[chainId] + console.log( + `${name} (${chainId}): + - receipts: ${receipts.length} + - locks: ${lockAddresses.length} unique lock addresses + - earliest version ${earliest} + - earliest ${earliestLocks.length} locks + - versions: ${Object.keys(count) + .map((v) => `v${v}:${count[v]}`) + .join(',')} + ` + ) +} + +async function main() { + const timeLimit = new Date('2022-01-01').getTime() / 1000 + + const chains = Object.keys(networks).filter( + (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork + ) + console.log(`Chains: ${chains.join(',')} `) + const infos = {} + await Promise.all( + chains.map(async (chainId) => { + try { + const info = await getAllLockVersionInfo({ chainId, timeLimit }) + infos[chainId] = info + logLocks(info) + } catch (error) { + console.log(`Couldn't fetch chain ${chainId}: ${error.message}`) + } + }) + ) +} + +// execute as standalone +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +} + +module.exports = main From a509d0151eb521abcf430c246a26dc270feb3f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Thu, 20 Jun 2024 17:51:53 +0200 Subject: [PATCH 04/27] show addresses --- governance/scripts/lock/outdated.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index bbaf66dc176..09c4cfc5223 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -103,7 +103,7 @@ function logLocks({ - receipts: ${receipts.length} - locks: ${lockAddresses.length} unique lock addresses - earliest version ${earliest} - - earliest ${earliestLocks.length} locks + - earliest ${earliestLocks.length} locks (${parseInt(earliest) < 9 ? earliestLocks.map(({ address }) => address).join(',') : ''}) - versions: ${Object.keys(count) .map((v) => `v${v}:${count[v]}`) .join(',')} From ddacc53ff7f94307fccb17b6a1b97a1abb6c4d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Thu, 20 Jun 2024 17:53:35 +0200 Subject: [PATCH 05/27] show date --- governance/scripts/lock/outdated.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index 09c4cfc5223..676d5f07de2 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -111,8 +111,9 @@ function logLocks({ ) } -async function main() { - const timeLimit = new Date('2022-01-01').getTime() / 1000 +async function main({ deadline = '2022-01-01' } = {}) { + console.log(`Before ${deadline}`) + const timeLimit = new Date(deadline).getTime() / 1000 const chains = Object.keys(networks).filter( (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork From 2d28a7b9182305ef1b634cea774a291e67450d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Thu, 20 Jun 2024 17:53:50 +0200 Subject: [PATCH 06/27] ignore logs --- governance/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/governance/.gitignore b/governance/.gitignore index 8821e7a8def..f1767c02748 100644 --- a/governance/.gitignore +++ b/governance/.gitignore @@ -10,4 +10,5 @@ artifacts-zk cache-zk .openzeppelin -xcalled.tmp.json \ No newline at end of file +xcalled.tmp.json +*.log \ No newline at end of file From ce461c0fb6b1c693df93f42698e35db353e56a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Wed, 14 Aug 2024 12:11:54 +0200 Subject: [PATCH 07/27] use `lastKeyMintedAt` subgraph query --- governance/helpers/subgraph.js | 1 + governance/scripts/lock/outdated.js | 85 +++++++++-------------------- 2 files changed, 28 insertions(+), 58 deletions(-) diff --git a/governance/helpers/subgraph.js b/governance/helpers/subgraph.js index 5928244c911..3862e43da74 100644 --- a/governance/helpers/subgraph.js +++ b/governance/helpers/subgraph.js @@ -9,6 +9,7 @@ const fetchFromSubgraph = async ({ chainId, query }) => { ) return [] } + console.log(subgraph.endpoint) const q = await fetch(subgraph.endpoint, { method: 'POST', diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index 676d5f07de2..a623487db65 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -1,7 +1,7 @@ const { fetchFromSubgraph } = require('../../helpers/subgraph') const { networks } = require('@unlock-protocol/networks') -async function getAllReceipts({ timeLimit, chainId }) { +async function getAllActiveLocks({ timeLimit, chainId }) { const limit = 1000 let skip = 0 let more = true @@ -10,14 +10,22 @@ async function getAllReceipts({ timeLimit, chainId }) { // console.log(`fetching results from ${skip} to ${limit}`) const receiptsQuery = ` { - receipts( + locks( skip: ${skip} first: ${limit} where:{ - timestamp_gte: ${timeLimit} + or : [ + { + lastKeyMintedAt_gte: ${BigInt(timeLimit)} + }, + { + lastKeyRenewedAt_gte: ${BigInt(timeLimit)} + } + ] } - ) { - lockAddress + ) { + address + version } } ` @@ -36,72 +44,31 @@ async function getAllReceipts({ timeLimit, chainId }) { return receipts } -async function getLockVersions({ chainId, lockAddresses }) { - const versionsQuery = ` - { - locks( - orderBy: version - sortDirection: DESC - where:{ - address_in: ${JSON.stringify(lockAddresses)} - - } - ) { - version - address - } - } - ` - - const { locks } = await fetchFromSubgraph({ - chainId, - query: versionsQuery, - }) - - // append chainId - return locks.map((lock) => ({ ...lock, chainId })) -} - async function getAllLockVersionInfo({ chainId, timeLimit }) { - // get all receipts before the date - const receipts = await getAllReceipts({ chainId, timeLimit }) - - // parse all addresses - const lockAddresses = receipts - .map(({ lockAddress }) => lockAddress) - .reduce((prev, curr) => (!prev.includes(curr) ? [...prev, curr] : prev), []) + // get all locks that still have at least 1 key minted or renewed before the deadline + const activeLocks = await getAllActiveLocks({ chainId, timeLimit }) - // get all receipts before the date - const versions = await getLockVersions({ chainId, lockAddresses }) - const count = versions.reduce( + // count by versions + const count = activeLocks.reduce( (prev, { version }) => ((prev[version] = (prev[version] || 0) + 1), prev), {} ) const earliest = Object.keys(count)[0] - const earliestLocks = versions.filter(({ version }) => version == earliest) + const earliestLocks = activeLocks.filter(({ version }) => version == earliest) return { chainId, - receipts, - lockAddresses, - earliest, + activeLocks, earliestLocks, + earliest, count, } } -function logLocks({ - chainId, - receipts, - lockAddresses, - earliest, - earliestLocks, - count, -}) { +function logLocks({ chainId, activeLocks, earliest, earliestLocks, count }) { const { name } = networks[chainId] console.log( `${name} (${chainId}): - - receipts: ${receipts.length} - - locks: ${lockAddresses.length} unique lock addresses + - locks: ${activeLocks.length} unique locks - earliest version ${earliest} - earliest ${earliestLocks.length} locks (${parseInt(earliest) < 9 ? earliestLocks.map(({ address }) => address).join(',') : ''}) - versions: ${Object.keys(count) @@ -115,9 +82,11 @@ async function main({ deadline = '2022-01-01' } = {}) { console.log(`Before ${deadline}`) const timeLimit = new Date(deadline).getTime() / 1000 - const chains = Object.keys(networks).filter( - (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork - ) + // const chains = Object.keys(networks).filter( + // (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork + // ) + const chains = [1] + console.log(`Chains: ${chains.join(',')} `) const infos = {} await Promise.all( From 7ab90c81278e42a70a8a1606697fb2a8b387c148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 16 Aug 2024 21:43:34 +0200 Subject: [PATCH 08/27] proper locks versions breakdown --- governance/helpers/subgraph.js | 1 - governance/scripts/lock/outdated.js | 12 +++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/governance/helpers/subgraph.js b/governance/helpers/subgraph.js index 3862e43da74..5928244c911 100644 --- a/governance/helpers/subgraph.js +++ b/governance/helpers/subgraph.js @@ -9,7 +9,6 @@ const fetchFromSubgraph = async ({ chainId, query }) => { ) return [] } - console.log(subgraph.endpoint) const q = await fetch(subgraph.endpoint, { method: 'POST', diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index a623487db65..c5bbc84a4a8 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -29,7 +29,7 @@ async function getAllActiveLocks({ timeLimit, chainId }) { } } ` - const { receipts: results } = await fetchFromSubgraph({ + const { locks: results } = await fetchFromSubgraph({ chainId, query: receiptsQuery, }) @@ -70,7 +70,6 @@ function logLocks({ chainId, activeLocks, earliest, earliestLocks, count }) { `${name} (${chainId}): - locks: ${activeLocks.length} unique locks - earliest version ${earliest} - - earliest ${earliestLocks.length} locks (${parseInt(earliest) < 9 ? earliestLocks.map(({ address }) => address).join(',') : ''}) - versions: ${Object.keys(count) .map((v) => `v${v}:${count[v]}`) .join(',')} @@ -79,13 +78,12 @@ function logLocks({ chainId, activeLocks, earliest, earliestLocks, count }) { } async function main({ deadline = '2022-01-01' } = {}) { - console.log(`Before ${deadline}`) + console.log(`locks before ${deadline}`) const timeLimit = new Date(deadline).getTime() / 1000 - // const chains = Object.keys(networks).filter( - // (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork - // ) - const chains = [1] + const chains = Object.keys(networks).filter( + (id) => !isNaN(parseInt(id)) && !networks[id].isTestNetwork + ) console.log(`Chains: ${chains.join(',')} `) const infos = {} From 7e902b10195847fa9b4d7482eebd23c1a76e0d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 16 Aug 2024 23:02:51 +0200 Subject: [PATCH 09/27] fix output --- governance/scripts/deployments/lock.js | 1 - governance/scripts/lock/outdated.js | 116 ++++++++++++++++++++----- packages/hardhat-helpers/src/fork.js | 12 +-- packages/hardhat-helpers/src/lock.js | 4 +- 4 files changed, 104 insertions(+), 29 deletions(-) diff --git a/governance/scripts/deployments/lock.js b/governance/scripts/deployments/lock.js index 83a47e4ed05..505a8343dba 100644 --- a/governance/scripts/deployments/lock.js +++ b/governance/scripts/deployments/lock.js @@ -3,7 +3,6 @@ const contracts = require('@unlock-protocol/contracts') const { createLockCalldata, getEvent, - getLockVersion, } = require('@unlock-protocol/hardhat-helpers') const toBigNumber = (mayBN) => BigInt(mayBN.toString()) diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index c5bbc84a4a8..55f68f7e357 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -1,7 +1,45 @@ const { fetchFromSubgraph } = require('../../helpers/subgraph') +const { getProvider } = require('../../helpers/multisig') +const contracts = require('@unlock-protocol/contracts') + const { networks } = require('@unlock-protocol/networks') +const { Contract, formatUnits } = require('ethers') +const { + ADDRESS_ZERO, + getERC20Contract, + getNetwork, +} = require('@unlock-protocol/hardhat-helpers') + +async function getLockBalance({ chainId, lock }) { + const { provider } = await getProvider(chainId) + const { nativeCurrency } = await getNetwork(chainId) + + // check native + const balanceNative = await provider.getBalance(lock.address) + + // check ERC20 + const { abi } = contracts[`PublicLockV${lock.version}`] + const lockContract = new Contract(lock.address, abi, provider) + const tokenAddress = await lockContract.tokenAddress() -async function getAllActiveLocks({ timeLimit, chainId }) { + let balanceToken = 0n + let balanceTokenParsed = '' + if (tokenAddress !== ADDRESS_ZERO) { + const token = await getERC20Contract(tokenAddress, provider) + const decimals = await token.decimals() + balanceToken = await token.balanceOf(lock.address) + balanceTokenParsed = `${formatUnits(balanceToken, decimals)} ${await token.symbol()}` + } + return { + chainId, + ...lock, + balanceNative, + balanceToken, + balanceFormatted: `${balanceToken === 0n ? '' : balanceTokenParsed} ${balanceNative === 0n ? '' : `${formatUnits(balanceNative, 18)} ${nativeCurrency.symbol}`}`, + } +} + +async function fetchAllActiveLocks({ timeLimit, chainId }) { const limit = 1000 let skip = 0 let more = true @@ -26,6 +64,7 @@ async function getAllActiveLocks({ timeLimit, chainId }) { ) { address version + lastKeyMintedAt } } ` @@ -44,36 +83,70 @@ async function getAllActiveLocks({ timeLimit, chainId }) { return receipts } -async function getAllLockVersionInfo({ chainId, timeLimit }) { - // get all locks that still have at least 1 key minted or renewed before the deadline - const activeLocks = await getAllActiveLocks({ chainId, timeLimit }) - - // count by versions - const count = activeLocks.reduce( +const count = (locks) => + locks.reduce( (prev, { version }) => ((prev[version] = (prev[version] || 0) + 1), prev), {} ) + +async function getAllLocks({ chainId, timeLimit }) { + // get all locks that still have at least 1 key minted or renewed before the deadline + const activeLocks = await fetchAllActiveLocks({ chainId, timeLimit }) + + // count by versions + const versionCount = count(activeLocks) const earliest = Object.keys(count)[0] - const earliestLocks = activeLocks.filter(({ version }) => version == earliest) + + // check balance on the earliest locks + const earlyLocks = ( + await Promise.all( + activeLocks + .filter(({ version }) => version <= 9) + .map((lock) => getLockBalance({ chainId, lock })) + ) + ) + .filter( + ({ balanceNative, balanceToken }) => + balanceNative !== 0n || balanceToken !== 0n + ) + .sort(({ version: a }, { version: b }) => b - a) + return { chainId, activeLocks, - earliestLocks, earliest, - count, + versions: versionCount, + earlyLocks, } } -function logLocks({ chainId, activeLocks, earliest, earliestLocks, count }) { +function logLocks({ chainId, activeLocks, earliest, earlyLocks, versions }) { const { name } = networks[chainId] console.log( - `${name} (${chainId}): - - locks: ${activeLocks.length} unique locks - - earliest version ${earliest} - - versions: ${Object.keys(count) - .map((v) => `v${v}:${count[v]}`) + `## ${name} (${chainId}): + +- **locks**: ${activeLocks.length} unique locks +- **earliest version**: ${earliest} +- **versions**: ${Object.keys(versions) + .map((v) => `v${v}:${versions[v]}`) .join(',')} - ` + +${ + earlyLocks.length + ? ` +## earliest locks with money left (total: ${earlyLocks.length}) + +| address | version | balance | lastKeyMinted | +| --- | --- | --- | --- | + ${earlyLocks + .map( + ({ address, balanceFormatted, lastKeyMintedAt, version }) => + `| ${address} | v${version} | ${balanceFormatted} | ${new Date(lastKeyMintedAt * 1000).toLocaleDateString('en-US')} |` + ) + .join('\n')}` + : '' +} +` ) } @@ -86,13 +159,14 @@ async function main({ deadline = '2022-01-01' } = {}) { ) console.log(`Chains: ${chains.join(',')} `) - const infos = {} + const recentLocks = {} await Promise.all( chains.map(async (chainId) => { try { - const info = await getAllLockVersionInfo({ chainId, timeLimit }) - infos[chainId] = info - logLocks(info) + const locks = await getAllLocks({ chainId, timeLimit }) + // earliest ${earliestLocks.length} locks (${parseInt(earliest) < 9 ? earliestLocks.map(({ address }) => address).join(',') : ''}) + recentLocks[chainId] = locks + logLocks(locks) } catch (error) { console.log(`Couldn't fetch chain ${chainId}: ${error.message}`) } diff --git a/packages/hardhat-helpers/src/fork.js b/packages/hardhat-helpers/src/fork.js index d28a857e463..e3bfe6e30ad 100644 --- a/packages/hardhat-helpers/src/fork.js +++ b/packages/hardhat-helpers/src/fork.js @@ -221,14 +221,16 @@ const getDelegates = async () => { const getERC20Contract = async (tokenAddress, signer) => { const { ethers } = require('hardhat') - const { - nativeCurrency: { wrapped }, - } = await getNetwork() + const network = await getNetwork() if (!signer) { ;[signer] = await ethers.getSigners() } - return tokenAddress === wrapped - ? await ethers.getContractAt(WETH_ABI, wrapped, signer) + return tokenAddress === network.nativeCurrency?.wrapped + ? await ethers.getContractAt( + WETH_ABI, + network.nativeCurrency?.wrapped, + signer + ) : await ethers.getContractAt(ERC20_ABI, tokenAddress, signer) } diff --git a/packages/hardhat-helpers/src/lock.js b/packages/hardhat-helpers/src/lock.js index 5e70ba5e8bc..4e20d5e60dc 100644 --- a/packages/hardhat-helpers/src/lock.js +++ b/packages/hardhat-helpers/src/lock.js @@ -2,13 +2,13 @@ const contracts = require('@unlock-protocol/contracts') const { ethers, Interface } = require('ethers') const { ADDRESS_ZERO } = require('./constants') -export const getLock = async (lockAddress) => { +export const getLock = async (lockAddress, version = 14) => { const { ethers } = require('hardhat') if (!lockAddress) { throw Error(`Missing lock address`) } // get unlock instance (TODO: do not use code version but packaged version) - const { abi } = contracts['PublicLockV14'] + const { abi } = contracts[`PublicLockV${version}`] const lock = await ethers.getContractAt(abi, lockAddress) return lock } From 1c1400ca2d707ef798a293e1d62e6a5c7470f0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 13:47:30 +0200 Subject: [PATCH 10/27] fix missing `getLock` --- governance/scripts/lock/listManagers.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/governance/scripts/lock/listManagers.js b/governance/scripts/lock/listManagers.js index 659b2ff93fd..f92d2dfc2eb 100644 --- a/governance/scripts/lock/listManagers.js +++ b/governance/scripts/lock/listManagers.js @@ -1,5 +1,6 @@ const { ethers } = require('hardhat') const { fetchFromSubgraph } = require('../../helpers/subgraph') +const { getLock } = require('@unlock-protocol/hardhat-helpers') async function main({ lockAddress }) { const { chainId } = await ethers.provider.getNetwork() @@ -19,6 +20,7 @@ async function main({ lockAddress }) { } = await fetchFromSubgraph({ chainId, query }) const managers = LockManagers.map((address) => address) + const lock = await getLock(lockAddress) console.log( `LOCK > managers for the lock '${await lock.name()}' (${lockAddress}):` ) From e05f60908ceda28a2659957ebc021d5926689c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 13:52:11 +0200 Subject: [PATCH 11/27] remove v9 --- .../src/abis/PublicLock/PublicLockV9.json | 1788 -------- .../contracts/src/abis/Unlock/UnlockV9.json | 633 --- .../contracts/PublicLock/IPublicLockV9.sol | 462 -- .../src/contracts/PublicLock/PublicLockV0.sol | 1108 ----- .../src/contracts/PublicLock/PublicLockV1.sol | 1809 -------- .../src/contracts/PublicLock/PublicLockV2.sol | 2 - .../src/contracts/PublicLock/PublicLockV3.sol | 2044 --------- .../src/contracts/PublicLock/PublicLockV4.sol | 2199 ---------- .../src/contracts/PublicLock/PublicLockV5.sol | 2 - .../src/contracts/PublicLock/PublicLockV6.sol | 3288 --------------- .../src/contracts/PublicLock/PublicLockV7.sol | 3260 --------------- .../src/contracts/PublicLock/PublicLockV8.sol | 3342 --------------- .../src/contracts/PublicLock/PublicLockV9.sol | 3702 ----------------- .../src/contracts/Unlock/IUnlockV9.sol | 166 - .../src/contracts/Unlock/UnlockV9.sol | 1591 ------- packages/unlock-js/scripts/compressAbi.js | 4 +- packages/unlock-js/src/abis.ts | 143 - 17 files changed, 2 insertions(+), 25541 deletions(-) delete mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV9.json delete mode 100644 packages/contracts/src/abis/Unlock/UnlockV9.json delete mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV0.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV1.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV2.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV3.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV4.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV5.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV6.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV7.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV8.sol delete mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV9.sol delete mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV9.sol delete mode 100644 packages/contracts/src/contracts/Unlock/UnlockV9.sol diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV9.json b/packages/contracts/src/abis/PublicLock/PublicLockV9.json deleted file mode 100644 index fa07035f2be..00000000000 --- a/packages/contracts/src/abis/PublicLock/PublicLockV9.json +++ /dev/null @@ -1,1788 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "PublicLock", - "sourceName": "src/contracts/PublicLock/PublicLockV9.sol", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sendTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "name": "CancelKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disable", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "_timeAdded", - "type": "bool" - } - ], - "name": "ExpirationChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ExpireKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundedAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "GasRefunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "KeyGranterRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "_newManager", - "type": "address" - } - ], - "name": "KeyManagerChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "LockManagerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "NewLockSymbol", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldKeyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "oldTokenAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - } - ], - "name": "PricingChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "RefundPenaltyChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newExpiration", - "type": "uint256" - } - ], - "name": "RenewKeyPurchase", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "TransferFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "unlockAddress", - "type": "address" - } - ], - "name": "UnlockCallFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "KEY_GRANTER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LOCK_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addKeyGranter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "addLockManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_approved", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "approveBeneficiary", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "beneficiary", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "cancelAndRefund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "disableLock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "expirationDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "expireAndRefundFor", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "freeTrialLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasRefundValue", - "outputs": [ - { - "internalType": "uint256", - "name": "_refundValue", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getCancelAndRefundValueFor", - "outputs": [ - { - "internalType": "uint256", - "name": "refund", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "getHasValidKey", - "outputs": [ - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_account", - "type": "address" - } - ], - "name": "getTokenIdFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_time", - "type": "uint256" - } - ], - "name": "getTransferFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_recipients", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_expirationTimestamps", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "_keyManagers", - "type": "address[]" - } - ], - "name": "grantKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_lockCreator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "isAlive", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isKeyGranter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "isLockManager", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - } - ], - "name": "keyExpirationTimestampFor", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "keyManagerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "keyPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumberOfKeys", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numberOfOwners", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onKeyCancelHook", - "outputs": [ - { - "internalType": "contract ILockKeyCancelHook", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onKeyPurchaseHook", - "outputs": [ - { - "internalType": "contract ILockKeyPurchaseHook", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onTokenURIHook", - "outputs": [ - { - "internalType": "contract ILockTokenURIHook", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onValidKeyHook", - "outputs": [ - { - "internalType": "contract ILockValidKeyHook", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "publicLockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchase", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "purchasePriceFor", - "outputs": [ - { - "internalType": "uint256", - "name": "minKeyPrice", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "refundPenaltyBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceLockManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_granter", - "type": "address" - } - ], - "name": "revokeKeyGranter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_baseTokenURI", - "type": "string" - } - ], - "name": "setBaseTokenURI", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_onKeyPurchaseHook", - "type": "address" - }, - { - "internalType": "address", - "name": "_onKeyCancelHook", - "type": "address" - }, - { - "internalType": "address", - "name": "_onValidKeyHook", - "type": "address" - }, - { - "internalType": "address", - "name": "_onTokenURIHook", - "type": "address" - } - ], - "name": "setEventHooks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_newExpirationDuration", - "type": "uint256" - } - ], - "name": "setExpirationDuration", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_refundValue", - "type": "uint256" - } - ], - "name": "setGasRefundValue", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_keyManager", - "type": "address" - } - ], - "name": "setKeyManagerOf", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - } - ], - "name": "setMaxNumberOfKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_timeShared", - "type": "uint256" - } - ], - "name": "shareKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_keyOwner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_index", - "type": "uint256" - } - ], - "name": "tokenOfOwnerByIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "transferFeeBasisPoints", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unlockProtocol", - "outputs": [ - { - "internalType": "contract IUnlock", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_beneficiary", - "type": "address" - } - ], - "name": "updateBeneficiary", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - } - ], - "name": "updateKeyPricing", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_lockName", - "type": "string" - } - ], - "name": "updateLockName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_lockSymbol", - "type": "string" - } - ], - "name": "updateLockSymbol", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_refundPenaltyBasisPoints", - "type": "uint256" - } - ], - "name": "updateRefundPenalty", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_transferFeeBasisPoints", - "type": "uint256" - } - ], - "name": "updateTransferFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x6080604052600061201e5534801561001657600080fd5b50615a8280620000276000396000f3fe60806040526004361061044b5760003560e01c806370a0823111610234578063aae4b8f71161012e578063d1bbd49c116100b6578063f0ba60401161007a578063f0ba604014610d4f578063f12c6b6e14610d64578063f3fef3a314610d84578063f5766b3914610da4578063fc42b58f14610dc457600080fd5b8063d1bbd49c14610cb3578063d250348514610ccf578063d32bfb6c14610cef578063d547741f14610d0f578063e985e9c514610d2f57600080fd5b8063b88d4fde116100fd578063b88d4fde14610c1e578063bf4a927014610c3e578063c1c98d0314610c5e578063c87b56dd14610c73578063cb0703c614610c9357600080fd5b8063aae4b8f714610b84578063abdf82ce14610ba4578063b11d7ec114610bde578063b585a6d514610bfe57600080fd5b806393fd1844116101bc578063a217fddf11610180578063a217fddf14610af8578063a22cb46514610b0d578063a2e4cd2e14610b2d578063a375cb0514610b4d578063a9059cbb14610b6457600080fd5b806393fd184414610a5457806395d89b4114610a6b578063970aaeb714610a8057806397aa390a14610ab75780639d76ea5814610ad757600080fd5b806381a3c9431161020357806381a3c943146109bf5780638577a6d5146109df5780638be4b870146109ff5780638ca2fbad14610a1257806391d1485414610a3457600080fd5b806370a082311461094757806374b6c10614610967578063782a4ade1461097e5780637ec2a7241461099e57600080fd5b80632f745c591161034557806352b0f638116102cd5780636207a8da116102915780636207a8da146108b1578063626485a3146108c75780636352211e146108e75780636d8ea5b4146109075780636eadde431461092757600080fd5b806352b0f6381461081a57806352d6a8e41461083a578063550ef3a81461085a578063564aa99d1461087a57806356e0d51f1461089a57600080fd5b806339f469861161031457806339f46986146107685780634136aa351461078857806342842e0e146107a35780634d025fed146107c35780634f6ccce7146107fa57600080fd5b80632f745c59146106e757806330176e131461070757806336568abe1461072757806338af3eed1461074757600080fd5b806318160ddd116103d3578063248a9ca311610397578063248a9ca31461063557806326e9ca07146106655780632af9162a146106865780632d33dd5b146106a65780632f2ff15d146106c757600080fd5b806318160ddd146105a5578063183767da146105bb578063217751bc146105d257806323100509146105f357806323b872dd1461061557600080fd5b8063097ba3331161041a578063097ba333146105085780630aaffd2a146105365780630f15023b1461055657806310e569731461057757806311a4c03a1461058e57600080fd5b806301ffc9a71461045757806306fdde031461048c578063081812fc146104ae578063095ea7b3146104e657600080fd5b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046152e6565b610de4565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610df5565b6040516104839190615672565b3480156104ba57600080fd5b506104ce6104c93660046152aa565b610e84565b6040516001600160a01b039091168152602001610483565b3480156104f257600080fd5b506105066105013660046151b3565b610f00565b005b34801561051457600080fd5b5061052861052336600461503e565b611035565b604051908152602001610483565b34801561054257600080fd5b50610506610551366004614ee1565b611081565b34801561056257600080fd5b50610c83546104ce906001600160a01b031681565b34801561058357600080fd5b50610528610c855481565b34801561059a57600080fd5b50610528610c845481565b3480156105b157600080fd5b50610c8754610528565b3480156105c757600080fd5b506105286124075481565b3480156105de57600080fd5b50610c8a546104ce906001600160a01b031681565b3480156105ff57600080fd5b506105286000805160206159ed83398151915281565b34801561062157600080fd5b506105066106303660046150a0565b611105565b34801561064157600080fd5b506105286106503660046152aa565b60009081526097602052604090206001015490565b34801561067157600080fd5b50610c8b546104ce906001600160a01b031681565b34801561069257600080fd5b506105066106a1366004614ee1565b611434565b3480156106b257600080fd5b50610c89546104ce906001600160a01b031681565b3480156106d357600080fd5b506105066106e23660046152c2565b6114b7565b3480156106f357600080fd5b506105286107023660046151b3565b6114e2565b34801561071357600080fd5b5061050661072236600461531e565b61156a565b34801561073357600080fd5b506105066107423660046152c2565b6115ab565b34801561075357600080fd5b50610c88546104ce906001600160a01b031681565b34801561077457600080fd5b5061050661078336600461544e565b611629565b34801561079457600080fd5b5061089a546104779060ff1681565b3480156107af57600080fd5b506105066107be3660046150a0565b6116a3565b3480156107cf57600080fd5b506104ce6107de3660046152aa565b611078602052600090815260409020546001600160a01b031681565b34801561080657600080fd5b506105286108153660046152aa565b6116be565b34801561082657600080fd5b50610477610835366004614ee1565b611705565b34801561084657600080fd5b50610528610855366004614ee1565b61171f565b34801561086657600080fd5b5061050661087536600461531e565b61172a565b34801561088657600080fd5b50610506610895366004614ee1565b61176b565b3480156108a657600080fd5b506105286127f05481565b3480156108bd57600080fd5b5061201e54610528565b3480156108d357600080fd5b506105066108e23660046152aa565b6117ee565b3480156108f357600080fd5b506104ce6109023660046152aa565b611828565b34801561091357600080fd5b50610477610922366004614ee1565b611844565b34801561093357600080fd5b50610506610942366004614f28565b61191d565b34801561095357600080fd5b50610528610962366004614ee1565b611a3c565b34801561097357600080fd5b50610528610c865481565b34801561098a57600080fd5b5061050661099936600461531e565b611a84565b3480156109aa57600080fd5b50610c8c546104ce906001600160a01b031681565b3480156109cb57600080fd5b506105066109da3660046151f9565b611b03565b3480156109eb57600080fd5b506105066109fa3660046152aa565b611d71565b610506610a0d3660046153de565b611dde565b348015610a1e57600080fd5b50610528600080516020615a2d83398151915281565b348015610a4057600080fd5b50610477610a4f3660046152c2565b61245e565b348015610a6057600080fd5b506105286110775481565b348015610a7757600080fd5b506104a1612489565b348015610a8c57600080fd5b50610528610a9b366004614ee1565b6001600160a01b03166000908152611075602052604090205490565b348015610ac357600080fd5b50610506610ad2366004614efd565b6125c2565b348015610ae357600080fd5b506104b1546104ce906001600160a01b031681565b348015610b0457600080fd5b50610528600081565b348015610b1957600080fd5b50610506610b28366004615186565b612626565b348015610b3957600080fd5b50610506610b483660046152c2565b6126fe565b348015610b5957600080fd5b506105286127f15481565b348015610b7057600080fd5b50610477610b7f3660046151b3565b612896565b348015610b9057600080fd5b50610477610b9f366004614ee1565b612905565b348015610bb057600080fd5b50610528610bbf366004614ee1565b6001600160a01b03166000908152611075602052604090206001015490565b348015610bea57600080fd5b50610506610bf93660046152c2565b61291f565b348015610c0a57600080fd5b50610477610c193660046151b3565b6129e3565b348015610c2a57600080fd5b50610506610c393660046150e0565b612aa7565b348015610c4a57600080fd5b50610506610c593660046152aa565b612b10565b348015610c6a57600080fd5b50610506612bb4565b348015610c7f57600080fd5b506104a1610c8e3660046152aa565b612c41565b348015610c9f57600080fd5b50610506610cae366004614fe3565b612ef8565b348015610cbf57600080fd5b5060405160098152602001610483565b348015610cdb57600080fd5b50610506610cea366004614ee1565b61312b565b348015610cfb57600080fd5b50610506610d0a3660046152aa565b6131ae565b348015610d1b57600080fd5b50610506610d2a3660046152c2565b613232565b348015610d3b57600080fd5b50610477610d4a366004614fab565b613258565b348015610d5b57600080fd5b506105066132f1565b348015610d7057600080fd5b50610506610d7f3660046151c5565b613336565b348015610d9057600080fd5b50610506610d9f3660046151b3565b61368b565b348015610db057600080fd5b50610506610dbf3660046152aa565b613818565b348015610dd057600080fd5b50610528610ddf3660046151b3565b613852565b6000610def826138cb565b92915050565b6114638054610e0390615937565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2f90615937565b8015610e7c5780601f10610e5157610100808354040283529160200191610e7c565b820191906000526020600020905b815481529060010190602001808311610e5f57829003601f168201915b505050505081565b6000818152611076602052604081205482906001600160a01b0316610ede5760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b60448201526064015b60405180910390fd5b600083815261107960205260409020546001600160a01b031691505b50919050565b61089a5460ff16610f235760405162461bcd60e51b8152600401610ed590615796565b80610f2e81336138d6565b80610f3e5750610f3e813361394e565b80610f67575060008181526110766020526040902054610f67906001600160a01b031633613258565b610f835760405162461bcd60e51b8152600401610ed5906156d5565b336001600160a01b0384161415610fcb5760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b60008281526110796020908152604080832080546001600160a01b0319166001600160a01b03888116918217909255611076909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611078858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b95945050505050565b61108a33612905565b806110a05750610c88546001600160a01b031633145b6110bc5760405162461bcd60e51b8152600401610ed59061570c565b6001600160a01b0381166110e25760405162461bcd60e51b8152600401610ed590615685565b610c8880546001600160a01b0319166001600160a01b0392909216919091179055565b61089a5460ff166111285760405162461bcd60e51b8152600401610ed590615796565b8261113281611844565b61114e5760405162461bcd60e51b8152600401610ed5906156ae565b8161115981336138d6565b806111695750611169813361394e565b80611192575060008181526110766020526040902054611192906001600160a01b031633613258565b6111ae5760405162461bcd60e51b8152600401610ed5906156d5565b846001600160a01b03166111c184611828565b6001600160a01b0316146112175760405162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e4552000000006044820152606401610ed5565b61271061240754106112645760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661128a5760405162461bcd60e51b8152600401610ed590615685565b836001600160a01b0316856001600160a01b031614156112df5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b60006112ec866000613852565b6001600160a01b03808816600090815261107560205260408082209289168252812060018101549394509192906113269088908690613a1f565b8154611342578682556113398888613b1f565b61134287613b9d565b4281116113705760018084015490830155868255611361876000613bdc565b61136b8888613b1f565b6113f8565b600019610c845414156113d75760405162461bcd60e51b815260206004820152602960248201527f526563697069656e7420616c7265616479206f776e732061206e6f6e2d6578706044820152686972696e67206b657960b81b6064820152608401610ed5565b428184600101546113e89190615861565b6113f291906158dd565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615a0d83398151915291a4505050505050505050565b61144c600080516020615a2d8339815191523361245e565b6114685760405162461bcd60e51b8152600401610ed590615741565b6114806000805160206159ed83398151915282613232565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6000828152609760205260409020600101546114d38133613c69565b6114dd8383613ccd565b505050565b60006114ed83611a3c565b8210801561150357506001600160a01b03831615155b6115485760405162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b6044820152606401610ed5565b6001600160a01b038316600090815261107560205260409020545b9392505050565b611582600080516020615a2d8339815191523361245e565b61159e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114658383614dc9565b6001600160a01b038116331461161b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610ed5565b6116258282613d53565b5050565b611641600080516020615a2d8339815191523361245e565b61165d5760405162461bcd60e51b8152600401610ed590615741565b60408051838152602081018390527fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c910160405180910390a16127f1919091556127f055565b6114dd83838360405180602001604052806000815250612aa7565b6000610c875482106117015760405162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b6044820152606401610ed5565b5090565b6000610def6000805160206159ed8339815191528361245e565b6000610def82613dba565b611742600080516020615a2d8339815191523361245e565b61175e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114638383614dc9565b611783600080516020615a2d8339815191523361245e565b61179f5760405162461bcd60e51b8152600401610ed590615741565b6117b76000805160206159ed833981519152826114b7565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b611806600080516020615a2d8339815191523361245e565b6118225760405162461bcd60e51b8152600401610ed590615741565b610c8455565b600090815261107660205260409020546001600160a01b031690565b6001600160a01b0380821660009081526110756020526040902060010154610c8b544290911191161561191857610c8b546001600160a01b0383811660008181526110756020526040908190206001015490516370b6638f60e11b815230600482015260248101929092526044820152831515606482015291169063e16cc71e9060840160206040518083038186803b1580156118e057600080fd5b505afa1580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def919061528e565b919050565b600054610100900460ff166119385760005460ff161561193c565b303b155b61199f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ed5565b600054610100900460ff161580156119c1576000805461ffff19166101011790555b6119ca86613eda565b6119dd61089a805460ff19166001179055565b6119e988888787613fb1565b6119f38383614053565b6119fb614079565b611a076103e86127f055565b611a108861408b565b611a206380ac58cd60e01b614113565b8015611a32576000805461ff00191690555b5050505050505050565b60006001600160a01b038216611a645760405162461bcd60e51b8152600401610ed590615685565b611a6d82611844565b611a78576000611a7b565b60015b60ff1692915050565b611a9c600080516020615a2d8339815191523361245e565b611ab85760405162461bcd60e51b8152600401610ed590615741565b611ac56114648383614dc9565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb978282604051611af792919061565e565b60405180910390a15050565b611b0c33611705565b80611b1b5750611b1b33612905565b611b995760405162461bcd60e51b815260206004820152604360248201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560448201527f20746865204b65794772616e746572206f72204c6f636b4d616e6167657220726064820152626f6c6560e81b608482015260a401610ed5565b60005b85811015611d68576000878783818110611bc657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bdb9190614ee1565b90506000868684818110611bff57634e487b7160e01b600052603260045260246000fd5b9050602002013590506000858585818110611c2a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c3f9190614ee1565b90506001600160a01b038316611c675760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b03831660009081526110756020526040902060018101548311611cc65760405162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b6044820152606401610ed5565b805480611ce357611cd682614192565b508054611ce38582613b1f565b611ced8184613bdc565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615a0d833981519152908290a450505050508080611d609061596c565b915050611b9c565b50505050505050565b611d89600080516020615a2d8339815191523361245e565b611da55760405162461bcd60e51b8152600401610ed590615741565b6040518181527f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49060200160405180910390a161240755565b61089a5460ff16611e015760405162461bcd60e51b8152600401610ed590615796565b610c8754610c865411611e465760405162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b6044820152606401610ed5565b6001600160a01b038516611e6c5760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b0385166000908152611075602052604081208054909181611f0857611e9783614192565b82549150611ea58883613b1f565b600019610c84541415611ebb5750600019611ecc565b610c8454611ec99042615861565b90505b60018301819055611edd8287613bdc565b60405182906001600160a01b038a1690600090600080516020615a0d833981519152908290a4612062565b4283600101541115611fe65760001983600101541415611f865760405162461bcd60e51b815260206004820152603360248201527f412076616c6964206e6f6e2d6578706972696e67206b65792063616e206e6f746044820152722062652070757263686173656420747769636560681b6064820152608401610ed5565b610c84548360010154611f999190615861565b600184018190556040518181529091506001600160a01b038916907f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9060200160405180910390a2612062565b600019610c84541415611ffc575060001961200d565b610c845461200a9042615861565b90505b6001830181905561201e8287613bdc565b876001600160a01b03167f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d8260405161205991815260200190565b60405180910390a25b60006120a5898988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b610c835460405163939d9f1f60e01b8152600481018390526001600160a01b038b8116602483015292935091169063939d9f1f90604401600060405180830381600087803b1580156120f657600080fd5b505af1925050508015612107575060015b61214f57610c83546040516001600160a01b03909116815230907f6b18946261693dfd6c760d986b28ad2238b5b0267f8e5b6bc40a2f998e2f20ac9060200160405180910390a25b6104b1546000906001600160a01b0316156121f957506104b1546040516323b872dd60e01b8152336004820152306024820152604481018c90528b916001600160a01b03169081906323b872dd90606401602060405180830381600087803b1580156121ba57600080fd5b505af11580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061528e565b50506121fc565b50345b818110156122415760405162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b6044820152606401610ed5565b610c89546001600160a01b0316156122c357610c8954604051639849965760e01b81526001600160a01b03909116906398499657906122909033908e908e908d908d908a908a906004016155ac565b600060405180830381600087803b1580156122aa57600080fd5b505af11580156122be573d6000803e3d6000fd5b505050505b61201e5415612451576104b1546001600160a01b031615612377576104b15461201e546040516323b872dd60e01b815230600482015233602482015260448101919091526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561233857600080fd5b505af115801561234c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612370919061528e565b5050612404565b61201e5460405160009133918381818185875af1925050503d80600081146123bb576040519150601f19603f3d011682016040523d82523d6000602084013e6123c0565b606091505b50509050806124025760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610ed5565b505b61201e546104b154604080519283526001600160a01b03909116602083015233917f522a883b471164223f18b50f326da8671372b64b4792eac0e63d447e714c3e3b910160405180910390a25b5050505050505050505050565b60009182526097602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060611464805461249990615937565b1515905061253157610c8360009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f057600080fd5b505afa158015612504573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261252c919081019061535d565b905090565b611464805461253f90615937565b80601f016020809104026020016040519081016040528092919081815260200182805461256b90615937565b80156125b85780601f1061258d576101008083540402835291602001916125b8565b820191906000526020600020905b81548152906001019060200180831161259b57829003601f168201915b5050505050905090565b6125da600080516020615a2d8339815191523361245e565b6125f65760405162461bcd60e51b8152600401610ed590615741565b8161260081611844565b61261c5760405162461bcd60e51b8152600401610ed5906156ae565b6114dd83836141b6565b61089a5460ff166126495760405162461bcd60e51b8152600401610ed590615796565b6001600160a01b0382163314156126915760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b33600081815261107a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612716600080516020615a2d8339815191523361245e565b6127325760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff166127555760405162461bcd60e51b8152600401610ed590615796565b610c85546104b1546001600160a01b0390811690831615806127e757506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ad57600080fd5b505afa1580156127c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e591906153c6565b115b6128235760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b610c858490556104b180546001600160a01b0319166001600160a01b0385811691821790925560408051858152602081018890529284169083015260608201527f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d49060800160405180910390a150505050565b600080610c8454836128a891906158be565b336000908152611075602052604081206001810154929350916128cc9042906158dd565b9050808310156128ea576128e586836000015485613336565b6128f9565b6128f933878460000154611105565b50600195945050505050565b6000610def600080516020615a2d8339815191528361245e565b6000828152611076602052604090205482906001600160a01b03166129745760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b6044820152606401610ed5565b61297e83336138d6565b8061298d575061298d33612905565b6129d95760405162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f555044415445006044820152606401610ed5565b6114dd8383613bdc565b60006129ee33612905565b80612a045750610c88546001600160a01b031633145b612a205760405162461bcd60e51b8152600401610ed59061570c565b6104b15460405163095ea7b360e01b81526001600160a01b038581166004830152602482018590529091169063095ea7b390604401602060405180830381600087803b158015612a6f57600080fd5b505af1158015612a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611563919061528e565b612ab2848484611105565b612abe848484846142b1565b612b0a5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b50505050565b612b28600080516020615a2d8339815191523361245e565b612b445760405162461bcd60e51b8152600401610ed590615741565b610c87548111612bae5760405162461bcd60e51b815260206004820152602f60248201527f6d61784e756d6265724f664b65797320697320736d616c6c6572207468616e2060448201526e6578697374696e6720737570706c7960881b6064820152608401610ed5565b610c8655565b612bcc600080516020615a2d8339815191523361245e565b612be85760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff16612c0b5760405162461bcd60e51b8152600401610ed590615796565b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a161089a805460ff19169055565b606080806000612c5030614370565b905060608515612c6a57612c63866145cb565b9250612c7d565b6040518060200160405280600081525092505b610c8c546001600160a01b031615612d6b576000612c9a87611828565b90506000612cc1826001600160a01b03166000908152611075602052604090206001015490565b610c8c5460405163988b93ad60e01b81523060048201523360248201526001600160a01b038581166044830152606482018c90526084820184905292935091169063988b93ad9060a40160006040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d5f919081019061535d565b98975050505050505050565b6114658054612d7990615937565b15159050612e2f57610c8360009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b158015612dd057600080fd5b505afa158015612de4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e0c919081019061535d565b9350604051806040016040528060018152602001602f60f81b8152509050612ee2565b6114658054612e3d90615937565b80601f0160208091040260200160405190810160405280929190818152602001828054612e6990615937565b8015612eb65780601f10612e8b57610100808354040283529160200191612eb6565b820191906000526020600020905b815481529060010190602001808311612e9957829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b612eee84838386614713565b9695505050505050565b612f10600080516020615a2d8339815191523361245e565b612f2c5760405162461bcd60e51b8152600401610ed590615741565b6001600160a01b0384161580612f4b57506001600160a01b0384163b15155b612f975760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b00000000000000006044820152606401610ed5565b6001600160a01b0383161580612fb657506001600160a01b0383163b15155b6130025760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b0000000000006044820152606401610ed5565b6001600160a01b038216158061302157506001600160a01b0382163b15155b61306d5760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f56414c49445f4b45595f484f4f4b000000000000006044820152606401610ed5565b6001600160a01b038116158061308c57506001600160a01b0381163b15155b6130d85760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f544f4b454e5f5552495f484f4f4b000000000000006044820152606401610ed5565b610c8980546001600160a01b039586166001600160a01b031991821617909155610c8a805494861694821694909417909355610c8c8054918516918416919091179055610c8b8054919093169116179055565b613143600080516020615a2d8339815191523361245e565b61315f5760405162461bcd60e51b8152600401610ed590615741565b613177600080516020615a2d833981519152826114b7565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b806131b981336138d6565b806131c957506131c9813361394e565b806131f25750600081815261107660205260409020546131f2906001600160a01b031633613258565b61320e5760405162461bcd60e51b8152600401610ed5906156d5565b600061321983611828565b9050600061322682613dba565b9050612b0a82826141b6565b60008281526097602052604090206001015461324e8133613c69565b6114dd8383613d53565b6001600160a01b03808316600090815261107560209081526040808320548084526110789092528220549192909116806132be575050506001600160a01b03808316600090815261107a602090815260408083209385168352929052205460ff16610def565b6001600160a01b03908116600090815261107a602090815260408083209387168352929052205460ff169150610def9050565b613309600080516020615a2d833981519152336115ab565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b61089a5460ff166133595760405162461bcd60e51b8152600401610ed590615796565b8161336481336138d6565b806133745750613374813361394e565b8061339d57506000818152611076602052604090205461339d906001600160a01b031633613258565b6133b95760405162461bcd60e51b8152600401610ed5906156d5565b61271061240754106134065760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661342c5760405162461bcd60e51b8152600401610ed590615685565b600083815261107660205260409020546001600160a01b031661344e81611844565b61346a5760405162461bcd60e51b8152600401610ed5906156ae565b846001600160a01b0316816001600160a01b031614156134bf5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b6001600160a01b038082166000908152611075602052604080822092881682528120805460018401549192909181906134f99042906158dd565b90506000613507878a613852565b90506000613515828b615861565b9050828110156135335789935061352e8b826000613a1f565b61357e565b61353d8884613852565b915061354982846158dd565b4260018901556040519094508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b846135c55761358c86614192565b8554945061359a8c86613b1f565b60405185906001600160a01b038e1690600090600080516020615a0d833981519152908290a46135db565b428660010154116135db576135db856000613bdc565b6135e785856001613a1f565b848c6001600160a01b0316896001600160a01b0316600080516020615a0d83398151915260405160405180910390a4613631888d87604051806020016040528060008152506142b1565b61367d5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b505050505050505050505050565b61369433612905565b806136aa5750610c88546001600160a01b031633145b6136c65760405162461bcd60e51b8152600401610ed59061570c565b60006001600160a01b0383166136dd575047613757565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b15801561371c57600080fd5b505afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375491906153c6565b90505b600082158061376557508183115b156137b457600082116137ad5760405162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b6044820152606401610ed5565b50806137b7565b50815b610c88546040518281526001600160a01b039182169186169033907f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9060200160405180910390a4610c8854612b0a9085906001600160a01b031683614745565b613830600080516020615a2d8339815191523361245e565b61384c5760405162461bcd60e51b8152600401610ed590615741565b61201e55565b600061385d83611844565b61386957506000610def565b6001600160a01b0383166000908152611075602052604081209080846138a05742836001015461389991906158dd565b91506138a4565b8491505b61271061240754836138b691906158be565b6138c0919061589e565b9350610def92505050565b6000610def82614781565b600082815261107860205260408120546001600160a01b03838116911614806139395750600083815261107860205260409020546001600160a01b03161580156139395750816001600160a01b031661392e84611828565b6001600160a01b0316145b1561394657506001610def565b506000610def565b60009182526110796020526040909120546001600160a01b0391821691161490565b610c89546000906001600160a01b031615613a1357610c895460405163221c1fd160e01b81526001600160a01b039091169063221c1fd1906139bc9033908890889088906004016155f7565b60206040518083038186803b1580156139d457600080fd5b505afa1580156139e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0c91906153c6565b9050611563565b50610c85549392505050565b6000613a2a84611828565b90506001600160a01b038116613a755760405162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b6044820152606401610ed5565b6001600160a01b03811660009081526110756020526040812060018101549091613a9e84611844565b90508415613aca578015613ac057613ab68683615861565b6001840155613ada565b613ab68642615861565b613ad486836158dd565b60018401555b60408051878152861515602082015288917fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3910160405180910390a250505050505050565b6001600160a01b0382166000908152611075602090815260409182902082518084019093528054835260010154908201819052613b6d576110778054906000613b678361596c565b91905055505b5060009081526110766020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600081815261107960205260409020546001600160a01b031615613bd95760008181526110796020526040902080546001600160a01b03191690555b50565b600082815261107860205260409020546001600160a01b038281169116146116255760008281526110786020526040902080546001600160a01b0319166001600160a01b038316179055613c2f82613b9d565b6040516001600160a01b0382169083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a35050565b613c73828261245e565b61162557613c8b816001600160a01b0316601461478c565b613c9683602061478c565b604051602001613ca7929190615537565b60408051601f198184030181529082905262461bcd60e51b8252610ed591600401615672565b613cd7828261245e565b6116255760008281526097602090815260408083206001600160a01b03851684529091529020805460ff19166001179055613d0f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b613d5d828261245e565b156116255760008281526097602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600081613dc681611844565b613de25760405162461bcd60e51b8152600401610ed5906156ae565b6001600160a01b038316600090815261107560205260409020610c84546000191415613e1457610c8554925050610efa565b6000428260010154613e2691906158dd565b9050610c84546127f15482613e3b9190615861565b10613e4b57610c85549350613e6b565b610c845481610c8554613e5e91906158be565b613e68919061589e565b93505b6127f1541580613e8a5750610c84546127f154613e889083615861565b105b15613ed25760006127106127f054610c8554613ea691906158be565b613eb0919061589e565b905080851115613ecb57613ec481866158dd565b9450613ed0565b600094505b505b505050919050565b6104b180546001600160a01b0319166001600160a01b0383169081179091551580613f7557506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f3b57600080fd5b505afa158015613f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7391906153c6565b115b613bd95760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b63bbf81e008311156140055760405162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f594541525300000000000000006044820152606401610ed5565b610c838054336001600160a01b031991821617909155610c8880549091166001600160a01b038616179055821561403c5782614040565b6000195b610c8455610c8591909155610c86555050565b61405b61496d565b6140686114638383614dc9565b50611625635b5e139f60e01b614113565b61408963780e9d6360e01b614113565b565b6140a3600080516020615a2d833981519152806149a4565b6140c96000805160206159ed833981519152600080516020615a2d8339815191526149a4565b6140d281612905565b6140ee576140ee600080516020615a2d833981519152826149ef565b6140f781611705565b613bd957613bd96000805160206159ed833981519152826149ef565b6001600160e01b0319808216141561416d5760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e74657266616365206964000000006044820152606401610ed5565b6001600160e01b0319166000908152606560205260409020805460ff19166001179055565b8054613bd957610c8780549060006141a98361596c565b9091555050610c87549055565b6001600160a01b0382166000818152611075602052604090819020805491519092339290917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce5289061420a9087815260200190565b60405180910390a44260018201558115614236576104b154614236906001600160a01b03168484614745565b610c8a546001600160a01b0316156114dd57610c8a5460405163b499b6c560e01b81523360048201526001600160a01b038581166024830152604482018590529091169063b499b6c590606401600060405180830381600087803b15801561429d57600080fd5b505af1158015611d68573d6000803e3d6000fd5b60006001600160a01b0384163b6142ca57506001614368565b604051630a85bd0160e11b81526000906001600160a01b0386169063150b7a02906142ff9033908a908990899060040161562b565b602060405180830381600087803b15801561431957600080fd5b505af115801561432d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143519190615302565b6001600160e01b031916630a85bd0160e11b149150505b949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b816000815181106143e957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061442657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060005b60148110156145c2578260048561445884600c615861565b6020811061447657634e487b7160e01b600052603260045260246000fd5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106144aa57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826144c58360026158be565b6144d0906002615861565b815181106144ee57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350828461451283600c615861565b6020811061453057634e487b7160e01b600052603260045260246000fd5b825191901a600f1690811061455557634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826145708360026158be565b61457b906003615861565b8151811061459957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350806145ba8161596c565b915050614440565b50949350505050565b606081806145f25750506040805180820190915260018152600360fc1b6020820152919050565b8260005b811561461c57806146068161596c565b91506146159050600a8361589e565b91506145f6565b6000816001600160401b0381111561464457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561466e576020820181803683370190505b509050815b8415614709576146846001826158dd565b90506000614693600a8761589e565b61469e90600a6158be565b6146a890876158dd565b6146b3906030615879565b905060008160f81b9050808484815181106146de57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614700600a8861589e565b96505050614673565b5095945050505050565b60608484848460405160200161472c94939291906154e0565b6040516020818303038152906040529050949350505050565b80156114dd576001600160a01b03831661476c576114dd6001600160a01b038316826149f9565b82612b0a6001600160a01b0382168484614b12565b6000610def82614b64565b6060600061479b8360026158be565b6147a6906002615861565b6001600160401b038111156147cb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147f5576020820181803683370190505b509050600360fc1b8160008151811061481e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061485b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061487f8460026158be565b61488a906001615861565b90505b600181111561491e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106148cc57634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106148f057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361491781615920565b905061488d565b5083156115635760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ed5565b600054610100900460ff166149945760405162461bcd60e51b8152600401610ed5906157bf565b61499c614b89565b614089614b89565b600082815260976020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6116258282613ccd565b80471015614a495760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ed5565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614a96576040519150601f19603f3d011682016040523d82523d6000602084013e614a9b565b606091505b50509050806114dd5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ed5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114dd908490614bb0565b60006001600160e01b03198216637965db0b60e01b1480610def5750610def82614c82565b600054610100900460ff166140895760405162461bcd60e51b8152600401610ed5906157bf565b6000614c05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614cbe9092919063ffffffff16565b8051909150156114dd5780806020019051810190614c23919061528e565b6114dd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ed5565b60006301ffc9a760e01b6001600160e01b031983161480610def5750506001600160e01b03191660009081526065602052604090205460ff1690565b6060614368848460008585843b614d175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ed5565b600080866001600160a01b03168587604051614d3391906154c4565b60006040518083038185875af1925050503d8060008114614d70576040519150601f19603f3d011682016040523d82523d6000602084013e614d75565b606091505b5091509150614d85828286614d90565b979650505050505050565b60608315614d9f575081611563565b825115614daf5782518084602001fd5b8160405162461bcd60e51b8152600401610ed59190615672565b828054614dd590615937565b90600052602060002090601f016020900481019282614df75760008555614e3d565b82601f10614e105782800160ff19823516178555614e3d565b82800160010185558215614e3d579182015b82811115614e3d578235825591602001919060010190614e22565b506117019291505b808211156117015760008155600101614e45565b60008083601f840112614e6a578182fd5b5081356001600160401b03811115614e80578182fd5b6020830191508360208260051b8501011115614e9b57600080fd5b9250929050565b60008083601f840112614eb3578182fd5b5081356001600160401b03811115614ec9578182fd5b602083019150836020828501011115614e9b57600080fd5b600060208284031215614ef2578081fd5b8135611563816159b3565b60008060408385031215614f0f578081fd5b8235614f1a816159b3565b946020939093013593505050565b600080600080600080600060c0888a031215614f42578283fd5b8735614f4d816159b3565b9650602088013595506040880135614f64816159b3565b9450606088013593506080880135925060a08801356001600160401b03811115614f8c578283fd5b614f988a828b01614ea2565b989b979a50959850939692959293505050565b60008060408385031215614fbd578182fd5b8235614fc8816159b3565b91506020830135614fd8816159b3565b809150509250929050565b60008060008060808587031215614ff8578384fd5b8435615003816159b3565b93506020850135615013816159b3565b92506040850135615023816159b3565b91506060850135615033816159b3565b939692955090935050565b60008060008060608587031215615053578384fd5b843561505e816159b3565b9350602085013561506e816159b3565b925060408501356001600160401b03811115615088578283fd5b61509487828801614ea2565b95989497509550505050565b6000806000606084860312156150b4578081fd5b83356150bf816159b3565b925060208401356150cf816159b3565b929592945050506040919091013590565b600080600080608085870312156150f5578182fd5b8435615100816159b3565b93506020850135615110816159b3565b92506040850135915060608501356001600160401b03811115615131578182fd5b8501601f81018713615141578182fd5b803561515461514f8261583a565b61580a565b818152886020838501011115615168578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615198578182fd5b82356151a3816159b3565b91506020830135614fd8816159c8565b60008060408385031215614f0f578182fd5b6000806000606084860312156151d9578081fd5b83356151e4816159b3565b95602085013595506040909401359392505050565b60008060008060008060608789031215615211578384fd5b86356001600160401b0380821115615227578586fd5b6152338a838b01614e59565b9098509650602089013591508082111561524b578586fd5b6152578a838b01614e59565b9096509450604089013591508082111561526f578384fd5b5061527c89828a01614e59565b979a9699509497509295939492505050565b60006020828403121561529f578081fd5b8151611563816159c8565b6000602082840312156152bb578081fd5b5035919050565b600080604083850312156152d4578182fd5b823591506020830135614fd8816159b3565b6000602082840312156152f7578081fd5b8135611563816159d6565b600060208284031215615313578081fd5b8151611563816159d6565b60008060208385031215615330578182fd5b82356001600160401b03811115615345578283fd5b61535185828601614ea2565b90969095509350505050565b60006020828403121561536e578081fd5b81516001600160401b03811115615383578182fd5b8201601f81018413615393578182fd5b80516153a161514f8261583a565b8181528560208385010111156153b5578384fd5b6110788260208301602086016158f4565b6000602082840312156153d7578081fd5b5051919050565b60008060008060008060a087890312156153f6578384fd5b863595506020870135615408816159b3565b94506040870135615418816159b3565b93506060870135615428816159b3565b925060808701356001600160401b03811115615442578283fd5b61527c89828a01614ea2565b60008060408385031215615460578182fd5b50508035926020909101359150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526154b08160208601602086016158f4565b601f01601f19169290920160200192915050565b600082516154d68184602087016158f4565b9190910192915050565b600085516154f2818460208a016158f4565b855190830190615506818360208a016158f4565b85519101906155198183602089016158f4565b845191019061552c8183602088016158f4565b019695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161556f8160178501602088016158f4565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516155a08160288401602088016158f4565b01602801949350505050565b6001600160a01b03888116825287811660208301528616604082015260c0606082018190526000906155e1908301868861546f565b60808301949094525060a0015295945050505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090612eee90830184615498565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612eee90830184615498565b60208152600061436860208301848661546f565b6020815260006115636020830184615498565b6020808252600f908201526e494e56414c49445f4144445245535360881b604082015260600190565b6020808252600d908201526c12d15657d393d517d590531251609a1b604082015260600190565b6020808252601c908201527f4f4e4c595f4b45595f4d414e414745525f4f525f415050524f56454400000000604082015260600190565b6020808252818101527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604082015260600190565b60208082526035908201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560408201527420746865204c6f636b4d616e6167657220726f6c6560581b606082015260800190565b6020808252600f908201526e1313d0d2d7d11154149150d0551151608a1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156158325761583261599d565b604052919050565b60006001600160401b038211156158535761585361599d565b50601f01601f191660200190565b6000821982111561587457615874615987565b500190565b600060ff821660ff84168060ff0382111561589657615896615987565b019392505050565b6000826158b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156158d8576158d8615987565b500290565b6000828210156158ef576158ef615987565b500390565b60005b8381101561590f5781810151838201526020016158f7565b83811115612b0a5750506000910152565b60008161592f5761592f615987565b506000190190565b600181811c9082168061594b57607f821691505b60208210811415610efa57634e487b7160e01b600052602260045260246000fd5b600060001982141561598057615980615987565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613bd957600080fd5b8015158114613bd957600080fd5b6001600160e01b031981168114613bd957600080fdfeb309c40027c81d382c3b58d8de24207a34b27e1db369b1434e4a11311f154b5eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efb89cdd26cddd51301940bf2715f765b626b8a5a9e2681ac62dc83cc2db2530c0a2646970667358221220a966aec0ea72cc36f07dd0afa1e277f5eb266146078b7651e59c22655e0639ae64736f6c63430008040033", - "deployedBytecode": "0x60806040526004361061044b5760003560e01c806370a0823111610234578063aae4b8f71161012e578063d1bbd49c116100b6578063f0ba60401161007a578063f0ba604014610d4f578063f12c6b6e14610d64578063f3fef3a314610d84578063f5766b3914610da4578063fc42b58f14610dc457600080fd5b8063d1bbd49c14610cb3578063d250348514610ccf578063d32bfb6c14610cef578063d547741f14610d0f578063e985e9c514610d2f57600080fd5b8063b88d4fde116100fd578063b88d4fde14610c1e578063bf4a927014610c3e578063c1c98d0314610c5e578063c87b56dd14610c73578063cb0703c614610c9357600080fd5b8063aae4b8f714610b84578063abdf82ce14610ba4578063b11d7ec114610bde578063b585a6d514610bfe57600080fd5b806393fd1844116101bc578063a217fddf11610180578063a217fddf14610af8578063a22cb46514610b0d578063a2e4cd2e14610b2d578063a375cb0514610b4d578063a9059cbb14610b6457600080fd5b806393fd184414610a5457806395d89b4114610a6b578063970aaeb714610a8057806397aa390a14610ab75780639d76ea5814610ad757600080fd5b806381a3c9431161020357806381a3c943146109bf5780638577a6d5146109df5780638be4b870146109ff5780638ca2fbad14610a1257806391d1485414610a3457600080fd5b806370a082311461094757806374b6c10614610967578063782a4ade1461097e5780637ec2a7241461099e57600080fd5b80632f745c591161034557806352b0f638116102cd5780636207a8da116102915780636207a8da146108b1578063626485a3146108c75780636352211e146108e75780636d8ea5b4146109075780636eadde431461092757600080fd5b806352b0f6381461081a57806352d6a8e41461083a578063550ef3a81461085a578063564aa99d1461087a57806356e0d51f1461089a57600080fd5b806339f469861161031457806339f46986146107685780634136aa351461078857806342842e0e146107a35780634d025fed146107c35780634f6ccce7146107fa57600080fd5b80632f745c59146106e757806330176e131461070757806336568abe1461072757806338af3eed1461074757600080fd5b806318160ddd116103d3578063248a9ca311610397578063248a9ca31461063557806326e9ca07146106655780632af9162a146106865780632d33dd5b146106a65780632f2ff15d146106c757600080fd5b806318160ddd146105a5578063183767da146105bb578063217751bc146105d257806323100509146105f357806323b872dd1461061557600080fd5b8063097ba3331161041a578063097ba333146105085780630aaffd2a146105365780630f15023b1461055657806310e569731461057757806311a4c03a1461058e57600080fd5b806301ffc9a71461045757806306fdde031461048c578063081812fc146104ae578063095ea7b3146104e657600080fd5b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046152e6565b610de4565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610df5565b6040516104839190615672565b3480156104ba57600080fd5b506104ce6104c93660046152aa565b610e84565b6040516001600160a01b039091168152602001610483565b3480156104f257600080fd5b506105066105013660046151b3565b610f00565b005b34801561051457600080fd5b5061052861052336600461503e565b611035565b604051908152602001610483565b34801561054257600080fd5b50610506610551366004614ee1565b611081565b34801561056257600080fd5b50610c83546104ce906001600160a01b031681565b34801561058357600080fd5b50610528610c855481565b34801561059a57600080fd5b50610528610c845481565b3480156105b157600080fd5b50610c8754610528565b3480156105c757600080fd5b506105286124075481565b3480156105de57600080fd5b50610c8a546104ce906001600160a01b031681565b3480156105ff57600080fd5b506105286000805160206159ed83398151915281565b34801561062157600080fd5b506105066106303660046150a0565b611105565b34801561064157600080fd5b506105286106503660046152aa565b60009081526097602052604090206001015490565b34801561067157600080fd5b50610c8b546104ce906001600160a01b031681565b34801561069257600080fd5b506105066106a1366004614ee1565b611434565b3480156106b257600080fd5b50610c89546104ce906001600160a01b031681565b3480156106d357600080fd5b506105066106e23660046152c2565b6114b7565b3480156106f357600080fd5b506105286107023660046151b3565b6114e2565b34801561071357600080fd5b5061050661072236600461531e565b61156a565b34801561073357600080fd5b506105066107423660046152c2565b6115ab565b34801561075357600080fd5b50610c88546104ce906001600160a01b031681565b34801561077457600080fd5b5061050661078336600461544e565b611629565b34801561079457600080fd5b5061089a546104779060ff1681565b3480156107af57600080fd5b506105066107be3660046150a0565b6116a3565b3480156107cf57600080fd5b506104ce6107de3660046152aa565b611078602052600090815260409020546001600160a01b031681565b34801561080657600080fd5b506105286108153660046152aa565b6116be565b34801561082657600080fd5b50610477610835366004614ee1565b611705565b34801561084657600080fd5b50610528610855366004614ee1565b61171f565b34801561086657600080fd5b5061050661087536600461531e565b61172a565b34801561088657600080fd5b50610506610895366004614ee1565b61176b565b3480156108a657600080fd5b506105286127f05481565b3480156108bd57600080fd5b5061201e54610528565b3480156108d357600080fd5b506105066108e23660046152aa565b6117ee565b3480156108f357600080fd5b506104ce6109023660046152aa565b611828565b34801561091357600080fd5b50610477610922366004614ee1565b611844565b34801561093357600080fd5b50610506610942366004614f28565b61191d565b34801561095357600080fd5b50610528610962366004614ee1565b611a3c565b34801561097357600080fd5b50610528610c865481565b34801561098a57600080fd5b5061050661099936600461531e565b611a84565b3480156109aa57600080fd5b50610c8c546104ce906001600160a01b031681565b3480156109cb57600080fd5b506105066109da3660046151f9565b611b03565b3480156109eb57600080fd5b506105066109fa3660046152aa565b611d71565b610506610a0d3660046153de565b611dde565b348015610a1e57600080fd5b50610528600080516020615a2d83398151915281565b348015610a4057600080fd5b50610477610a4f3660046152c2565b61245e565b348015610a6057600080fd5b506105286110775481565b348015610a7757600080fd5b506104a1612489565b348015610a8c57600080fd5b50610528610a9b366004614ee1565b6001600160a01b03166000908152611075602052604090205490565b348015610ac357600080fd5b50610506610ad2366004614efd565b6125c2565b348015610ae357600080fd5b506104b1546104ce906001600160a01b031681565b348015610b0457600080fd5b50610528600081565b348015610b1957600080fd5b50610506610b28366004615186565b612626565b348015610b3957600080fd5b50610506610b483660046152c2565b6126fe565b348015610b5957600080fd5b506105286127f15481565b348015610b7057600080fd5b50610477610b7f3660046151b3565b612896565b348015610b9057600080fd5b50610477610b9f366004614ee1565b612905565b348015610bb057600080fd5b50610528610bbf366004614ee1565b6001600160a01b03166000908152611075602052604090206001015490565b348015610bea57600080fd5b50610506610bf93660046152c2565b61291f565b348015610c0a57600080fd5b50610477610c193660046151b3565b6129e3565b348015610c2a57600080fd5b50610506610c393660046150e0565b612aa7565b348015610c4a57600080fd5b50610506610c593660046152aa565b612b10565b348015610c6a57600080fd5b50610506612bb4565b348015610c7f57600080fd5b506104a1610c8e3660046152aa565b612c41565b348015610c9f57600080fd5b50610506610cae366004614fe3565b612ef8565b348015610cbf57600080fd5b5060405160098152602001610483565b348015610cdb57600080fd5b50610506610cea366004614ee1565b61312b565b348015610cfb57600080fd5b50610506610d0a3660046152aa565b6131ae565b348015610d1b57600080fd5b50610506610d2a3660046152c2565b613232565b348015610d3b57600080fd5b50610477610d4a366004614fab565b613258565b348015610d5b57600080fd5b506105066132f1565b348015610d7057600080fd5b50610506610d7f3660046151c5565b613336565b348015610d9057600080fd5b50610506610d9f3660046151b3565b61368b565b348015610db057600080fd5b50610506610dbf3660046152aa565b613818565b348015610dd057600080fd5b50610528610ddf3660046151b3565b613852565b6000610def826138cb565b92915050565b6114638054610e0390615937565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2f90615937565b8015610e7c5780601f10610e5157610100808354040283529160200191610e7c565b820191906000526020600020905b815481529060010190602001808311610e5f57829003601f168201915b505050505081565b6000818152611076602052604081205482906001600160a01b0316610ede5760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b60448201526064015b60405180910390fd5b600083815261107960205260409020546001600160a01b031691505b50919050565b61089a5460ff16610f235760405162461bcd60e51b8152600401610ed590615796565b80610f2e81336138d6565b80610f3e5750610f3e813361394e565b80610f67575060008181526110766020526040902054610f67906001600160a01b031633613258565b610f835760405162461bcd60e51b8152600401610ed5906156d5565b336001600160a01b0384161415610fcb5760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b60008281526110796020908152604080832080546001600160a01b0319166001600160a01b03888116918217909255611076909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611078858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b95945050505050565b61108a33612905565b806110a05750610c88546001600160a01b031633145b6110bc5760405162461bcd60e51b8152600401610ed59061570c565b6001600160a01b0381166110e25760405162461bcd60e51b8152600401610ed590615685565b610c8880546001600160a01b0319166001600160a01b0392909216919091179055565b61089a5460ff166111285760405162461bcd60e51b8152600401610ed590615796565b8261113281611844565b61114e5760405162461bcd60e51b8152600401610ed5906156ae565b8161115981336138d6565b806111695750611169813361394e565b80611192575060008181526110766020526040902054611192906001600160a01b031633613258565b6111ae5760405162461bcd60e51b8152600401610ed5906156d5565b846001600160a01b03166111c184611828565b6001600160a01b0316146112175760405162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e4552000000006044820152606401610ed5565b61271061240754106112645760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661128a5760405162461bcd60e51b8152600401610ed590615685565b836001600160a01b0316856001600160a01b031614156112df5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b60006112ec866000613852565b6001600160a01b03808816600090815261107560205260408082209289168252812060018101549394509192906113269088908690613a1f565b8154611342578682556113398888613b1f565b61134287613b9d565b4281116113705760018084015490830155868255611361876000613bdc565b61136b8888613b1f565b6113f8565b600019610c845414156113d75760405162461bcd60e51b815260206004820152602960248201527f526563697069656e7420616c7265616479206f776e732061206e6f6e2d6578706044820152686972696e67206b657960b81b6064820152608401610ed5565b428184600101546113e89190615861565b6113f291906158dd565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615a0d83398151915291a4505050505050505050565b61144c600080516020615a2d8339815191523361245e565b6114685760405162461bcd60e51b8152600401610ed590615741565b6114806000805160206159ed83398151915282613232565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6000828152609760205260409020600101546114d38133613c69565b6114dd8383613ccd565b505050565b60006114ed83611a3c565b8210801561150357506001600160a01b03831615155b6115485760405162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b6044820152606401610ed5565b6001600160a01b038316600090815261107560205260409020545b9392505050565b611582600080516020615a2d8339815191523361245e565b61159e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114658383614dc9565b6001600160a01b038116331461161b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610ed5565b6116258282613d53565b5050565b611641600080516020615a2d8339815191523361245e565b61165d5760405162461bcd60e51b8152600401610ed590615741565b60408051838152602081018390527fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c910160405180910390a16127f1919091556127f055565b6114dd83838360405180602001604052806000815250612aa7565b6000610c875482106117015760405162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b6044820152606401610ed5565b5090565b6000610def6000805160206159ed8339815191528361245e565b6000610def82613dba565b611742600080516020615a2d8339815191523361245e565b61175e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114638383614dc9565b611783600080516020615a2d8339815191523361245e565b61179f5760405162461bcd60e51b8152600401610ed590615741565b6117b76000805160206159ed833981519152826114b7565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b611806600080516020615a2d8339815191523361245e565b6118225760405162461bcd60e51b8152600401610ed590615741565b610c8455565b600090815261107660205260409020546001600160a01b031690565b6001600160a01b0380821660009081526110756020526040902060010154610c8b544290911191161561191857610c8b546001600160a01b0383811660008181526110756020526040908190206001015490516370b6638f60e11b815230600482015260248101929092526044820152831515606482015291169063e16cc71e9060840160206040518083038186803b1580156118e057600080fd5b505afa1580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def919061528e565b919050565b600054610100900460ff166119385760005460ff161561193c565b303b155b61199f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ed5565b600054610100900460ff161580156119c1576000805461ffff19166101011790555b6119ca86613eda565b6119dd61089a805460ff19166001179055565b6119e988888787613fb1565b6119f38383614053565b6119fb614079565b611a076103e86127f055565b611a108861408b565b611a206380ac58cd60e01b614113565b8015611a32576000805461ff00191690555b5050505050505050565b60006001600160a01b038216611a645760405162461bcd60e51b8152600401610ed590615685565b611a6d82611844565b611a78576000611a7b565b60015b60ff1692915050565b611a9c600080516020615a2d8339815191523361245e565b611ab85760405162461bcd60e51b8152600401610ed590615741565b611ac56114648383614dc9565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb978282604051611af792919061565e565b60405180910390a15050565b611b0c33611705565b80611b1b5750611b1b33612905565b611b995760405162461bcd60e51b815260206004820152604360248201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560448201527f20746865204b65794772616e746572206f72204c6f636b4d616e6167657220726064820152626f6c6560e81b608482015260a401610ed5565b60005b85811015611d68576000878783818110611bc657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bdb9190614ee1565b90506000868684818110611bff57634e487b7160e01b600052603260045260246000fd5b9050602002013590506000858585818110611c2a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c3f9190614ee1565b90506001600160a01b038316611c675760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b03831660009081526110756020526040902060018101548311611cc65760405162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b6044820152606401610ed5565b805480611ce357611cd682614192565b508054611ce38582613b1f565b611ced8184613bdc565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615a0d833981519152908290a450505050508080611d609061596c565b915050611b9c565b50505050505050565b611d89600080516020615a2d8339815191523361245e565b611da55760405162461bcd60e51b8152600401610ed590615741565b6040518181527f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49060200160405180910390a161240755565b61089a5460ff16611e015760405162461bcd60e51b8152600401610ed590615796565b610c8754610c865411611e465760405162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b6044820152606401610ed5565b6001600160a01b038516611e6c5760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b0385166000908152611075602052604081208054909181611f0857611e9783614192565b82549150611ea58883613b1f565b600019610c84541415611ebb5750600019611ecc565b610c8454611ec99042615861565b90505b60018301819055611edd8287613bdc565b60405182906001600160a01b038a1690600090600080516020615a0d833981519152908290a4612062565b4283600101541115611fe65760001983600101541415611f865760405162461bcd60e51b815260206004820152603360248201527f412076616c6964206e6f6e2d6578706972696e67206b65792063616e206e6f746044820152722062652070757263686173656420747769636560681b6064820152608401610ed5565b610c84548360010154611f999190615861565b600184018190556040518181529091506001600160a01b038916907f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9060200160405180910390a2612062565b600019610c84541415611ffc575060001961200d565b610c845461200a9042615861565b90505b6001830181905561201e8287613bdc565b876001600160a01b03167f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d8260405161205991815260200190565b60405180910390a25b60006120a5898988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b610c835460405163939d9f1f60e01b8152600481018390526001600160a01b038b8116602483015292935091169063939d9f1f90604401600060405180830381600087803b1580156120f657600080fd5b505af1925050508015612107575060015b61214f57610c83546040516001600160a01b03909116815230907f6b18946261693dfd6c760d986b28ad2238b5b0267f8e5b6bc40a2f998e2f20ac9060200160405180910390a25b6104b1546000906001600160a01b0316156121f957506104b1546040516323b872dd60e01b8152336004820152306024820152604481018c90528b916001600160a01b03169081906323b872dd90606401602060405180830381600087803b1580156121ba57600080fd5b505af11580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061528e565b50506121fc565b50345b818110156122415760405162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b6044820152606401610ed5565b610c89546001600160a01b0316156122c357610c8954604051639849965760e01b81526001600160a01b03909116906398499657906122909033908e908e908d908d908a908a906004016155ac565b600060405180830381600087803b1580156122aa57600080fd5b505af11580156122be573d6000803e3d6000fd5b505050505b61201e5415612451576104b1546001600160a01b031615612377576104b15461201e546040516323b872dd60e01b815230600482015233602482015260448101919091526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561233857600080fd5b505af115801561234c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612370919061528e565b5050612404565b61201e5460405160009133918381818185875af1925050503d80600081146123bb576040519150601f19603f3d011682016040523d82523d6000602084013e6123c0565b606091505b50509050806124025760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610ed5565b505b61201e546104b154604080519283526001600160a01b03909116602083015233917f522a883b471164223f18b50f326da8671372b64b4792eac0e63d447e714c3e3b910160405180910390a25b5050505050505050505050565b60009182526097602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060611464805461249990615937565b1515905061253157610c8360009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f057600080fd5b505afa158015612504573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261252c919081019061535d565b905090565b611464805461253f90615937565b80601f016020809104026020016040519081016040528092919081815260200182805461256b90615937565b80156125b85780601f1061258d576101008083540402835291602001916125b8565b820191906000526020600020905b81548152906001019060200180831161259b57829003601f168201915b5050505050905090565b6125da600080516020615a2d8339815191523361245e565b6125f65760405162461bcd60e51b8152600401610ed590615741565b8161260081611844565b61261c5760405162461bcd60e51b8152600401610ed5906156ae565b6114dd83836141b6565b61089a5460ff166126495760405162461bcd60e51b8152600401610ed590615796565b6001600160a01b0382163314156126915760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b33600081815261107a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612716600080516020615a2d8339815191523361245e565b6127325760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff166127555760405162461bcd60e51b8152600401610ed590615796565b610c85546104b1546001600160a01b0390811690831615806127e757506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ad57600080fd5b505afa1580156127c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e591906153c6565b115b6128235760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b610c858490556104b180546001600160a01b0319166001600160a01b0385811691821790925560408051858152602081018890529284169083015260608201527f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d49060800160405180910390a150505050565b600080610c8454836128a891906158be565b336000908152611075602052604081206001810154929350916128cc9042906158dd565b9050808310156128ea576128e586836000015485613336565b6128f9565b6128f933878460000154611105565b50600195945050505050565b6000610def600080516020615a2d8339815191528361245e565b6000828152611076602052604090205482906001600160a01b03166129745760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b6044820152606401610ed5565b61297e83336138d6565b8061298d575061298d33612905565b6129d95760405162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f555044415445006044820152606401610ed5565b6114dd8383613bdc565b60006129ee33612905565b80612a045750610c88546001600160a01b031633145b612a205760405162461bcd60e51b8152600401610ed59061570c565b6104b15460405163095ea7b360e01b81526001600160a01b038581166004830152602482018590529091169063095ea7b390604401602060405180830381600087803b158015612a6f57600080fd5b505af1158015612a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611563919061528e565b612ab2848484611105565b612abe848484846142b1565b612b0a5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b50505050565b612b28600080516020615a2d8339815191523361245e565b612b445760405162461bcd60e51b8152600401610ed590615741565b610c87548111612bae5760405162461bcd60e51b815260206004820152602f60248201527f6d61784e756d6265724f664b65797320697320736d616c6c6572207468616e2060448201526e6578697374696e6720737570706c7960881b6064820152608401610ed5565b610c8655565b612bcc600080516020615a2d8339815191523361245e565b612be85760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff16612c0b5760405162461bcd60e51b8152600401610ed590615796565b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a161089a805460ff19169055565b606080806000612c5030614370565b905060608515612c6a57612c63866145cb565b9250612c7d565b6040518060200160405280600081525092505b610c8c546001600160a01b031615612d6b576000612c9a87611828565b90506000612cc1826001600160a01b03166000908152611075602052604090206001015490565b610c8c5460405163988b93ad60e01b81523060048201523360248201526001600160a01b038581166044830152606482018c90526084820184905292935091169063988b93ad9060a40160006040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d5f919081019061535d565b98975050505050505050565b6114658054612d7990615937565b15159050612e2f57610c8360009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b158015612dd057600080fd5b505afa158015612de4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e0c919081019061535d565b9350604051806040016040528060018152602001602f60f81b8152509050612ee2565b6114658054612e3d90615937565b80601f0160208091040260200160405190810160405280929190818152602001828054612e6990615937565b8015612eb65780601f10612e8b57610100808354040283529160200191612eb6565b820191906000526020600020905b815481529060010190602001808311612e9957829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b612eee84838386614713565b9695505050505050565b612f10600080516020615a2d8339815191523361245e565b612f2c5760405162461bcd60e51b8152600401610ed590615741565b6001600160a01b0384161580612f4b57506001600160a01b0384163b15155b612f975760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b00000000000000006044820152606401610ed5565b6001600160a01b0383161580612fb657506001600160a01b0383163b15155b6130025760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b0000000000006044820152606401610ed5565b6001600160a01b038216158061302157506001600160a01b0382163b15155b61306d5760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f56414c49445f4b45595f484f4f4b000000000000006044820152606401610ed5565b6001600160a01b038116158061308c57506001600160a01b0381163b15155b6130d85760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f544f4b454e5f5552495f484f4f4b000000000000006044820152606401610ed5565b610c8980546001600160a01b039586166001600160a01b031991821617909155610c8a805494861694821694909417909355610c8c8054918516918416919091179055610c8b8054919093169116179055565b613143600080516020615a2d8339815191523361245e565b61315f5760405162461bcd60e51b8152600401610ed590615741565b613177600080516020615a2d833981519152826114b7565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b806131b981336138d6565b806131c957506131c9813361394e565b806131f25750600081815261107660205260409020546131f2906001600160a01b031633613258565b61320e5760405162461bcd60e51b8152600401610ed5906156d5565b600061321983611828565b9050600061322682613dba565b9050612b0a82826141b6565b60008281526097602052604090206001015461324e8133613c69565b6114dd8383613d53565b6001600160a01b03808316600090815261107560209081526040808320548084526110789092528220549192909116806132be575050506001600160a01b03808316600090815261107a602090815260408083209385168352929052205460ff16610def565b6001600160a01b03908116600090815261107a602090815260408083209387168352929052205460ff169150610def9050565b613309600080516020615a2d833981519152336115ab565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b61089a5460ff166133595760405162461bcd60e51b8152600401610ed590615796565b8161336481336138d6565b806133745750613374813361394e565b8061339d57506000818152611076602052604090205461339d906001600160a01b031633613258565b6133b95760405162461bcd60e51b8152600401610ed5906156d5565b61271061240754106134065760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661342c5760405162461bcd60e51b8152600401610ed590615685565b600083815261107660205260409020546001600160a01b031661344e81611844565b61346a5760405162461bcd60e51b8152600401610ed5906156ae565b846001600160a01b0316816001600160a01b031614156134bf5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b6001600160a01b038082166000908152611075602052604080822092881682528120805460018401549192909181906134f99042906158dd565b90506000613507878a613852565b90506000613515828b615861565b9050828110156135335789935061352e8b826000613a1f565b61357e565b61353d8884613852565b915061354982846158dd565b4260018901556040519094508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b846135c55761358c86614192565b8554945061359a8c86613b1f565b60405185906001600160a01b038e1690600090600080516020615a0d833981519152908290a46135db565b428660010154116135db576135db856000613bdc565b6135e785856001613a1f565b848c6001600160a01b0316896001600160a01b0316600080516020615a0d83398151915260405160405180910390a4613631888d87604051806020016040528060008152506142b1565b61367d5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b505050505050505050505050565b61369433612905565b806136aa5750610c88546001600160a01b031633145b6136c65760405162461bcd60e51b8152600401610ed59061570c565b60006001600160a01b0383166136dd575047613757565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b15801561371c57600080fd5b505afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375491906153c6565b90505b600082158061376557508183115b156137b457600082116137ad5760405162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b6044820152606401610ed5565b50806137b7565b50815b610c88546040518281526001600160a01b039182169186169033907f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9060200160405180910390a4610c8854612b0a9085906001600160a01b031683614745565b613830600080516020615a2d8339815191523361245e565b61384c5760405162461bcd60e51b8152600401610ed590615741565b61201e55565b600061385d83611844565b61386957506000610def565b6001600160a01b0383166000908152611075602052604081209080846138a05742836001015461389991906158dd565b91506138a4565b8491505b61271061240754836138b691906158be565b6138c0919061589e565b9350610def92505050565b6000610def82614781565b600082815261107860205260408120546001600160a01b03838116911614806139395750600083815261107860205260409020546001600160a01b03161580156139395750816001600160a01b031661392e84611828565b6001600160a01b0316145b1561394657506001610def565b506000610def565b60009182526110796020526040909120546001600160a01b0391821691161490565b610c89546000906001600160a01b031615613a1357610c895460405163221c1fd160e01b81526001600160a01b039091169063221c1fd1906139bc9033908890889088906004016155f7565b60206040518083038186803b1580156139d457600080fd5b505afa1580156139e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0c91906153c6565b9050611563565b50610c85549392505050565b6000613a2a84611828565b90506001600160a01b038116613a755760405162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b6044820152606401610ed5565b6001600160a01b03811660009081526110756020526040812060018101549091613a9e84611844565b90508415613aca578015613ac057613ab68683615861565b6001840155613ada565b613ab68642615861565b613ad486836158dd565b60018401555b60408051878152861515602082015288917fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3910160405180910390a250505050505050565b6001600160a01b0382166000908152611075602090815260409182902082518084019093528054835260010154908201819052613b6d576110778054906000613b678361596c565b91905055505b5060009081526110766020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600081815261107960205260409020546001600160a01b031615613bd95760008181526110796020526040902080546001600160a01b03191690555b50565b600082815261107860205260409020546001600160a01b038281169116146116255760008281526110786020526040902080546001600160a01b0319166001600160a01b038316179055613c2f82613b9d565b6040516001600160a01b0382169083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a35050565b613c73828261245e565b61162557613c8b816001600160a01b0316601461478c565b613c9683602061478c565b604051602001613ca7929190615537565b60408051601f198184030181529082905262461bcd60e51b8252610ed591600401615672565b613cd7828261245e565b6116255760008281526097602090815260408083206001600160a01b03851684529091529020805460ff19166001179055613d0f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b613d5d828261245e565b156116255760008281526097602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600081613dc681611844565b613de25760405162461bcd60e51b8152600401610ed5906156ae565b6001600160a01b038316600090815261107560205260409020610c84546000191415613e1457610c8554925050610efa565b6000428260010154613e2691906158dd565b9050610c84546127f15482613e3b9190615861565b10613e4b57610c85549350613e6b565b610c845481610c8554613e5e91906158be565b613e68919061589e565b93505b6127f1541580613e8a5750610c84546127f154613e889083615861565b105b15613ed25760006127106127f054610c8554613ea691906158be565b613eb0919061589e565b905080851115613ecb57613ec481866158dd565b9450613ed0565b600094505b505b505050919050565b6104b180546001600160a01b0319166001600160a01b0383169081179091551580613f7557506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f3b57600080fd5b505afa158015613f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7391906153c6565b115b613bd95760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b63bbf81e008311156140055760405162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f594541525300000000000000006044820152606401610ed5565b610c838054336001600160a01b031991821617909155610c8880549091166001600160a01b038616179055821561403c5782614040565b6000195b610c8455610c8591909155610c86555050565b61405b61496d565b6140686114638383614dc9565b50611625635b5e139f60e01b614113565b61408963780e9d6360e01b614113565b565b6140a3600080516020615a2d833981519152806149a4565b6140c96000805160206159ed833981519152600080516020615a2d8339815191526149a4565b6140d281612905565b6140ee576140ee600080516020615a2d833981519152826149ef565b6140f781611705565b613bd957613bd96000805160206159ed833981519152826149ef565b6001600160e01b0319808216141561416d5760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e74657266616365206964000000006044820152606401610ed5565b6001600160e01b0319166000908152606560205260409020805460ff19166001179055565b8054613bd957610c8780549060006141a98361596c565b9091555050610c87549055565b6001600160a01b0382166000818152611075602052604090819020805491519092339290917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce5289061420a9087815260200190565b60405180910390a44260018201558115614236576104b154614236906001600160a01b03168484614745565b610c8a546001600160a01b0316156114dd57610c8a5460405163b499b6c560e01b81523360048201526001600160a01b038581166024830152604482018590529091169063b499b6c590606401600060405180830381600087803b15801561429d57600080fd5b505af1158015611d68573d6000803e3d6000fd5b60006001600160a01b0384163b6142ca57506001614368565b604051630a85bd0160e11b81526000906001600160a01b0386169063150b7a02906142ff9033908a908990899060040161562b565b602060405180830381600087803b15801561431957600080fd5b505af115801561432d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143519190615302565b6001600160e01b031916630a85bd0160e11b149150505b949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b816000815181106143e957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061442657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060005b60148110156145c2578260048561445884600c615861565b6020811061447657634e487b7160e01b600052603260045260246000fd5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106144aa57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826144c58360026158be565b6144d0906002615861565b815181106144ee57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350828461451283600c615861565b6020811061453057634e487b7160e01b600052603260045260246000fd5b825191901a600f1690811061455557634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826145708360026158be565b61457b906003615861565b8151811061459957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350806145ba8161596c565b915050614440565b50949350505050565b606081806145f25750506040805180820190915260018152600360fc1b6020820152919050565b8260005b811561461c57806146068161596c565b91506146159050600a8361589e565b91506145f6565b6000816001600160401b0381111561464457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561466e576020820181803683370190505b509050815b8415614709576146846001826158dd565b90506000614693600a8761589e565b61469e90600a6158be565b6146a890876158dd565b6146b3906030615879565b905060008160f81b9050808484815181106146de57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614700600a8861589e565b96505050614673565b5095945050505050565b60608484848460405160200161472c94939291906154e0565b6040516020818303038152906040529050949350505050565b80156114dd576001600160a01b03831661476c576114dd6001600160a01b038316826149f9565b82612b0a6001600160a01b0382168484614b12565b6000610def82614b64565b6060600061479b8360026158be565b6147a6906002615861565b6001600160401b038111156147cb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147f5576020820181803683370190505b509050600360fc1b8160008151811061481e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061485b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061487f8460026158be565b61488a906001615861565b90505b600181111561491e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106148cc57634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106148f057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361491781615920565b905061488d565b5083156115635760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ed5565b600054610100900460ff166149945760405162461bcd60e51b8152600401610ed5906157bf565b61499c614b89565b614089614b89565b600082815260976020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6116258282613ccd565b80471015614a495760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ed5565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614a96576040519150601f19603f3d011682016040523d82523d6000602084013e614a9b565b606091505b50509050806114dd5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ed5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114dd908490614bb0565b60006001600160e01b03198216637965db0b60e01b1480610def5750610def82614c82565b600054610100900460ff166140895760405162461bcd60e51b8152600401610ed5906157bf565b6000614c05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614cbe9092919063ffffffff16565b8051909150156114dd5780806020019051810190614c23919061528e565b6114dd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ed5565b60006301ffc9a760e01b6001600160e01b031983161480610def5750506001600160e01b03191660009081526065602052604090205460ff1690565b6060614368848460008585843b614d175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ed5565b600080866001600160a01b03168587604051614d3391906154c4565b60006040518083038185875af1925050503d8060008114614d70576040519150601f19603f3d011682016040523d82523d6000602084013e614d75565b606091505b5091509150614d85828286614d90565b979650505050505050565b60608315614d9f575081611563565b825115614daf5782518084602001fd5b8160405162461bcd60e51b8152600401610ed59190615672565b828054614dd590615937565b90600052602060002090601f016020900481019282614df75760008555614e3d565b82601f10614e105782800160ff19823516178555614e3d565b82800160010185558215614e3d579182015b82811115614e3d578235825591602001919060010190614e22565b506117019291505b808211156117015760008155600101614e45565b60008083601f840112614e6a578182fd5b5081356001600160401b03811115614e80578182fd5b6020830191508360208260051b8501011115614e9b57600080fd5b9250929050565b60008083601f840112614eb3578182fd5b5081356001600160401b03811115614ec9578182fd5b602083019150836020828501011115614e9b57600080fd5b600060208284031215614ef2578081fd5b8135611563816159b3565b60008060408385031215614f0f578081fd5b8235614f1a816159b3565b946020939093013593505050565b600080600080600080600060c0888a031215614f42578283fd5b8735614f4d816159b3565b9650602088013595506040880135614f64816159b3565b9450606088013593506080880135925060a08801356001600160401b03811115614f8c578283fd5b614f988a828b01614ea2565b989b979a50959850939692959293505050565b60008060408385031215614fbd578182fd5b8235614fc8816159b3565b91506020830135614fd8816159b3565b809150509250929050565b60008060008060808587031215614ff8578384fd5b8435615003816159b3565b93506020850135615013816159b3565b92506040850135615023816159b3565b91506060850135615033816159b3565b939692955090935050565b60008060008060608587031215615053578384fd5b843561505e816159b3565b9350602085013561506e816159b3565b925060408501356001600160401b03811115615088578283fd5b61509487828801614ea2565b95989497509550505050565b6000806000606084860312156150b4578081fd5b83356150bf816159b3565b925060208401356150cf816159b3565b929592945050506040919091013590565b600080600080608085870312156150f5578182fd5b8435615100816159b3565b93506020850135615110816159b3565b92506040850135915060608501356001600160401b03811115615131578182fd5b8501601f81018713615141578182fd5b803561515461514f8261583a565b61580a565b818152886020838501011115615168578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615198578182fd5b82356151a3816159b3565b91506020830135614fd8816159c8565b60008060408385031215614f0f578182fd5b6000806000606084860312156151d9578081fd5b83356151e4816159b3565b95602085013595506040909401359392505050565b60008060008060008060608789031215615211578384fd5b86356001600160401b0380821115615227578586fd5b6152338a838b01614e59565b9098509650602089013591508082111561524b578586fd5b6152578a838b01614e59565b9096509450604089013591508082111561526f578384fd5b5061527c89828a01614e59565b979a9699509497509295939492505050565b60006020828403121561529f578081fd5b8151611563816159c8565b6000602082840312156152bb578081fd5b5035919050565b600080604083850312156152d4578182fd5b823591506020830135614fd8816159b3565b6000602082840312156152f7578081fd5b8135611563816159d6565b600060208284031215615313578081fd5b8151611563816159d6565b60008060208385031215615330578182fd5b82356001600160401b03811115615345578283fd5b61535185828601614ea2565b90969095509350505050565b60006020828403121561536e578081fd5b81516001600160401b03811115615383578182fd5b8201601f81018413615393578182fd5b80516153a161514f8261583a565b8181528560208385010111156153b5578384fd5b6110788260208301602086016158f4565b6000602082840312156153d7578081fd5b5051919050565b60008060008060008060a087890312156153f6578384fd5b863595506020870135615408816159b3565b94506040870135615418816159b3565b93506060870135615428816159b3565b925060808701356001600160401b03811115615442578283fd5b61527c89828a01614ea2565b60008060408385031215615460578182fd5b50508035926020909101359150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526154b08160208601602086016158f4565b601f01601f19169290920160200192915050565b600082516154d68184602087016158f4565b9190910192915050565b600085516154f2818460208a016158f4565b855190830190615506818360208a016158f4565b85519101906155198183602089016158f4565b845191019061552c8183602088016158f4565b019695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161556f8160178501602088016158f4565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516155a08160288401602088016158f4565b01602801949350505050565b6001600160a01b03888116825287811660208301528616604082015260c0606082018190526000906155e1908301868861546f565b60808301949094525060a0015295945050505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090612eee90830184615498565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612eee90830184615498565b60208152600061436860208301848661546f565b6020815260006115636020830184615498565b6020808252600f908201526e494e56414c49445f4144445245535360881b604082015260600190565b6020808252600d908201526c12d15657d393d517d590531251609a1b604082015260600190565b6020808252601c908201527f4f4e4c595f4b45595f4d414e414745525f4f525f415050524f56454400000000604082015260600190565b6020808252818101527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604082015260600190565b60208082526035908201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560408201527420746865204c6f636b4d616e6167657220726f6c6560581b606082015260800190565b6020808252600f908201526e1313d0d2d7d11154149150d0551151608a1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156158325761583261599d565b604052919050565b60006001600160401b038211156158535761585361599d565b50601f01601f191660200190565b6000821982111561587457615874615987565b500190565b600060ff821660ff84168060ff0382111561589657615896615987565b019392505050565b6000826158b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156158d8576158d8615987565b500290565b6000828210156158ef576158ef615987565b500390565b60005b8381101561590f5781810151838201526020016158f7565b83811115612b0a5750506000910152565b60008161592f5761592f615987565b506000190190565b600181811c9082168061594b57607f821691505b60208210811415610efa57634e487b7160e01b600052602260045260246000fd5b600060001982141561598057615980615987565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613bd957600080fd5b8015158114613bd957600080fd5b6001600160e01b031981168114613bd957600080fdfeb309c40027c81d382c3b58d8de24207a34b27e1db369b1434e4a11311f154b5eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efb89cdd26cddd51301940bf2715f765b626b8a5a9e2681ac62dc83cc2db2530c0a2646970667358221220a966aec0ea72cc36f07dd0afa1e277f5eb266146078b7651e59c22655e0639ae64736f6c63430008040033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/packages/contracts/src/abis/Unlock/UnlockV9.json b/packages/contracts/src/abis/Unlock/UnlockV9.json deleted file mode 100644 index 2c2593cb66e..00000000000 --- a/packages/contracts/src/abis/Unlock/UnlockV9.json +++ /dev/null @@ -1,633 +0,0 @@ -{ - "contractName": "Unlock", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "udt", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "weth", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "estimatedGasForPurchase", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenSymbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "globalTokenURI", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "name": "ConfigUnlock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "lockOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "NewLock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "grossNetworkProduct", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiscountGranted", - "type": "uint256" - } - ], - "name": "ResetTrackedValue", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "publicLockAddress", - "type": "address" - } - ], - "name": "SetLockTemplate", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "chainId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "estimatedGasForPurchase", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "globalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grossNetworkProduct", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isOwner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "locks", - "outputs": [ - { - "internalType": "bool", - "name": "deployed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "totalSales", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "yieldedDiscountTokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "publicLockAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalDiscountGranted", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "udt", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "uniswapOracles", - "outputs": [ - { - "internalType": "contract IUniswapOracle", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "weth", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_unlockOwner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_expirationDuration", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_lockName", - "type": "string" - }, - { - "internalType": "bytes12", - "name": "_salt", - "type": "bytes12" - } - ], - "name": "createLock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "computeAvailableDiscountFor", - "outputs": [ - { - "internalType": "uint256", - "name": "discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokens", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_referrer", - "type": "address" - } - ], - "name": "recordKeyPurchase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_discount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "recordConsumedDiscount", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "unlockVersion", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_udt", - "type": "address" - }, - { - "internalType": "address", - "name": "_weth", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_estimatedGasForPurchase", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "_URI", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - } - ], - "name": "configUnlock", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "_publicLockAddress", - "type": "address" - } - ], - "name": "setLockTemplate", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_tokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracleAddress", - "type": "address" - } - ], - "name": "setOracle", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_grossNetworkProduct", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_totalDiscountGranted", - "type": "uint256" - } - ], - "name": "resetTrackedValue", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalBaseTokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getGlobalTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x6080604052611d43806100136000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80637ff94bb2116100f9578063a998e9fb11610097578063d6e9e80311610071578063d6e9e80314610612578063ef67fde61461061a578063f2fde38b14610640578063f832899114610666576101a9565b8063a998e9fb146105dc578063c4d66de8146105e4578063cec410521461060a576101a9565b8063939d9f1f116100d3578063939d9f1f1461057d578063963a9478146105a95780639a8a0592146105cc578063a082eb0e146105d4576101a9565b80637ff94bb2146105515780638da5cb5b146105595780638f32d59b14610561576101a9565b806342d92106116101665780636bced5a2116101405780636bced5a214610427578063715018a61461044d578063743bbc2f146104555780637d8fb6411461046f576101a9565b806342d92106146102e05780635c38eb3a146103b35780635de9a137146103e1576101a9565b80630cb175e3146101ae578063262d0a85146101f357806335a750de1461021757806336524663146102945780633fc8cef3146102b95780634220bd46146102c1575b600080fd5b6101da600480360360408110156101c457600080fd5b506001600160a01b03813516906020013561066e565b6040805192835260208301919091528051918290030190f35b6101fb610677565b604080516001600160a01b039092168252519081900360200190f35b61021f610686565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610259578181015183820152602001610241565b50505050905090810190601f1680156102865780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102b7600480360360408110156102aa57600080fd5b508035906020013561071d565b005b6101fb61077b565b6102c961078a565b6040805161ffff9092168252519081900360200190f35b6102b7600480360360c08110156102f657600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561033257600080fd5b82018360208201111561034457600080fd5b8035906020019184600183028401116401000000008311171561036657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061078f9050565b6102b7600480360360408110156103c957600080fd5b506001600160a01b03813581169160200135166109ab565b610407600480360360208110156103f757600080fd5b50356001600160a01b0316610a96565b604080519315158452602084019290925282820152519081900360600190f35b6101fb6004803603602081101561043d57600080fd5b50356001600160a01b0316610abb565b6102b7610ad6565b61045d610b67565b60408051918252519081900360200190f35b6102b7600480360360c081101561048557600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104c057600080fd5b8201836020820111156104d257600080fd5b803590602001918460018302840111640100000000831117156104f457600080fd5b91939092909160208101903564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184600183028401116401000000008311171561054657600080fd5b919350915035610b6d565b61021f610ce4565b6101fb610d45565b610569610d54565b604080519115158252519081900360200190f35b6102b76004803603604081101561059357600080fd5b50803590602001356001600160a01b0316610d7a565b6102b7600480360360408110156105bf57600080fd5b5080359060200135611484565b61045d611514565b61045d61151a565b61021f611520565b6102b7600480360360208110156105fa57600080fd5b50356001600160a01b03166115ae565b61021f611659565b61045d6116b4565b6102b76004803603602081101561063057600080fd5b50356001600160a01b03166116ba565b6102b76004803603602081101561065657600080fd5b50356001600160a01b0316611831565b6101fb611884565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b820191906000526020600020905b8154815290600101906020018083116106f557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661076e576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600990565b606b546001600160a01b03166107e4576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b54600090610814906001600160a01b03168363ffffffff61189316565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108b95781810151838201526020016108a1565b50505050905090810190601f1680156108e65780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b6109b3610d54565b6109f2576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561077757606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610ade610d54565b610b1d576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b610b75610d54565b610bb4576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055610bf5606a8686611be1565b50610c0260698484611be1565b50806070819055507fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be67888888888888888860405180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b0316815260200187815260200180602001806020018481526020018381038352888882818152602001925080828437600083820152601f01601f191690910184810383528681526020019050868680828437600083820152604051601f909101601f19169092018290039c50909a5050505050505050505050a15050505050505050565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b6033546001600160a01b031690565b6033546000906001600160a01b0316610d6b61198b565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610dcb576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561077757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0d57600080fd5b505afa158015610e21573d6000803e3d6000fd5b505050506040513d6020811015610e3757600080fd5b505190506001600160a01b03811615801590610e615750606d546001600160a01b03828116911614155b15610f1a576001600160a01b038082166000908152606c6020526040902054168015610f1457606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610ee557600080fd5b505af1158015610ef9573d6000803e3d6000fd5b505050506040513d6020811015610f0f57600080fd5b505192505b50610f1e565b8391505b606654610f31908363ffffffff61198f16565b6066553360009081526068602052604090206001018054830190556001600160a01b0383161561147e57606e546001600160a01b039081166000908152606c602052604090205416801561147c57606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b505050506040513d602081101561101057600080fd5b5051606f54909150600090829060649061103b903a026806c6b935b8bbd4000063ffffffff6119f016565b8161104257fe5b048161104a57fe5b0490506000809050600160705411156111145760665480600288028161106c57fe5b606e54604080516370a0823160e01b8152306004820152905193909204600201926110fd928b926001600160a01b0316916370a08231916024808201926020929091908290030181600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505050506040513d60208110156110ef57600080fd5b50519063ffffffff6119f016565b8161110457fe5b048161110c57fe5b049050611180565b606654600261116d88606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110c557600080fd5b8161117457fe5b048161117c57fe5b0490505b8082111561118c578091505b811561147857600060646111a784601463ffffffff6119f016565b816111ae57fe5b0490506001607054111561135d57606e54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a0823191602480830192602092919082900301818787803b15801561120857600080fd5b505af115801561121c573d6000803e3d6000fd5b505050506040513d602081101561123257600080fd5b505190508381111561135757606e546040805163a9059cbb60e01b81526001600160a01b038c8116600483015285880360248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561129557600080fd5b505af11580156112a9573d6000803e3d6000fd5b505050506040513d60208110156112bf57600080fd5b5050606e546001600160a01b031663a9059cbb6112da610d45565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561132a57600080fd5b505af115801561133e573d6000803e3d6000fd5b505050506040513d602081101561135457600080fd5b50505b50611476565b606e54604080516340c10f1960e01b81526001600160a01b038b811660048301528487036024830152915191909216916340c10f199160448083019260209291908290030181600087803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b505050506040513d60208110156113de57600080fd5b5050606e546001600160a01b03166340c10f196113f9610d45565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561144957600080fd5b505af115801561145d573d6000803e3d6000fd5b505050506040513d602081101561147357600080fd5b50505b505b5050505b505b50505050565b61148c610d54565b6114cb576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60705481565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b820191906000526020600020905b81548152906001019060200180831161158957829003601f168201915b505050505081565b600054610100900460ff16806115c757506115c7611a49565b806115d5575060005460ff16155b6116105760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff1615801561163b576000805460ff1961ff0019909116610100171660011790555b61164482611a4f565b8015610777576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b60665481565b6116c2610d54565b611701576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611839610d54565b611878576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b61188181611b40565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146119225760009350611931565b6101008301516037846000f593505b5050506001600160a01b038116611985576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b6000828201838110156119e9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826119ff57506000611985565b82820282848281611a0c57fe5b04146119e95760405162461bcd60e51b8152600401808060200182810382526021815260200180611ca06021913960400191505060405180910390fd5b303b1590565b600054610100900460ff1680611a685750611a68611a49565b80611a76575060005460ff16155b611ab15760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff16158015611adc576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610777576000805461ff00191690555050565b6001600160a01b038116611b855760405162461bcd60e51b8152600401808060200182810382526026815260200180611c7a6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c225782800160ff19823516178555611c4f565b82800160010185558215611c4f579182015b82811115611c4f578235825591602001919060010190611c34565b50611c5b929150611c5f565b5090565b61071a91905b80821115611c5b5760008155600101611c6556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820b5be3eecf05b8785daddd76ce8d2c6c2eba8012ba1537f20635313bac678c70a64736f6c63430005110032", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80637ff94bb2116100f9578063a998e9fb11610097578063d6e9e80311610071578063d6e9e80314610612578063ef67fde61461061a578063f2fde38b14610640578063f832899114610666576101a9565b8063a998e9fb146105dc578063c4d66de8146105e4578063cec410521461060a576101a9565b8063939d9f1f116100d3578063939d9f1f1461057d578063963a9478146105a95780639a8a0592146105cc578063a082eb0e146105d4576101a9565b80637ff94bb2146105515780638da5cb5b146105595780638f32d59b14610561576101a9565b806342d92106116101665780636bced5a2116101405780636bced5a214610427578063715018a61461044d578063743bbc2f146104555780637d8fb6411461046f576101a9565b806342d92106146102e05780635c38eb3a146103b35780635de9a137146103e1576101a9565b80630cb175e3146101ae578063262d0a85146101f357806335a750de1461021757806336524663146102945780633fc8cef3146102b95780634220bd46146102c1575b600080fd5b6101da600480360360408110156101c457600080fd5b506001600160a01b03813516906020013561066e565b6040805192835260208301919091528051918290030190f35b6101fb610677565b604080516001600160a01b039092168252519081900360200190f35b61021f610686565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610259578181015183820152602001610241565b50505050905090810190601f1680156102865780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102b7600480360360408110156102aa57600080fd5b508035906020013561071d565b005b6101fb61077b565b6102c961078a565b6040805161ffff9092168252519081900360200190f35b6102b7600480360360c08110156102f657600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561033257600080fd5b82018360208201111561034457600080fd5b8035906020019184600183028401116401000000008311171561036657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061078f9050565b6102b7600480360360408110156103c957600080fd5b506001600160a01b03813581169160200135166109ab565b610407600480360360208110156103f757600080fd5b50356001600160a01b0316610a96565b604080519315158452602084019290925282820152519081900360600190f35b6101fb6004803603602081101561043d57600080fd5b50356001600160a01b0316610abb565b6102b7610ad6565b61045d610b67565b60408051918252519081900360200190f35b6102b7600480360360c081101561048557600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104c057600080fd5b8201836020820111156104d257600080fd5b803590602001918460018302840111640100000000831117156104f457600080fd5b91939092909160208101903564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184600183028401116401000000008311171561054657600080fd5b919350915035610b6d565b61021f610ce4565b6101fb610d45565b610569610d54565b604080519115158252519081900360200190f35b6102b76004803603604081101561059357600080fd5b50803590602001356001600160a01b0316610d7a565b6102b7600480360360408110156105bf57600080fd5b5080359060200135611484565b61045d611514565b61045d61151a565b61021f611520565b6102b7600480360360208110156105fa57600080fd5b50356001600160a01b03166115ae565b61021f611659565b61045d6116b4565b6102b76004803603602081101561063057600080fd5b50356001600160a01b03166116ba565b6102b76004803603602081101561065657600080fd5b50356001600160a01b0316611831565b6101fb611884565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b820191906000526020600020905b8154815290600101906020018083116106f557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661076e576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600990565b606b546001600160a01b03166107e4576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b54600090610814906001600160a01b03168363ffffffff61189316565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108b95781810151838201526020016108a1565b50505050905090810190601f1680156108e65780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b6109b3610d54565b6109f2576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561077757606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610ade610d54565b610b1d576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b610b75610d54565b610bb4576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055610bf5606a8686611be1565b50610c0260698484611be1565b50806070819055507fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be67888888888888888860405180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b0316815260200187815260200180602001806020018481526020018381038352888882818152602001925080828437600083820152601f01601f191690910184810383528681526020019050868680828437600083820152604051601f909101601f19169092018290039c50909a5050505050505050505050a15050505050505050565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b6033546001600160a01b031690565b6033546000906001600160a01b0316610d6b61198b565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610dcb576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561077757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0d57600080fd5b505afa158015610e21573d6000803e3d6000fd5b505050506040513d6020811015610e3757600080fd5b505190506001600160a01b03811615801590610e615750606d546001600160a01b03828116911614155b15610f1a576001600160a01b038082166000908152606c6020526040902054168015610f1457606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610ee557600080fd5b505af1158015610ef9573d6000803e3d6000fd5b505050506040513d6020811015610f0f57600080fd5b505192505b50610f1e565b8391505b606654610f31908363ffffffff61198f16565b6066553360009081526068602052604090206001018054830190556001600160a01b0383161561147e57606e546001600160a01b039081166000908152606c602052604090205416801561147c57606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b505050506040513d602081101561101057600080fd5b5051606f54909150600090829060649061103b903a026806c6b935b8bbd4000063ffffffff6119f016565b8161104257fe5b048161104a57fe5b0490506000809050600160705411156111145760665480600288028161106c57fe5b606e54604080516370a0823160e01b8152306004820152905193909204600201926110fd928b926001600160a01b0316916370a08231916024808201926020929091908290030181600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505050506040513d60208110156110ef57600080fd5b50519063ffffffff6119f016565b8161110457fe5b048161110c57fe5b049050611180565b606654600261116d88606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110c557600080fd5b8161117457fe5b048161117c57fe5b0490505b8082111561118c578091505b811561147857600060646111a784601463ffffffff6119f016565b816111ae57fe5b0490506001607054111561135d57606e54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a0823191602480830192602092919082900301818787803b15801561120857600080fd5b505af115801561121c573d6000803e3d6000fd5b505050506040513d602081101561123257600080fd5b505190508381111561135757606e546040805163a9059cbb60e01b81526001600160a01b038c8116600483015285880360248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561129557600080fd5b505af11580156112a9573d6000803e3d6000fd5b505050506040513d60208110156112bf57600080fd5b5050606e546001600160a01b031663a9059cbb6112da610d45565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561132a57600080fd5b505af115801561133e573d6000803e3d6000fd5b505050506040513d602081101561135457600080fd5b50505b50611476565b606e54604080516340c10f1960e01b81526001600160a01b038b811660048301528487036024830152915191909216916340c10f199160448083019260209291908290030181600087803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b505050506040513d60208110156113de57600080fd5b5050606e546001600160a01b03166340c10f196113f9610d45565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561144957600080fd5b505af115801561145d573d6000803e3d6000fd5b505050506040513d602081101561147357600080fd5b50505b505b5050505b505b50505050565b61148c610d54565b6114cb576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60705481565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b820191906000526020600020905b81548152906001019060200180831161158957829003601f168201915b505050505081565b600054610100900460ff16806115c757506115c7611a49565b806115d5575060005460ff16155b6116105760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff1615801561163b576000805460ff1961ff0019909116610100171660011790555b61164482611a4f565b8015610777576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b60665481565b6116c2610d54565b611701576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611839610d54565b611878576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b61188181611b40565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146119225760009350611931565b6101008301516037846000f593505b5050506001600160a01b038116611985576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b6000828201838110156119e9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826119ff57506000611985565b82820282848281611a0c57fe5b04146119e95760405162461bcd60e51b8152600401808060200182810382526021815260200180611ca06021913960400191505060405180910390fd5b303b1590565b600054610100900460ff1680611a685750611a68611a49565b80611a76575060005460ff16155b611ab15760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff16158015611adc576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610777576000805461ff00191690555050565b6001600160a01b038116611b855760405162461bcd60e51b8152600401808060200182810382526026815260200180611c7a6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c225782800160ff19823516178555611c4f565b82800160010185558215611c4f579182015b82811115611c4f578235825591602001919060010190611c34565b50611c5b929150611c5f565b5090565b61071a91905b80821115611c5b5760008155600101611c6556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820b5be3eecf05b8785daddd76ce8d2c6c2eba8012ba1537f20635313bac678c70a64736f6c63430005110032", - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13.Emscripten.clang" - }, - "schemaVersion": "3.2.4", - "updatedAt": "2021-06-08T19:38:15.028Z" -} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol deleted file mode 100644 index 53127b197dd..00000000000 --- a/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol +++ /dev/null @@ -1,462 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.17 <0.9.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLockV9 { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - // roles - function DEFAULT_ADMIN_ROLE() external pure returns (bytes32 role); - - function KEY_GRANTER_ROLE() external pure returns (bytes32 role); - - function LOCK_MANAGER_ROLE() external pure returns (bytes32 role); - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint16); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function to change the default duration of each key in the lock - * @notice keys previously bought are unaffected by this change (i.e. - * existing keys timestamps are not recalculated/updated) - * @param _newExpirationDuration the new amount of time for each key purchased - * or zero (0) for a non-expiring key - */ - function setExpirationDuration(uint _newExpirationDuration) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - * @param _onValidKeyHook Hook called to determine if the contract should overide the status for a given address - * @param _onTokenURIHook Hook called to generate a data URI used for NFT metadata - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook, - address _onValidKeyHook, - address _onTokenURIHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _keyManager optional address to grant managing rights to a specific address on creation - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - address _keyManager, - bytes calldata _data - ) external payable; - - /** - * @param _gasRefundValue price in wei or token in smallest price unit - * @dev Set the value to be refunded to the sender on purchase - */ - function setGasRefundValue(uint256 _gasRefundValue) external; - - /** - * _gasRefundValue price in wei or token in smallest price unit - * @dev Returns the value/rpice to be refunded to the sender on purchase - */ - function gasRefundValue() external view returns (uint256 _gasRefundValue); - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function onValidKeyHook() external view returns (bool); - - function onTokenURIHook() external view returns (string memory); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - /** - * @dev Change the maximum number of keys the lock can edit - * @param _maxNumberOfKeys uint the maximum number of keys - */ - function setMaxNumberOfKeys(uint _maxNumberOfKeys) external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) external view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - function approve(address to, uint256 tokenId) external; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return operator The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint256 _tokenId - ) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address _owner, - address operator - ) external view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - - function totalSupply() external view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) external view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) external view returns (uint256); - - /** - * Innherited from Open Zeppelin AccessControl.sol - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - function grantRole(bytes32 role, address account) external; - - function revokeRole(bytes32 role, address account) external; - - function renounceRole(bytes32 role, address account) external; - - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV0.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV0.sol deleted file mode 100644 index c20cc840ad2..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV0.sol +++ /dev/null @@ -1,1108 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/ILockCore.sol - -pragma solidity 0.4.25; - -/** - * @title The Lock interface core methods for a Lock - * @author HardlyDifficult (unlock-protocol.com) - */ -interface ILockCore { - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - */ - function purchaseFor(address _recipient, bytes _data) external payable; - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data optional marker for the key - */ - function purchaseForFrom( - address _recipient, - address _referrer, - bytes _data - ) external payable; - - /** - * @dev Called by owner to withdraw all funds from the lock. - */ - function withdraw() external; - - /** - * @dev Called by owner to partially withdraw funds from the lock. - */ - function partialWithdraw(uint _amount) external; - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than outstandingKeys. - */ - function numberOfOwners() external view returns (uint); - - /** - * Public function which returns the total number of keys (both expired and valid) - */ - function outstandingKeys() external view returns (uint); - - /** - * @dev Returns the key's data field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyDataFor(address _owner) external view returns (bytes data); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[]); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.4.25; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * Return type `ILockCore` is the most specific interface from which all lock types inherit. - */ - function createLock( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) external returns (ILockCore lock); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); -} - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.4.25; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - // function safeTransferFrom(address _from, address _to, uint _tokenId, bytes data) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to "" - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - // function safeTransferFrom(address _from, address _to, uint _tokenId) external payable; - - /// @notice Enable or disable approval for a third party ("operator") to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - // function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - // function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} - -// interface ERC721TokenReceiver { -// /// @notice Handle the receipt of an NFT -// /// @dev The ERC721 smart contract calls this function on the -// /// recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return -// /// of other than the magic value MUST result in the transaction being reverted. -// /// @notice The contract address is always the message sender. -// /// @param _operator The address which called `safeTransferFrom` function -// /// @param _from The address which previously owned the token -// /// @param _tokenId The NFT identifier which is being transferred -// /// @param _data Additional data with no specified format -// /// @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` -// /// unless throwing -// function onERC721Received( -// address _operator, -// address _from, -// uint _tokenId, -// bytes _data -// ) -// external -// returns(bytes4); -// } - -// File zos-lib/contracts/Initializable.sol@v2.1.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipRenounced(address indexed previousOwner); - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipRenounced(_owner); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File contracts/interfaces/IERC721Receiver.sol - -pragma solidity 0.4.25; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -interface IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint tokenId, - bytes data - ) public returns (bytes4); -} - -// File openzeppelin-eth/contracts/introspection/IERC165.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title IERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-eth/contracts/introspection/ERC165.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is Initializable, IERC165 { - bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) internal _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - function initialize() public initializer { - _registerInterface(_InterfaceId_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) public view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev private method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } - - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/math/SafeMath.sol@v2.0.2 - -pragma solidity ^0.4.24; - -/** - * @title SafeMath - * @dev Math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two numbers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0); // Solidity only automatically asserts when dividing by 0 - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two numbers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two numbers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.4.25; - -/** - * TODO: consider error codes rather than strings - */ - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ -contract PublicLock is ILockCore, ERC165, IERC721, IERC721Receiver, Ownable { - using SafeMath for uint; - - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - bytes data; // Note: This can be expensive? - } - - // Events - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Fields - // Unlock Protocol address - // TODO: should we make that private/internal? - address public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) internal ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) internal approved; - - /** - * MODIFIERS - */ - // Ensures that an owner has a key - modifier hasKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > 0, "No such key"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > now, "Key is not valid"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(ownerByTokenId[_tokenId] == msg.sender); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "No such key"); - _; - } - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - ownerByTokenId[_tokenId] == msg.sender || - _getApproved(_tokenId) == msg.sender, - "Only key owner or approved owner" - ); - _; - } - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require( - maxNumberOfKeys > numberOfKeysSold, - "Maximum number of keys already sold" - ); - _; - } - - // Constructor - constructor( - address _owner, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) public { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "Expiration duration exceeds 100 years" - ); - unlockProtocol = msg.sender; // Make sure we link back to Unlock's smart contract. - Ownable.initialize(_owner); - ERC165.initialize(); - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - */ - function purchaseFor(address _recipient, bytes _data) external payable { - return _purchaseFor(_recipient, address(0), _data); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data optional marker for the key - */ - function purchaseForFrom( - address _recipient, - address _referrer, - bytes _data - ) external payable hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer, _data); - } - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - external - payable - notSoldOut - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0)); - - uint previousExpiration = keyByOwner[_recipient].expirationTimestamp; - - if (previousExpiration == 0) { - // The recipient did not have a key previously - owners.push(_recipient); - // Note: not using the tokenId above since ATM we do not transfer tokenId's - // this will change when we decouple tokenId from address - ownerByTokenId[uint(_recipient)] = _recipient; - // At the moment tokenId is the user's address, but as we work towards ERC721 - // support this will change to a sequenceId assigned at purchase. - keyByOwner[_recipient].tokenId = uint(_recipient); - } - - if (previousExpiration <= now) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - keyByOwner[_recipient].expirationTimestamp = keyByOwner[_from] - .expirationTimestamp; - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - now` cannot underflow - keyByOwner[_recipient].expirationTimestamp = keyByOwner[_from] - .expirationTimestamp - .add(previousExpiration - now); - } - // Overwite data in all cases - keyByOwner[_recipient].data = keyByOwner[_from].data; - - // Effectively expiring the key for the previous owner - keyByOwner[_from].expirationTimestamp = now; - - // Clear any previous approvals - approved[_tokenId] = address(0); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = address(this).balance; - require(balance > 0, "Not enough funds"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "Must request an amount greater than 0"); - uint256 balance = address(this).balance; - require(balance > 0 && balance >= _amount, "Not enough funds"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyKeyOwner(_tokenId) { - require(_approved != address(0)); - require(msg.sender != _approved, "You can't approve yourself"); - - approved[_tokenId] = _approved; - emit Approval(ownerByTokenId[_tokenId], _approved, _tokenId); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "Invalid address"); - return keyByOwner[_owner].expirationTimestamp > 0 ? 1 : 0; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) external view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than outstandingKeys. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function outstandingKeys() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[]) { - require(outstandingKeys() > 0, "No keys to retrieve"); - uint _startIndex = _page * _pageSize; - require( - _startIndex >= 0 && _startIndex < outstandingKeys(), - "Index must be in-bounds" - ); - uint endOfPageIndex; - - if (_startIndex + _pageSize > owners.length) { - endOfPageIndex = owners.length; - _pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + _pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](_pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - keyByOwner[_owner].expirationTimestamp = now; // Effectively expiring the key - } - - /** - * @dev Returns the key's data field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyDataFor( - address _owner - ) public view hasKey(_owner) returns (bytes memory data) { - return keyByOwner[_owner].data; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view hasKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint,bytes)"))` - */ - function onERC721Received( - address operator, // solhint-disable-line no-unused-vars - address from, // solhint-disable-line no-unused-vars - uint tokenId, // solhint-disable-line no-unused-vars - bytes data // solhint-disable-line no-unused-vars - ) public returns (bytes4) { - return this.onERC721Received.selector; - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * @param _data optional marker for the key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer, - bytes memory _data - ) internal notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0)); - - // Let's get the actual price for the key from the Unlock smart contract - IUnlock unlock = IUnlock(unlockProtocol); - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlock.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts to allow "donations" or partial refunds after - // discounts (TODO implement partial refunds) - require(msg.value >= netPrice, "Insufficient funds"); - // TODO: If there is more than the required price, then let's return whatever is extra - // extra (CAREFUL: re-entrancy!) - - // Assign the key - uint previousExpiration = keyByOwner[_recipient].expirationTimestamp; - if (previousExpiration < now) { - if (previousExpiration == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension - numberOfKeysSold++; - owners.push(_recipient); - // Note: for ERC721 support we will be changing tokenId to be a sequence id instead - ownerByTokenId[uint(_recipient)] = _recipient; - // At the moment tokenId is the user's address, but as we work towards ERC721 - // support this will change to a sequenceId assigned at purchase. - keyByOwner[_recipient].tokenId = uint(_recipient); - } - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - keyByOwner[_recipient].expirationTimestamp = now + expirationDuration; - } else { - // This is an existing owner trying to extend their key - keyByOwner[_recipient].expirationTimestamp = previousExpiration.add( - expirationDuration - ); - } - // Overwite data in all cases - keyByOwner[_recipient].data = _data; - - if (discount > 0) { - unlock.recordConsumedDiscount(discount, tokens); - } - - unlock.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - uint(_recipient) // Note: since each user can own a single token, we use the current - // owner (new!) for the token id - ); - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "No approved recipient exists"); - return approvedRecipient; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - Ownable.owner().transfer(_amount); - emit Withdrawal(msg.sender, _amount); - } -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV1.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV1.sol deleted file mode 100644 index 3a95c65e558..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV1.sol +++ /dev/null @@ -1,1809 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.7; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File contracts/interfaces/ILockCore.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock interface core methods for a Lock - * @author HardlyDifficult (unlock-protocol.com) - */ -interface ILockCore { - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable; - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable; - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Called by owner to withdraw all funds from the lock. - */ - function withdraw() external; - - /** - * @dev Called by owner to partially withdraw funds from the lock. - */ - function partialWithdraw(uint _amount) external; - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external; - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract. - * @dev Reverts if called by anyone but the owner. - * @dev Reverts if isAlive == false - * @dev Should emit Disable event. - */ - function disableLock() external; - - /** - * @dev Used to clean up old lock contracts from the blockchain by using selfdestruct. - * @dev Reverts if called by anyone but the owner. - * @dev Reverts if isAlive == true - * @dev Should emit Destroy event. - */ - function destroyLock() external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Public function which returns the total number of keys (both expired and valid) - * - * This function signature is from the ERC-721 enumerable extension. - * https://eips.ethereum.org/EIPS/eip-721 - * @notice Count NFTs tracked by this contract - * @return A count of valid NFTs tracked by this contract, where each one of - * them has an assigned and queryable owner not equal to the zero address - */ - function totalSupply() external view returns (uint); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); -} - -// File zos-lib/contracts/Initializable.sol@v2.2.2 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title IERC165 - * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is IERC165 { - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - /** - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() internal { - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev internal method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.1.3 - -pragma solidity ^0.5.0; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - emit Destroy(address(this).balance, msg.sender); - selfdestruct(msg.sender); - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * Return type `ILockCore` is the most specific interface from which all lock types inherit. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys - ) external returns (ILockCore lock); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title ERC20 interface - * @dev see https://github.com/ethereum/EIPs/issues/20 - */ -interface IERC20 { - function transfer(address to, uint256 value) external returns (bool); - - function approve(address spender, uint256 value) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool); - - function totalSupply() external view returns (uint256); - - function balanceOf(address who) external view returns (uint256); - - function allowance( - address owner, - address spender - ) external view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint256 value); - - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.7; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - - /** - * Gets the current balance of the account provided. - */ - function _getBalance(address _account) internal view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // The version number for this lock contract, - uint public publicLockVersion; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - constructor( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys, - uint _version - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - publicLockVersion = _version; - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = _getBalance(address(this)); - require(balance > 0, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "GREATER_THAN_ZERO"); - uint balance = _getBalance(address(this)); - require(balance >= _amount, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - _transfer(Ownable.owner(), _amount); - emit Withdrawal(msg.sender, _amount); - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner has a key - modifier hasKey(address _owner) { - Key storage key = keyByOwner[_owner]; - require(key.expirationTimestamp > 0, "NO_SUCH_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return keyByOwner[_owner].expirationTimestamp > 0 ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view hasKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is IERC721, Ownable { - /// A descriptive name for a collection of NFTs in this contract - string private lockName; - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title SafeMath - * @dev Unsigned math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two unsigned integers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two unsigned integers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts of ETH to allow 'donations' - _chargeAtLeast(netPrice); - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - uint previousExpiration = toKey.expirationTimestamp; - if (previousExpiration < block.timestamp) { - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } else { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = previousExpiration.add(expirationDuration); - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.7; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - event CancelKey(uint indexed tokenId, address indexed owner, uint refund); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - Key storage key = _getKeyFor(msg.sender); - - uint refund = _getCancelAndRefundValue(msg.sender); - - emit CancelKey(key.tokenId, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * Utility library of inline functions on addresses - */ -library Address { - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param account address of the account to check - * @return whether the target address is a contract - */ - function isContract(address account) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - // TODO: this value is currently ignored and no fee is charged yet! - uint public transferFeeNumerator = 5; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - } - _recordOwner(_recipient, toKey.tokenId); - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - toKey.expirationTimestamp = fromKey.expirationTimestamp; - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - MixinNoFallback, - ERC721Holder, - IERC721, - ILockCore, - ERC165, - Ownable, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinGrantKeys, - MixinApproval, - MixinLockMetadata, - MixinRefunds, - MixinPurchase, - MixinTransfer -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_expirationDuration, _keyPrice, _maxNumberOfKeys, 1) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV2.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV2.sol deleted file mode 100644 index 2ddc5ce892b..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV2.sol +++ /dev/null @@ -1,2 +0,0 @@ -// Error HH603: Hardhat flatten doesn't support cyclic dependencies. -// For more info go to https://hardhat.org/HH603 or run Hardhat with --show-stack-traces \ No newline at end of file diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV3.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV3.sol deleted file mode 100644 index b080219c9f0..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV3.sol +++ /dev/null @@ -1,2044 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.7; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File zos-lib/contracts/Initializable.sol@v2.2.3 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool wasInitializing = initializing; - initializing = true; - initialized = true; - - _; - - initializing = wasInitializing; - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title IERC165 - * @dev https://eips.ethereum.org/EIPS/eip-165 - */ -interface IERC165 { - /** - * @notice Query if a contract implements an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @dev Interface identification is specified in ERC-165. This function - * uses less than 30,000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC165 - * @author Matt Condon (@shrugs) - * @dev Implements ERC165 using a lookup table. - */ -contract ERC165 is IERC165 { - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - /* - * 0x01ffc9a7 === - * bytes4(keccak256('supportsInterface(bytes4)')) - */ - - /** - * @dev a mapping of interface id to whether or not it's supported - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - /** - * @dev A contract implementing SupportsInterfaceWithLookup - * implement ERC165 itself - */ - constructor() internal { - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev implement supportsInterface(bytes4) using a lookup table - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev internal method for registering an interface - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.2.0 - -pragma solidity ^0.5.2; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title ERC20 interface - * @dev see https://eips.ethereum.org/EIPS/eip-20 - */ -interface IERC20 { - function transfer(address to, uint256 value) external returns (bool); - - function approve(address spender, uint256 value) external returns (bool); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool); - - function totalSupply() external view returns (uint256); - - function balanceOf(address who) external view returns (uint256); - - function allowance( - address owner, - address spender - ) external view returns (uint256); - - event Transfer(address indexed from, address indexed to, uint256 value); - - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.7; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (_price > 0) { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (_amount > 0) { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - } - - /** - * Gets the current balance of the account provided. - */ - function _getBalance(address _account) internal view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - - emit Destroy(address(this).balance, msg.sender); - - // this will send any ETH or ERC20 held by the lock to the owner - _transfer(msg.sender, _getBalance(address(this))); - selfdestruct(msg.sender); - - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.7; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory); - - /** Function to set the globalTokenURI field. - * Should throw if called by other than owner - */ - function setGlobalBaseTokenURI(string calldata _URI) external; - - // Function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function to set the globalTokenSymbol field. - * Should throw if called by other than owner. - */ - function setGlobalTokenSymbol(string calldata _symbol) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal(address indexed _sender, uint _amount); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - constructor( - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Called by owner to withdraw all funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function withdraw() external onlyOwner { - uint balance = _getBalance(address(this)); - require(balance > 0, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(balance); - } - - /** - * @dev Called by owner to partially withdraw funds from the lock. - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - */ - function partialWithdraw(uint _amount) external onlyOwner { - require(_amount > 0, "GREATER_THAN_ZERO"); - uint balance = _getBalance(address(this)); - require(balance >= _amount, "NOT_ENOUGH_FUNDS"); - // Security: re-entrancy not a risk as this is the last line of an external function - _withdraw(_amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } - - /** - * @dev private version of the withdraw function which handles all withdrawals from the lock. - * - * Security: Be wary of re-entrancy when calling this. - */ - function _withdraw(uint _amount) private { - _transfer(Ownable.owner(), _amount); - emit Withdrawal(msg.sender, _amount); - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _owner) { - require(keyByOwner[_owner].expirationTimestamp > 0, "HAS_NEVER_OWNED_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_owner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasValidKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.7; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -contract UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) public pure returns (string memory _concatenatedString) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - string memory abcd = new string( - _ba.length + _bb.length + _bc.length + _bd.length - ); - bytes memory babcd = bytes(abcd); - uint k = 0; - uint i = 0; - for (i = 0; i < _ba.length; i++) { - babcd[k++] = _ba[i]; - } - for (i = 0; i < _bb.length; i++) { - babcd[k++] = _bb[i]; - } - for (i = 0; i < _bc.length; i++) { - babcd[k++] = _bc[i]; - } - for (i = 0; i < _bd.length; i++) { - babcd[k++] = _bd[i]; - } - return string(babcd); - } - - function uint2Str(uint _i) public pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721, - ERC165, - Ownable, - MixinLockCore, - UnlockUtils, - MixinKeys -{ - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string private lockName; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - constructor(string memory _lockName) internal { - lockName = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol(string calldata _lockSymbol) external onlyOwner { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.getGlobalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external onlyOwner { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.getGlobalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return - UnlockUtils.strConcat( - URI, - UnlockUtils.address2Str(address(this)), - "/", - UnlockUtils.uint2Str(_tokenId) - ); - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title SafeMath - * @dev Unsigned math operations with safety checks that revert on error - */ -library SafeMath { - /** - * @dev Multiplies two unsigned integers, reverts on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b); - - return c; - } - - /** - * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a); - uint256 c = a - b; - - return c; - } - - /** - * @dev Adds two unsigned integers, reverts on overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a); - - return c; - } - - /** - * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), - * reverts when dividing by zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // We explicitly allow for greater amounts of ETH to allow 'donations' - _chargeAtLeast(netPrice); - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - uint previousExpiration = toKey.expirationTimestamp; - if (toKey.tokenId == 0) { - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } else { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = previousExpiration.add(expirationDuration); - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - } -} - -// File openzeppelin-solidity/contracts/cryptography/ECDSA.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * @title Elliptic curve signature operations - * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d - * TODO Remove this library once solidity supports passing a signature to ecrecover. - * See https://github.com/ethereum/solidity/issues/864 - */ - -library ECDSA { - /** - * @dev Recover signer address from a message by using their signature - * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. - * @param signature bytes signature, the signature is generated using web3.eth.sign() - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * toEthSignedMessageHash - * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" - * and hash the result - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.7; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyOwnerToNonce; - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - _cancelAndRefund(msg.sender); - } - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external { - require( - ECDSA.recover( - ECDSA.toEthSignedMessageHash( - getCancelAndRefundApprovalHash(_keyOwner, msg.sender) - ), - _signature - ) == _keyOwner, - "INVALID_SIGNATURE" - ); - - keyOwnerToNonce[_keyOwner]++; - _cancelAndRefund(_keyOwner); - } - - /** - * @dev Increments the current nonce for the msg.sender. - * This can be used to invalidate a previously signed message. - */ - function incrementNonce() external { - keyOwnerToNonce[msg.sender]++; - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // Approval enables only one cancel call - keyOwnerToNonce[_keyOwner], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner) internal { - Key storage key = _getKeyFor(_keyOwner); - - uint refund = _getCancelAndRefundValue(_keyOwner); - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.2.0 - -pragma solidity ^0.5.2; - -/** - * Utility library of inline functions on addresses - */ -library Address { - /** - * Returns whether the target address is a contract - * @dev This function will return false if invoked during the constructor of a contract, - * as the code is not actually created until after the constructor finishes. - * @param account address of the account to check - * @return whether the target address is a contract - */ - function isContract(address account) internal view returns (bool) { - uint256 size; - // XXX Currently there is no better way to check if there is a contract in an address - // than to check the size of the code at that address. - // See https://ethereum.stackexchange.com/a/14016/36603 - // for more details about how this works. - // TODO Check this again before the Serenity release, because all addresses will be - // contracts then. - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.7; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - uint public transferFeeNumerator = 0; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - _chargeAtLeast(getTransferFee(_from)); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, toKey.tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _owner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _owner - ) public view hasValidKey(_owner) returns (uint) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - uint fee; - if (timeRemaining >= expirationDuration) { - // Max the potential impact of this fee for keys with long durations remaining - fee = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - fee = keyPrice.mul(timeRemaining) / expirationDuration; - } - return fee.mul(transferFeeNumerator) / transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.7; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IERC721, - MixinNoFallback, - ERC165, - Ownable, - ERC721Holder, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinGrantKeys, - MixinPurchase, - MixinApproval, - MixinTransfer, - MixinRefunds -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_expirationDuration, _keyPrice, _maxNumberOfKeys) - MixinLockMetadata(_lockName) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - // The version number of the current implementation on this network - function publicLockVersion() external pure returns (uint16) { - return 3; - } -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV4.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV4.sol deleted file mode 100644 index 249fed48ef7..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV4.sol +++ /dev/null @@ -1,2199 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/IERC721.sol - -pragma solidity 0.5.9; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd - -interface IERC721 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer( - address indexed _from, - address indexed _to, - uint indexed _tokenId - ); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval( - address indexed _owner, - address indexed _approved, - uint indexed _tokenId - ); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll( - address indexed _owner, - address indexed _operator, - bool _approved - ); - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Set or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint _tokenId) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes calldata data - ) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to '' - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable; - - /// @notice Enable or disable approval for a third party ('operator') to manage - /// all of `msg.sender`'s assets. - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators. - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint _tokenId) external view returns (address); - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll( - address _owner, - address _operator - ) external view returns (bool); - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); -} - -// File zos-lib/contracts/Initializable.sol@v2.3.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File openzeppelin-eth/contracts/ownership/Ownable.sol@v2.1.3 - -pragma solidity ^0.5.0; - -/** - * @title Ownable - * @dev The Ownable contract has an owner address, and provides basic authorization control - * functions, this simplifies the implementation of "user permissions". - */ -contract Ownable is Initializable { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev The Ownable constructor sets the original `owner` of the contract to the sender - * account. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @return the address of the owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner()); - _; - } - - /** - * @return true if `msg.sender` is the owner of the contract. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Allows the current owner to relinquish control of the contract. - * @notice Renouncing to ownership will leave the contract without an owner. - * It will not be possible to call the functions with the `onlyOwner` - * modifier anymore. - */ - function renounceOwnership() public onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0)); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File openzeppelin-solidity/contracts/introspection/IERC165.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC165 standard, as defined in the - * [EIP](https://eips.ethereum.org/EIPS/eip-165). - * - * 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 - * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) - * 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); -} - -// File openzeppelin-solidity/contracts/introspection/ERC165.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Implementation of the `IERC165` interface. - * - * Contracts may inherit from this and call `_registerInterface` to declare - * their support of an interface. - */ -contract ERC165 is IERC165 { - /* - * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 - */ - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - constructor() internal { - // Derived contracts need only register support for their own interfaces, - // we register support for ERC165 itself here - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev See `IERC165.supportsInterface`. - * - * Time complexity O(1), guaranteed to always use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See `IERC165.supportsInterface`. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } -} - -// File openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a `safeTransfer`. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File openzeppelin-solidity/contracts/token/ERC721/ERC721Holder.sol@v2.3.0 - -pragma solidity ^0.5.0; - -contract ERC721Holder is IERC721Receiver { - function onERC721Received( - address, - address, - uint256, - bytes memory - ) public returns (bytes4) { - return this.onERC721Received.selector; - } -} - -// File openzeppelin-solidity/contracts/token/ERC20/IERC20.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. Does not include - * the optional functions; to access them see `ERC20Detailed`. - */ -interface IERC20 { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a `Transfer` event. - */ - function transfer(address recipient, 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. - * - * > 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.9; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - constructor(address _tokenAddress) public { - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - tokenAddress = _tokenAddress; - } - - /** - * Gets the current balance of the account provided. - */ - function getBalance(address _account) public view returns (uint) { - if (tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(tokenAddress).balanceOf(_account); - } - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal { - if (_price > 0) { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(address(this)); - token.transferFrom(msg.sender, address(this), _price); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require( - token.balanceOf(address(this)) > balanceBefore, - "TRANSFER_FAILED" - ); - } - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer(address _to, uint _amount) internal { - if (_amount > 0) { - if (tokenAddress == address(0)) { - address(uint160(_to)).transfer(_amount); - } else { - IERC20 token = IERC20(tokenAddress); - uint balanceBefore = token.balanceOf(_to); - token.transfer(_to, _amount); - - // There are known bugs in popular ERC20 implements which means we cannot - // trust the return value of `transferFrom`. This require statement ensures - // that a transfer occurred. - require(token.balanceOf(_to) > balanceBefore, "TRANSFER_FAILED"); - } - } - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is IERC721, Ownable, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - constructor() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - - emit Destroy(address(this).balance, msg.sender); - - // this will send any ETH or ERC20 held by the lock to the owner - _transfer(msg.sender, getBalance(address(this))); - selfdestruct(msg.sender); - - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.9; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event NewTokenURI(string tokenURI); - - event NewGlobalTokenSymbol(string tokenSymbol); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function getGlobalBaseTokenURI() external view returns (string memory); - - /** Function to set the globalTokenURI field. - * Should throw if called by other than owner - */ - function setGlobalBaseTokenURI(string calldata _URI) external; - - // Function to read the globalTokenSymbol field. - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function to set the globalTokenSymbol field. - * Should throw if called by other than owner. - */ - function setGlobalTokenSymbol(string calldata _symbol) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is Ownable, MixinFunds, MixinDisableAndDestroy { - event PriceChanged(uint oldKeyPrice, uint keyPrice); - - event Withdrawal( - address indexed sender, - address indexed beneficiary, - uint amount - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint public numberOfKeysSold; - - // The account which will receive funds on withdrawal - address public beneficiary; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > numberOfKeysSold, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyOwnerOrBeneficiary() { - require( - msg.sender == owner() || msg.sender == beneficiary, - "ONLY_LOCK_OWNER_OR_BENEFICIARY" - ); - _; - } - - constructor( - address _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` use case. - */ - function withdraw(uint _amount) external onlyOwnerOrBeneficiary { - uint balance = getBalance(address(this)); - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(beneficiary, amount); - } - - /** - * A function which lets the owner of the lock to change the price for future purchases. - */ - function updateKeyPrice(uint _keyPrice) external onlyOwner onlyIfAlive { - uint oldKeyPrice = keyPrice; - keyPrice = _keyPrice; - emit PriceChanged(oldKeyPrice, keyPrice); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary( - address _beneficiary - ) external onlyOwnerOrBeneficiary { - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - /** - * Public function which returns the total number of unique keys sold (both - * expired and valid) - */ - function totalSupply() public view returns (uint) { - return numberOfKeysSold; - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) private keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with numberOfKeysSold into an array instead. - mapping(uint => address) private ownerByTokenId; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _owner) { - require(keyByOwner[_owner].expirationTimestamp > 0, "HAS_NEVER_OWNED_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(ownerByTokenId[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) external view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_owner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) external view hasValidKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return ownerByTokenId[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - /** - * @notice ERC721: Find the owner of an NFT - * @return The address of the owner of the NFT, if applicable - */ - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return ownerByTokenId[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from numberOfKeysSold) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner, else an owner of an expired key buying an extension. - // We increment the tokenId counter - numberOfKeysSold++; - // we assign the incremented `numberOfKeysSold` as the tokenId for the new key - _key.tokenId = numberOfKeysSold; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (ownerByTokenId[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - ownerByTokenId[_tokenId] = _owner; - } - } - - /** - * Returns the Key struct for the given owner. - */ - function _getKeyFor(address _owner) internal view returns (Key storage) { - return keyByOwner[_owner]; - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is IERC721, MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transfered - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(ownerOf(_tokenId), msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) external payable onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(ownerOf(_tokenId), _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) external onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * external version - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) external view returns (address) { - return _getApproved(_tokenId); - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * Will return the approved recipient for a key transfer or ownership. - * Note: this does not check that a corresponding key - * actually exists. - */ - function _getApproved(uint _tokenId) internal view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is IERC721, Ownable, MixinKeys { - /** - * Allows the Lock owner to give a user a key with no charge. - */ - function grantKey( - address _recipient, - uint _expirationTimestamp - ) external onlyOwner { - _grantKey(_recipient, _expirationTimestamp); - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * All keys granted have the same expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint _expirationTimestamp - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamp); - } - } - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - _grantKey(_recipients[i], _expirationTimestamps[i]); - } - } - - /** - * Give a key to the given user - */ - function _grantKey(address _recipient, uint _expirationTimestamp) private { - require(_recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = _getKeyFor(_recipient); - require( - _expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - toKey.expirationTimestamp = _expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.9; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -contract UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) public pure returns (string memory _concatenatedString) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - string memory abcd = new string( - _ba.length + _bb.length + _bc.length + _bd.length - ); - bytes memory babcd = bytes(abcd); - uint k = 0; - uint i = 0; - for (i = 0; i < _ba.length; i++) { - babcd[k++] = _ba[i]; - } - for (i = 0; i < _bb.length; i++) { - babcd[k++] = _bb[i]; - } - for (i = 0; i < _bc.length; i++) { - babcd[k++] = _bc[i]; - } - for (i = 0; i < _bd.length; i++) { - babcd[k++] = _bd[i]; - } - return string(babcd); - } - - function uint2Str(uint _i) public pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) public pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721, - ERC165, - Ownable, - MixinLockCore, - UnlockUtils, - MixinKeys -{ - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string private lockName; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - constructor(string memory _lockName) internal { - lockName = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - lockName = _lockName; - } - - /** - * @dev Gets the token name - * @return string representing the token name - */ - function name() external view returns (string memory) { - return lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol(string calldata _lockSymbol) external onlyOwner { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.getGlobalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external onlyOwner { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.getGlobalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return - UnlockUtils.strConcat( - URI, - UnlockUtils.address2Str(address(this)), - "/", - UnlockUtils.uint2Str(_tokenId) - ); - } -} - -// File contracts/mixins/MixinNoFallback.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the fallback function implementation, which simply reverts. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinNoFallback { - /** - * @dev the fallback function should not be used. This explicitly reverts - * to ensure it's never used. - */ - function() external { - revert("NO_FALLBACK"); - } -} - -// File openzeppelin-solidity/contracts/math/SafeMath.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - /** - * @dev Purchase function, public version, with no referrer. - * @param _recipient address of the recipient of the purchased key - */ - function purchaseFor(address _recipient) external payable onlyIfAlive { - return _purchaseFor(_recipient, address(0)); - } - - /** - * @dev Purchase function, public version, with referrer. - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - */ - function purchaseForFrom( - address _recipient, - address _referrer - ) external payable onlyIfAlive hasValidKey(_referrer) { - return _purchaseFor(_recipient, _referrer); - } - - /** - * @dev Purchase function: this lets a user purchase a key from the lock for another user - * @param _recipient address of the recipient of the purchased key - * This will fail if - * - the keyReleaseMechanism is private - * - the keyReleaseMechanism is Approved and the recipient has not been previously approved - * - the amount value is smaller than the price - * - the recipient already owns a key - * TODO: next version of solidity will allow for message to be added to require. - */ - function _purchaseFor( - address _recipient, - address _referrer - ) private notSoldOut { - // solhint-disable-line function-max-lines - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - uint netPrice = inMemoryKeyPrice; - if (discount > inMemoryKeyPrice) { - netPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - netPrice = inMemoryKeyPrice - discount; - } - - // Assign the key - Key storage toKey = _getKeyFor(_recipient); - - if (toKey.tokenId == 0) { - // Assign a new tokenId (if a new owner or previously transfered) - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - } - - if (toKey.expirationTimestamp >= block.timestamp) { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = toKey.expirationTimestamp.add( - expirationDuration - ); - } else { - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(netPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - numberOfKeysSold - ); - - // We explicitly allow for greater amounts of ETH to allow 'donations' - // Security: last line to minimize risk of re-entrancy - _chargeAtLeast(netPrice); - } -} - -// File openzeppelin-solidity/contracts/cryptography/ECDSA.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * (.note) This call _does not revert_ if the signature is invalid, or - * if the signer is otherwise unable to be retrieved. In those scenarios, - * the zero address is returned. - * - * (.warning) `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise) - * be too long), and then calling `toEthSignedMessageHash` on it. - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) - * JSON-RPC method. - * - * See `recover`. - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.9; - -contract MixinRefunds is Ownable, MixinFunds, MixinLockCore, MixinKeys { - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyNumerator / refundPenaltyDenominator`. - uint public refundPenaltyNumerator = 1; - uint public refundPenaltyDenominator = 10; - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyOwnerToNonce; - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint oldRefundPenaltyNumerator, - uint oldRefundPenaltyDenominator, - uint refundPenaltyNumerator, - uint refundPenaltyDenominator - ); - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - _cancelAndRefund(msg.sender); - } - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _signature getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - bytes calldata _signature - ) external { - require( - ECDSA.recover( - ECDSA.toEthSignedMessageHash( - getCancelAndRefundApprovalHash(_keyOwner, msg.sender) - ), - _signature - ) == _keyOwner, - "INVALID_SIGNATURE" - ); - - keyOwnerToNonce[_keyOwner]++; - _cancelAndRefund(_keyOwner); - } - - /** - * @dev Increments the current nonce for the msg.sender. - * This can be used to invalidate a previously signed message. - */ - function incrementNonce() external { - keyOwnerToNonce[msg.sender]++; - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _refundPenaltyNumerator, - uint _refundPenaltyDenominator - ) external onlyOwner { - require(_refundPenaltyDenominator != 0, "INVALID_RATE"); - - emit RefundPenaltyChanged( - refundPenaltyNumerator, - refundPenaltyDenominator, - _refundPenaltyNumerator, - _refundPenaltyDenominator - ); - refundPenaltyNumerator = _refundPenaltyNumerator; - refundPenaltyDenominator = _refundPenaltyDenominator; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @dev returns the hash to sign in order to allow another user to cancel on your behalf. - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // Approval enables only one cancel call - keyOwnerToNonce[_keyOwner], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner) internal { - Key storage key = _getKeyFor(_keyOwner); - - uint refund = _getCancelAndRefundValue(_keyOwner); - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(msg.sender, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - uint penalty = keyPrice.mul(refundPenaltyNumerator) / - refundPenaltyDenominator; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } -} - -// File openzeppelin-solidity/contracts/utils/Address.sol@v2.3.0 - -pragma solidity ^0.5.0; - -/** - * @dev Collection of functions related to the address type, - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing a contract. - * - * > It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.9; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged( - uint oldTransferFeeNumerator, - uint oldTransferFeeDenominator, - uint transferFeeNumerator, - uint transferFeeDenominator - ); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeNumerator / transferFeeDenominator`. - uint public transferFeeNumerator = 0; - uint public transferFeeDenominator = 100; - - /** - * This is payable because at some point we want to allow the LOCK to capture a fee on 2ndary - * market transactions... - */ - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) - public - payable - onlyIfAlive - hasValidKey(_from) - onlyKeyOwnerOrApproved(_tokenId) - { - require(_recipient != address(0), "INVALID_ADDRESS"); - _chargeAtLeast(getTransferFee(_from)); - - Key storage fromKey = _getKeyFor(_from); - Key storage toKey = _getKeyFor(_recipient); - - uint previousExpiration = toKey.expirationTimestamp; - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, toKey.tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId - ) external payable { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - payable - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(ownerOf(_tokenId)) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeNumerator, - uint _transferFeeDenominator - ) external onlyOwner { - require(_transferFeeDenominator != 0, "INVALID_RATE"); - emit TransferFeeChanged( - transferFeeNumerator, - transferFeeDenominator, - _transferFeeNumerator, - _transferFeeDenominator - ); - transferFeeNumerator = _transferFeeNumerator; - transferFeeDenominator = _transferFeeDenominator; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _owner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _owner - ) public view hasValidKey(_owner) returns (uint) { - Key storage key = _getKeyFor(_owner); - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - uint fee; - if (timeRemaining >= expirationDuration) { - // Max the potential impact of this fee for keys with long durations remaining - fee = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - fee = keyPrice.mul(timeRemaining) / expirationDuration; - } - return fee.mul(transferFeeNumerator) / transferFeeDenominator; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.9; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * Eventually: implement ERC721. - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IERC721, - MixinNoFallback, - ERC165, - Ownable, - ERC721Holder, - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinGrantKeys, - MixinPurchase, - MixinApproval, - MixinTransfer, - MixinRefunds -{ - constructor( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) - public - MixinFunds(_tokenAddress) - MixinLockCore(_owner, _expirationDuration, _keyPrice, _maxNumberOfKeys) - MixinLockMetadata(_lockName) - { - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - // We must manually initialize Ownable.sol - Ownable.initialize(_owner); - } - - // The version number of the current implementation on this network - function publicLockVersion() external pure returns (uint16) { - return 4; - } -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV5.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV5.sol deleted file mode 100644 index 2ddc5ce892b..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV5.sol +++ /dev/null @@ -1,2 +0,0 @@ -// Error HH603: Hardhat flatten doesn't support cyclic dependencies. -// For more info go to https://hardhat.org/HH603 or run Hardhat with --show-stack-traces \ No newline at end of file diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV6.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV6.sol deleted file mode 100644 index 669190caf63..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV6.sol +++ /dev/null @@ -1,3288 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.6.0 - -pragma solidity >=0.4.24 <0.6.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - uint256 cs; - assembly { - cs := extcodesize(address) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/IERC165.sol@v2.4.0 - -pragma solidity ^0.5.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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity ^0.5.0; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock is IERC721Enumerable { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Events - event Destroy(uint balance, address indexed owner); - - event Disable(); - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - event ExpireKey(uint indexed tokenId); - - event NewLockSymbol(string symbol); - - event TransferFeeChanged(uint transferFeeBasisPoints); - - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyOwner, uint nextAvailableNonce); - - ///=================================================================== - - /// Functions - - function initialize( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than the owner. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @notice Used to clean up old lock contracts from the blockchain. - * TODO: add a check to ensure all keys are INVALID! - * @dev Throws if called by other than owner. - * @dev Throws if lock has not yet been disabled. - */ - function destroyLock() external; - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than the owner or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `fullRefund` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets the owner of the lock to change the price for future purchases. - * @dev Throws if called by other than owner - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than owner of beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * A function which lets the owner of the lock expire a users' key. - * @dev Throws if called by other than lock owner - * @dev Throws if key owner does not have a valid key - * @param _owner The address of the key owner - */ - function expireKeyFor(address _owner) external; - - /** - * Checks if the user has a non-expired key. - * @param _owner The address of the key owner - */ - function getHasValidKey(address _owner) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - * @dev Throws if key owner does not have a valid key - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _owner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - * @dev Throws if owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _owner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than the lock owner - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - * @dev Throws if called by other than the lock owner - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than the lock-owner - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * Allow the Lock owner to change the transfer fee. - * @dev Throws if called by other than lock-owner - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _owner does not have a valid key - * @param _owner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _owner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by the lock owner to destroy the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than owner - * @dev Throws if _keyOwner does not have a valid key - */ - function fullRefund(address _keyOwner, uint amount) external; - - /** - * @notice Destroys the msg.sender's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external; - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - uint8 _v, - bytes32 _r, - bytes32 _s - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow the owner to change the refund penalty. - * @dev Throws if called by other than owner - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _owner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund); - - function keyOwnerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyOwner The key owner's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) external view returns (bytes32 approvalHash); - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function erc1820() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyCancelInterfaceId() external view returns (bytes32); - - function keySoldInterfaceId() external view returns (bytes32); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function BASIS_POINTS_DEN() external view returns (uint256); - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - function CANCEL_TYPEHASH() external view returns (bytes32); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From Openzeppelin's Ownable.sol - function owner() external view returns (address); - - function isOwner() external view returns (bool); - - function renounceOwnership() external; - - function transferOwnership(address newOwner) external; - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - ///=================================================================== -} - -// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.4.0 - -pragma solidity ^0.5.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 GSN 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. - */ -contract Context is Initializable { - // Empty internal constructor, to prevent people from mistakenly deploying - // an instance of this contract, which should be used via inheritance. - constructor() internal {} - - // solhint-disable-previous-line no-empty-blocks - - function _msgSender() internal view returns (address payable) { - return msg.sender; - } - - function _msgData() internal view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @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. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Initializable, Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return _msgSender() == _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 onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = 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 onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/ERC165.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts may inherit from this and call {_registerInterface} to declare - * their support of an interface. - */ -contract ERC165 is Initializable, IERC165 { - /* - * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 - */ - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - function initialize() public initializer { - // Derived contracts need only register support for their own interfaces, - // we register support for ERC165 itself here - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev See {IERC165-supportsInterface}. - * - * Time complexity O(1), guaranteed to always use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) public view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See {IERC165-supportsInterface}. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } - - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. Does not include - * the optional functions; to access them see {ERC20Detailed}. - */ -interface IERC20 { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.4.0 - -pragma solidity ^0.5.5; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing 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. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != 0x0 && codehash != accountHash); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - * - * _Available since v2.4.0._ - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/SafeERC20.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @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 ERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using SafeMath for uint256; - 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) - ); - } - - 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' - // solhint-disable-next-line max-line-length - 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).add(value); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender).sub( - value, - "SafeERC20: decreased allowance below zero" - ); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - /** - * @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. - - // A Solidity high level call has three parts: - // 1. The target address is checked to verify it contains contract code - // 2. The call itself is made, and success asserted - // 3. The return value is decoded, which in turn checks the size of the returned data. - // solhint-disable-next-line max-line-length - require(address(token).isContract(), "SafeERC20: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = address(token).call(data); - require(success, "SafeERC20: low-level call failed"); - - if (returndata.length > 0) { - // Return data is optional - // solhint-disable-next-line max-line-length - require( - abi.decode(returndata, (bool)), - "SafeERC20: ERC20 operation did not succeed" - ); - } - } -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.14; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds is Ownable { - using Address for address payable; - using SafeERC20 for IERC20; - - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - function _initializeMixinFunds(address _tokenAddress) internal { - tokenAddress = _tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - } - - /** - * Gets the current balance of the account provided. - */ - function getBalance( - address _tokenAddress, - address _account - ) public view returns (uint) { - if (_tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(_tokenAddress).balanceOf(_account); - } - } - - /** - * Ensures that the msg.sender has paid at least the price stated. - * - * With ETH, this means the function originally called was `payable` and the - * transaction included at least the amount requested. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _chargeAtLeast(uint _price) internal returns (uint) { - if (_price > 0) { - if (tokenAddress == address(0)) { - require(msg.value >= _price, "NOT_ENOUGH_FUNDS"); - return msg.value; - } else { - IERC20 token = IERC20(tokenAddress); - token.safeTransferFrom(msg.sender, address(this), _price); - return _price; - } - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer( - address _tokenAddress, - address _to, - uint _amount - ) internal { - if (_amount > 0) { - if (_tokenAddress == address(0)) { - // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/ - address(uint160(_to)).sendValue(_amount); - } else { - IERC20 token = IERC20(_tokenAddress); - token.safeTransfer(_to, _amount); - } - } - } -} - -// File contracts/mixins/MixinDisableAndDestroy.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisableAndDestroy is Ownable, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Destroy(uint balance, address indexed owner); - - event Disable(); - - function _initializeMixinDisableAndDestroy() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyOwner onlyIfAlive { - emit Disable(); - isAlive = false; - } - - /** - * @dev Used to clean up old lock contracts from the blockchain - * TODO: add a check to ensure all keys are INVALID! - */ - function destroyLock() external onlyOwner { - require(isAlive == false, "DISABLE_FIRST"); - - emit Destroy(address(this).balance, msg.sender); - - // this will send any ETH or ERC20 held by the lock to the owner - _transfer( - tokenAddress, - msg.sender, - getBalance(tokenAddress, address(this)) - ); - selfdestruct(msg.sender); - - // Note we don't clean up the `locks` data in Unlock.sol as it should not be necessary - // and leaves some data behind ('Unlock.LockBalances') which may be helpful. - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/access/Roles.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title Roles - * @dev Library for managing addresses assigned to a Role. - */ -library Roles { - struct Role { - mapping(address => bool) bearer; - } - - /** - * @dev Give an account access to this role. - */ - function add(Role storage role, address account) internal { - require(!has(role, account), "Roles: account already has role"); - role.bearer[account] = true; - } - - /** - * @dev Remove an account's access to this role. - */ - function remove(Role storage role, address account) internal { - require(has(role, account), "Roles: account does not have role"); - role.bearer[account] = false; - } - - /** - * @dev Check if an account has this role. - * @return bool - */ - function has( - Role storage role, - address account - ) internal view returns (bool) { - require(account != address(0), "Roles: account is the zero address"); - return role.bearer[account]; - } -} - -// File contracts/mixins/MixinLockManagerRole.sol - -pragma solidity ^0.5.0; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinLockManagerRole is Ownable { - using Roles for Roles.Role; - - event LockManagerAdded(address indexed account); - event LockManagerRemoved(address indexed account); - - Roles.Role private lockManagers; - - function _initializeMixinLockManagerRole(address sender) internal { - if (!isLockManager(sender)) { - lockManagers.add(sender); - } - } - - modifier onlyLockManager() { - require( - isLockManager(msg.sender), - "MixinLockManager: caller does not have the LockManager role" - ); - _; - } - - function isLockManager(address account) public view returns (bool) { - return lockManagers.has(account); - } - - function addLockManager(address account) public onlyOwner { - lockManagers.add(account); - emit LockManagerAdded(account); - } - - function renounceLockManager() public { - lockManagers.remove(msg.sender); - emit LockManagerRemoved(msg.sender); - } -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.14; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address publicLockAddress, - string globalTokenSymbol, - string globalTokenURI - ); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _owner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock( - address _publicLockAddress, - string calldata _symbol, - string calldata _URI - ) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is - IERC721Enumerable, - Ownable, - MixinFunds, - MixinDisableAndDestroy, - MixinLockManagerRole -{ - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint internal _totalSupply; - - // The account which will receive funds on withdrawal - address public beneficiary; - - // The denominator component for values specified in basis points. - uint public constant BASIS_POINTS_DEN = 10000; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > _totalSupply, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyOwnerOrBeneficiary() { - require( - msg.sender == owner() || msg.sender == beneficiary, - "ONLY_LOCK_OWNER_OR_BENEFICIARY" - ); - _; - } - - function _initializeMixinLockCore( - address _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - // The version number of the current implementation on this network - function publicLockVersion() public pure returns (uint) { - return 6; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `fullRefund` - * use cases. - */ - function withdraw( - address _tokenAddress, - uint _amount - ) external onlyOwnerOrBeneficiary { - uint balance = getBalance(_tokenAddress, address(this)); - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, _tokenAddress, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(_tokenAddress, beneficiary, amount); - } - - /** - * A function which lets the owner of the lock change the pricing for future purchases. - * This consists of 2 parts: The token address and the price in the given token. - * In order to set the token to ETH, use 0 for the token Address. - */ - function updateKeyPricing( - uint _keyPrice, - address _tokenAddress - ) external onlyLockManager onlyIfAlive { - uint oldKeyPrice = keyPrice; - address oldTokenAddress = tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - keyPrice = _keyPrice; - tokenAddress = _tokenAddress; - emit PricingChanged(oldKeyPrice, keyPrice, oldTokenAddress, tokenAddress); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary( - address _beneficiary - ) external onlyOwnerOrBeneficiary { - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - function totalSupply() public view returns (uint256) { - return _totalSupply; - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for managing `Key` data. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is Ownable, MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Called when the Lock owner expires a user's Key - event ExpireKey(uint indexed tokenId); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with totalSupply into an array instead. - mapping(uint => address) internal _ownerOf; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _owner) { - require(keyByOwner[_owner].expirationTimestamp > 0, "HAS_NEVER_OWNED_KEY"); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _owner) { - require(getHasValidKey(_owner), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(_ownerOf[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * A function which lets the owner of the lock expire a users' key. - */ - function expireKeyFor(address _owner) public onlyOwner hasValidKey(_owner) { - Key storage key = keyByOwner[_owner]; - key.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(key.tokenId); - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_owner`, either 0 or 1. - */ - function balanceOf(address _owner) public view returns (uint) { - require(_owner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_owner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _owner) public view returns (bool) { - return keyByOwner[_owner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else revert - */ - function getTokenIdFor( - address _account - ) public view hasValidKey(_account) returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _owner - ) public view returns (bool) { - return _ownerOf[_tokenId] == _owner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _owner address of the user for whom we search the key - */ - function keyExpirationTimestampFor( - address _owner - ) public view ownsOrHasOwnedKey(_owner) returns (uint timestamp) { - return keyByOwner[_owner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - // Returns the owner of a given tokenId - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return _ownerOf[_tokenId]; - } - - /** - * Assigns the key a new tokenId (from totalSupply) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner - // We increment the tokenId counter - _totalSupply++; - // we assign the incremented `_totalSupply` as the tokenId for the new key - _key.tokenId = _totalSupply; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _owner, uint _tokenId) internal { - if (_ownerOf[_tokenId] != _owner) { - // TODO: this may include duplicate entries - owners.push(_owner); - // We register the owner of the tokenID - _ownerOf[_tokenId] = _owner; - } - } -} - -// File contracts/mixins/MixinApproval.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for the Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinApproval is MixinDisableAndDestroy, MixinKeys { - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transferred - // Note: the approver may actually NOT have a key... and there can only - // be a single approved beneficiary - // Note 2: for transfer, both addresses will be different - // Note 3: for sales (new keys on restricted locks), both addresses will be the same - mapping(uint => address) private approved; - - // Keeping track of approved operators for a Key owner. - // Since an owner can have up to 1 Key, this is similiar to above - // but the approval does not reset when a transfer occurs. - mapping(address => mapping(address => bool)) private ownerToOperatorApproved; - - // Ensure that the caller has a key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyOwnerOrApproved(uint _tokenId) { - require( - isKeyOwner(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(_ownerOf[_tokenId], msg.sender), - "ONLY_KEY_OWNER_OR_APPROVED" - ); - _; - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) public onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(_ownerOf[_tokenId], _approved, _tokenId); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - ownerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * Will return the approved recipient for a key, if any. - */ - function getApproved(uint _tokenId) public view returns (address) { - address approvedRecipient = approved[_tokenId]; - require(approvedRecipient != address(0), "NONE_APPROVED"); - return approvedRecipient; - } - - /** - * @dev Tells whether an operator is approved by a given owner - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - return ownerToOperatorApproved[_owner][_operator]; - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinERC721Enumerable.sol - -pragma solidity 0.5.14; - -/** - * @title Implements the ERC-721 Enumerable extension. - */ -contract MixinERC721Enumerable is - IERC721Enumerable, - ERC165, - MixinLockCore, // Implements totalSupply - MixinKeys -{ - function _initializeMixinERC721Enumerable() internal { - /** - * register the supported interface to conform to ERC721Enumerable via ERC165 - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - _registerInterface(0x780e9d63); - } - - /// @notice Enumerate valid NFTs - /// @dev Throws if `_index` >= `totalSupply()`. - /// @param _index A counter less than `totalSupply()` - /// @return The token identifier for the `_index`th NFT, - /// (sort order not specified) - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < _totalSupply, "OUT_OF_RANGE"); - return _index; - } - - /// @notice Enumerate NFTs assigned to an owner - /// @dev Throws if `_index` >= `balanceOf(_owner)` or if - /// `_owner` is the zero address, representing invalid NFTs. - /// @param _owner An address where we are interested in NFTs owned by them - /// @param _index A counter less than `balanceOf(_owner)` - /// @return The token identifier for the `_index`th NFT assigned to `_owner`, - /// (sort order not specified) - function tokenOfOwnerByIndex( - address _owner, - uint256 _index - ) public view returns (uint256) { - require(_index == 0, "ONLY_ONE_KEY_PER_OWNER"); - return getTokenIdFor(_owner); - } -} - -// File contracts/interfaces/IUnlockEventHooks.sol - -pragma solidity 0.5.14; - -interface IUnlockEventHooks { - /** - * @notice If the lock owner has registered an implementer for this interface with ERC-1820 - * then this hook is called with every key sold. - * @dev Use the interface name `keccak256("IUnlockEventHooks_keySold")` - * which is 4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0 - * @param from the msg.sender making the purchase - * @param to the account which will be granted a key - * @param referrer the account which referred this key sale - * @param pricePaid the amount paid for the key, in the lock's currency (ETH or a ERC-20 token) - * @param data arbitrary data populated by the front-end which initiated the sale - */ - function keySold( - address from, - address to, - address referrer, - uint256 pricePaid, - bytes calldata data - ) external; - - /** - * @notice If the lock owner has registered an implementer for this interface with ERC-1820 - * then this hook is called with every key cancel. - * @dev Use the interface name `keccak256("IUnlockEventHooks_keyCancel")` - * which is 0xd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68 - * @param operator the msg.sender issuing the cancel - * @param to the account which had the key canceled - * @param refund the amount sent to the `to` account (ETH or a ERC-20 token) - */ - function keyCancel(address operator, address to, uint256 refund) external; -} - -// File @openzeppelin/contracts/introspection/IERC1820Registry.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the global ERC1820 Registry, as defined in the - * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register - * implementers for interfaces in this registry, as well as query support. - * - * Implementers may be shared by multiple accounts, and can also implement more - * than a single interface for each account. Contracts can implement interfaces - * for themselves, but externally-owned accounts (EOA) must delegate this to a - * contract. - * - * {IERC165} interfaces can also be queried via the registry. - * - * For an in-depth explanation and source code analysis, see the EIP text. - */ -interface IERC1820Registry { - /** - * @dev Sets `newManager` as the manager for `account`. A manager of an - * account is able to set interface implementers for it. - * - * By default, each account is its own manager. Passing a value of `0x0` in - * `newManager` will reset the manager to this initial state. - * - * Emits a {ManagerChanged} event. - * - * Requirements: - * - * - the caller must be the current manager for `account`. - */ - function setManager(address account, address newManager) external; - - /** - * @dev Returns the manager for `account`. - * - * See {setManager}. - */ - function getManager(address account) external view returns (address); - - /** - * @dev Sets the `implementer` contract as `account`'s implementer for - * `interfaceHash`. - * - * `account` being the zero address is an alias for the caller's address. - * The zero address can also be used in `implementer` to remove an old one. - * - * See {interfaceHash} to learn how these are created. - * - * Emits an {InterfaceImplementerSet} event. - * - * Requirements: - * - * - the caller must be the current manager for `account`. - * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not - * end in 28 zeroes). - * - `implementer` must implement {IERC1820Implementer} and return true when - * queried for support, unless `implementer` is the caller. See - * {IERC1820Implementer-canImplementInterfaceForAddress}. - */ - function setInterfaceImplementer( - address account, - bytes32 interfaceHash, - address implementer - ) external; - - /** - * @dev Returns the implementer of `interfaceHash` for `account`. If no such - * implementer is registered, returns the zero address. - * - * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28 - * zeroes), `account` will be queried for support of it. - * - * `account` being the zero address is an alias for the caller's address. - */ - function getInterfaceImplementer( - address account, - bytes32 interfaceHash - ) external view returns (address); - - /** - * @dev Returns the interface hash for an `interfaceName`, as defined in the - * corresponding - * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP]. - */ - function interfaceHash( - string calldata interfaceName - ) external pure returns (bytes32); - - /** - * @notice Updates the cache with whether the contract implements an ERC165 interface or not. - * @param account Address of the contract for which to update the cache. - * @param interfaceId ERC165 interface for which to update the cache. - */ - function updateERC165Cache(address account, bytes4 interfaceId) external; - - /** - * @notice Checks whether a contract implements an ERC165 interface or not. - * If the result is not cached a direct lookup on the contract address is performed. - * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling - * {updateERC165Cache} with the contract address. - * @param account Address of the contract to check. - * @param interfaceId ERC165 interface to check. - * @return True if `account` implements `interfaceId`, false otherwise. - */ - function implementsERC165Interface( - address account, - bytes4 interfaceId - ) external view returns (bool); - - /** - * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache. - * @param account Address of the contract to check. - * @param interfaceId ERC165 interface to check. - * @return True if `account` implements `interfaceId`, false otherwise. - */ - function implementsERC165InterfaceNoCache( - address account, - bytes4 interfaceId - ) external view returns (bool); - - event InterfaceImplementerSet( - address indexed account, - bytes32 indexed interfaceHash, - address indexed implementer - ); - - event ManagerChanged(address indexed account, address indexed newManager); -} - -// File contracts/mixins/MixinEventHooks.sol - -pragma solidity 0.5.14; - -/** - * @title Implements callback hooks for Locks. - * @author Nick Mancuso (unlock-protocol.com) - */ -contract MixinEventHooks is MixinLockCore { - IERC1820Registry public constant erc1820 = - IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); - - // `keccak256("IUnlockEventHooks_keySold")` - bytes32 public constant keySoldInterfaceId = - 0x4d99da10ff5120f726d35edd8dbd417bbe55d90453b8432acd284e650ee2c6f0; - - // `keccak256("IUnlockEventHooks_keyCancel")` - bytes32 public constant keyCancelInterfaceId = - 0xd6342b4bfdf66164985c9f5fe235f643a035ee12f507d7bd0f8c89e07e790f68; - - /** - * @dev called anytime a key is sold in order to inform the hook if there is one registered. - */ - function _onKeySold( - address _to, - address _referrer, - uint256 _pricePaid, - bytes memory _data - ) internal { - address implementer = erc1820.getInterfaceImplementer( - beneficiary, - keySoldInterfaceId - ); - if (implementer != address(0)) { - IUnlockEventHooks(implementer).keySold( - msg.sender, - _to, - _referrer, - _pricePaid, - _data - ); - } - } - - /** - * @dev called anytime a key is canceled in order to inform the hook if there is one registered. - */ - function _onKeyCancel(address _to, uint256 _refund) internal { - address implementer = erc1820.getInterfaceImplementer( - beneficiary, - keyCancelInterfaceId - ); - if (implementer != address(0)) { - IUnlockEventHooks(implementer).keyCancel(msg.sender, _to, _refund); - } - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is Ownable, MixinKeys { - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps - ) external onlyOwner { - for (uint i = 0; i < _recipients.length; i++) { - address recipient = _recipients[i]; - uint expirationTimestamp = _expirationTimestamps[i]; - - require(recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = keyByOwner[recipient]; - require( - expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - _assignNewTokenId(toKey); - _recordOwner(recipient, toKey.tokenId); - toKey.expirationTimestamp = expirationTimestamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - recipient, - toKey.tokenId - ); - } - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.14; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -library UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) internal pure returns (string memory _concatenatedString) { - bytes memory _ba = bytes(_a); - bytes memory _bb = bytes(_b); - bytes memory _bc = bytes(_c); - bytes memory _bd = bytes(_d); - string memory abcd = new string( - _ba.length + _bb.length + _bc.length + _bd.length - ); - bytes memory babcd = bytes(abcd); - uint k = 0; - uint i = 0; - for (i = 0; i < _ba.length; i++) { - babcd[k++] = _ba[i]; - } - for (i = 0; i < _bb.length; i++) { - babcd[k++] = _bb[i]; - } - for (i = 0; i < _bc.length; i++) { - babcd[k++] = _bc[i]; - } - for (i = 0; i < _bd.length; i++) { - babcd[k++] = _bd[i]; - } - return string(babcd); - } - - function uint2Str( - uint _i - ) internal pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) internal pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721Enumerable, - ERC165, - Ownable, - MixinLockCore, - MixinKeys -{ - using UnlockUtils for uint; - using UnlockUtils for address; - using UnlockUtils for string; - - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string public name; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - function _initializeMixinLockMetadata(string memory _lockName) internal { - ERC165.initialize(); - name = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyOwner { - name = _lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol(string calldata _lockSymbol) external onlyOwner { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.globalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external onlyOwner { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.globalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return URI.strConcat(address(this).address2Str(), "/", _tokenId.uint2Str()); - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is - MixinFunds, - MixinDisableAndDestroy, - MixinLockCore, - MixinKeys, - MixinEventHooks -{ - using SafeMath for uint; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable onlyIfAlive notSoldOut { - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Assign the key - Key storage toKey = keyByOwner[_recipient]; - - if (toKey.tokenId == 0) { - // Assign a new tokenId (if a new owner or previously transferred) - _assignNewTokenId(toKey); - _recordOwner(_recipient, toKey.tokenId); - } - - if (toKey.expirationTimestamp >= block.timestamp) { - // This is an existing owner trying to extend their key - toKey.expirationTimestamp = toKey.expirationTimestamp.add( - expirationDuration - ); - } else { - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - toKey.expirationTimestamp = block.timestamp + expirationDuration; - } - - // Let's get the actual price for the key from the Unlock smart contract - uint discount; - uint tokens; - uint inMemoryKeyPrice = keyPrice; - (discount, tokens) = unlockProtocol.computeAvailableDiscountFor( - _recipient, - inMemoryKeyPrice - ); - - if (discount > inMemoryKeyPrice) { - inMemoryKeyPrice = 0; - } else { - // SafeSub not required as the if statement already confirmed `inMemoryKeyPrice - discount` cannot underflow - inMemoryKeyPrice -= discount; - } - - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - unlockProtocol.recordKeyPurchase(inMemoryKeyPrice, _referrer); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - toKey.tokenId - ); - - // We explicitly allow for greater amounts of ETH or tokens to allow 'donations' - if (tokenAddress != address(0)) { - require(_value >= inMemoryKeyPrice, "INSUFFICIENT_VALUE"); - inMemoryKeyPrice = _value; - } - // Security: after state changes to minimize risk of re-entrancy - uint pricePaid = _chargeAtLeast(inMemoryKeyPrice); - - // Security: last line to minimize risk of re-entrancy - _onKeySold(_recipient, _referrer, pricePaid, _data); - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/cryptography/ECDSA.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * NOTE: This call _does not revert_ if the signature is invalid, or - * if the signer is otherwise unable to be retrieved. In those scenarios, - * the zero address is returned. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] - * JSON-RPC method. - * - * See {recover}. - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinSignatures.sol - -pragma solidity 0.5.14; - -contract MixinSignatures { - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyOwner, uint nextAvailableNonce); - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyOwnerToNonce; - - /// @notice Validates an off-chain approval signature. - /// @dev If valid the nonce is consumed, else revert. - modifier consumeOffchainApproval( - bytes32 _hash, - address _keyOwner, - uint8 _v, - bytes32 _r, - bytes32 _s - ) { - require( - ecrecover(ECDSA.toEthSignedMessageHash(_hash), _v, _r, _s) == _keyOwner, - "INVALID_SIGNATURE" - ); - keyOwnerToNonce[_keyOwner]++; - emit NonceChanged(_keyOwner, keyOwnerToNonce[_keyOwner]); - _; - } - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external { - require( - _nextAvailableNonce > keyOwnerToNonce[msg.sender], - "NONCE_ALREADY_USED" - ); - keyOwnerToNonce[msg.sender] = _nextAvailableNonce; - emit NonceChanged(msg.sender, _nextAvailableNonce); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.14; - -contract MixinRefunds is - Ownable, - MixinSignatures, - MixinFunds, - MixinLockCore, - MixinKeys, - MixinEventHooks -{ - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyBasisPoints / BASIS_POINTS_DEN`. - uint public refundPenaltyBasisPoints; - - uint public freeTrialLength; - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - bytes32 public constant CANCEL_TYPEHASH = - keccak256("cancelAndRefundFor(address _keyOwner)"); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - function _initializeMixinRefunds() internal { - // default to 10% - refundPenaltyBasisPoints = 1000; - } - - /** - * @dev Invoked by the lock owner to destroy the user's ket and perform a refund and cancellation - * of the key - */ - function fullRefund( - address _keyOwner, - uint amount - ) external onlyOwner hasValidKey(_keyOwner) { - _cancelAndRefund(_keyOwner, amount); - } - - /** - * @dev Destroys the user's key and sends a refund based on the amount of time remaining. - */ - function cancelAndRefund() external { - uint refund = _getCancelAndRefundValue(msg.sender); - - _cancelAndRefund(msg.sender, refund); - } - - /** - * @dev Cancels a key owned by a different user and sends the funds to the msg.sender. - * @param _keyOwner this user's key will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - */ - function cancelAndRefundFor( - address _keyOwner, - uint8 _v, - bytes32 _r, - bytes32 _s - ) - external - consumeOffchainApproval( - getCancelAndRefundApprovalHash(_keyOwner, msg.sender), - _keyOwner, - _v, - _r, - _s - ) - { - uint refund = _getCancelAndRefundValue(_keyOwner); - _cancelAndRefund(_keyOwner, refund); - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external onlyOwner { - emit RefundPenaltyChanged(_freeTrialLength, _refundPenaltyBasisPoints); - - freeTrialLength = _freeTrialLength; - refundPenaltyBasisPoints = _refundPenaltyBasisPoints; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _owner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_owner); - } - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyOwner The key owner's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyOwner, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // The specific function the signer is approving - CANCEL_TYPEHASH, - // Approval enables only one cancel call - keyOwnerToNonce[_keyOwner], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner, uint refund) internal { - Key storage key = keyByOwner[_keyOwner]; - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(tokenAddress, _keyOwner, refund); - } - - _onKeyCancel(_keyOwner, refund); - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _owner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _owner - ) private view hasValidKey(_owner) returns (uint refund) { - Key storage key = keyByOwner[_owner]; - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining + freeTrialLength >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - - // Apply the penalty if this is not a free trial - if ( - freeTrialLength == 0 || - timeRemaining + freeTrialLength < expirationDuration - ) { - uint penalty = keyPrice.mul(refundPenaltyBasisPoints) / BASIS_POINTS_DEN; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Receiver.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a {IERC721-safeTransferFrom}. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.14; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinFunds, MixinLockCore, MixinKeys, MixinApproval { - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged(uint transferFeeBasisPoints); - - event TimestampChanged(uint indexed _tokenId, uint _amount, bool _timeAdded); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeBasisPoints / BASIS_POINTS_DEN`. - uint public transferFeeBasisPoints; - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - */ - function shareKey( - address _to, - uint _tokenId, - uint _timeShared - ) public onlyIfAlive onlyKeyOwnerOrApproved(_tokenId) { - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_to != address(0), "INVALID_ADDRESS"); - address keyOwner = _ownerOf[_tokenId]; - require(getHasValidKey(keyOwner), "KEY_NOT_VALID"); - Key storage fromKey = keyByOwner[keyOwner]; - Key storage toKey = keyByOwner[_to]; - uint iDTo = toKey.tokenId; - uint time; - // get the remaining time for the origin key - uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; - // get the transfer fee based on amount of time wanted share - uint fee = getTransferFee(keyOwner, _timeShared); - uint timePlusFee = _timeShared.add(fee); - - // ensure that we don't try to share too much - if (timePlusFee < timeRemaining) { - // now we can safely set the time - time = _timeShared; - // deduct time from parent key, including transfer fee - _timeMachine(_tokenId, timePlusFee, false); - } else { - // we have to recalculate the fee here - fee = getTransferFee(keyOwner, timeRemaining); - time = timeRemaining - fee; - fromKey.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(_tokenId); - } - - if (toKey.tokenId == 0) { - _assignNewTokenId(toKey); - _recordOwner(_to, iDTo); - emit Transfer( - address(0), // This is a creation or time-sharing - _to, - iDTo - ); - } - // add time to new key - _timeMachine(iDTo, time, true); - // trigger event - emit Transfer(keyOwner, _to, iDTo); - - require( - _checkOnERC721Received(keyOwner, _to, _tokenId, ""), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) public onlyIfAlive hasValidKey(_from) onlyKeyOwnerOrApproved(_tokenId) { - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_recipient != address(0), "INVALID_ADDRESS"); - uint fee = getTransferFee(_from, 0); - - Key storage fromKey = keyByOwner[_from]; - Key storage toKey = keyByOwner[_recipient]; - uint id = fromKey.tokenId; - - uint previousExpiration = toKey.expirationTimestamp; - // subtract the fee from the senders key before the transfer - _timeMachine(id, fee, false); - - if (toKey.tokenId == 0) { - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, toKey.tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the - // sender's key expiration - // an expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = fromKey.tokenId; - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // Clear any previous approvals - _clearApproval(_tokenId); - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom(address _from, address _to, uint _tokenId) public { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) - public - onlyIfAlive - onlyKeyOwnerOrApproved(_tokenId) - hasValidKey(_ownerOf[_tokenId]) - { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee(uint _transferFeeBasisPoints) external onlyOwner { - emit TransferFeeChanged(_transferFeeBasisPoints); - transferFeeBasisPoints = _transferFeeBasisPoints; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _owner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _owner, - uint _time - ) public view hasValidKey(_owner) returns (uint) { - Key storage key = keyByOwner[_owner]; - uint timeToTransfer; - uint fee; - // Math: safeSub is not required since `hasValidKey` confirms timeToTransfer is positive - // this is for standard key transfers - if (_time == 0) { - timeToTransfer = key.expirationTimestamp - block.timestamp; - } else { - timeToTransfer = _time; - } - fee = timeToTransfer.mul(transferFeeBasisPoints) / BASIS_POINTS_DEN; - return fee; - } - - /** - * @notice Modify the expirationTimestamp of a key - * by a given amount. - * @param _tokenId The ID of the key to modify. - * @param _deltaT The amount of time in seconds by which - * to modify the keys expirationTimestamp - * @param _addTime Choose whether to increase or decrease - * expirationTimestamp (false == decrease, true == increase) - * @dev Throws if owner does not have a valid key. - */ - function _timeMachine( - uint _tokenId, - uint256 _deltaT, - bool _addTime - ) internal { - address tokenOwner = _ownerOf[_tokenId]; - require(tokenOwner != address(0), "NON_EXISTENT_KEY"); - Key storage key = keyByOwner[tokenOwner]; - uint formerTimestamp = key.expirationTimestamp; - bool validKey = getHasValidKey(tokenOwner); - if (_addTime) { - if (validKey) { - key.expirationTimestamp = formerTimestamp.add(_deltaT); - } else { - key.expirationTimestamp = block.timestamp.add(_deltaT); - } - } else { - key.expirationTimestamp = formerTimestamp.sub(_deltaT); - } - emit TimestampChanged(_tokenId, _deltaT, _addTime); - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.14; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IPublicLock, - ERC165, - Ownable, - MixinSignatures, - MixinFunds, - MixinDisableAndDestroy, - MixinLockManagerRole, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinERC721Enumerable, - MixinEventHooks, - MixinGrantKeys, - MixinPurchase, - MixinApproval, - MixinTransfer, - MixinRefunds -{ - function initialize( - address _owner, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) public initializer { - Ownable.initialize(_owner); - MixinFunds._initializeMixinFunds(_tokenAddress); - MixinDisableAndDestroy._initializeMixinDisableAndDestroy(); - MixinLockCore._initializeMixinLockCore( - _owner, - _expirationDuration, - _keyPrice, - _maxNumberOfKeys - ); - MixinLockMetadata._initializeMixinLockMetadata(_lockName); - MixinERC721Enumerable._initializeMixinERC721Enumerable(); - MixinRefunds._initializeMixinRefunds(); - MixinLockManagerRole._initializeMixinLockManagerRole(_owner); - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - } -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV7.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV7.sol deleted file mode 100644 index ac0252e0dbe..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV7.sol +++ /dev/null @@ -1,3260 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.7.1 - -pragma solidity >=0.4.24 <0.7.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/IERC165.sol@v2.4.0 - -pragma solidity ^0.5.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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/ERC165.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts may inherit from this and call {_registerInterface} to declare - * their support of an interface. - */ -contract ERC165 is Initializable, IERC165 { - /* - * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 - */ - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - function initialize() public initializer { - // Derived contracts need only register support for their own interfaces, - // we register support for ERC165 itself here - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev See {IERC165-supportsInterface}. - * - * Time complexity O(1), guaranteed to always use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) public view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See {IERC165-supportsInterface}. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } - - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. Does not include - * the optional functions; to access them see {ERC20Detailed}. - */ -interface IERC20 { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.4.0 - -pragma solidity ^0.5.5; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * This test is non-exhaustive, and there may be false-negatives: during the - * execution of a contract's constructor, its address will be reported as - * not containing 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. - */ - function isContract(address account) internal view returns (bool) { - // This method relies in extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != 0x0 && codehash != accountHash); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - * - * _Available since v2.4.0._ - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/SafeERC20.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @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 ERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using SafeMath for uint256; - 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) - ); - } - - 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' - // solhint-disable-next-line max-line-length - 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).add(value); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender).sub( - value, - "SafeERC20: decreased allowance below zero" - ); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - /** - * @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. - - // A Solidity high level call has three parts: - // 1. The target address is checked to verify it contains contract code - // 2. The call itself is made, and success asserted - // 3. The return value is decoded, which in turn checks the size of the returned data. - // solhint-disable-next-line max-line-length - require(address(token).isContract(), "SafeERC20: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = address(token).call(data); - require(success, "SafeERC20: low-level call failed"); - - if (returndata.length > 0) { - // Return data is optional - // solhint-disable-next-line max-line-length - require( - abi.decode(returndata, (bool)), - "SafeERC20: ERC20 operation did not succeed" - ); - } - } -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.17; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - using Address for address payable; - using SafeERC20 for IERC20; - - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - function _initializeMixinFunds(address _tokenAddress) internal { - tokenAddress = _tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - } - - /** - * Gets the current balance of the account provided. - */ - function getBalance( - address _tokenAddress, - address _account - ) public view returns (uint) { - if (_tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(_tokenAddress).balanceOf(_account); - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer( - address _tokenAddress, - address _to, - uint _amount - ) internal { - if (_amount > 0) { - if (_tokenAddress == address(0)) { - // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/ - address(uint160(_to)).sendValue(_amount); - } else { - IERC20 token = IERC20(_tokenAddress); - token.safeTransfer(_to, _amount); - } - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/access/Roles.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title Roles - * @dev Library for managing addresses assigned to a Role. - */ -library Roles { - struct Role { - mapping(address => bool) bearer; - } - - /** - * @dev Give an account access to this role. - */ - function add(Role storage role, address account) internal { - require(!has(role, account), "Roles: account already has role"); - role.bearer[account] = true; - } - - /** - * @dev Remove an account's access to this role. - */ - function remove(Role storage role, address account) internal { - require(has(role, account), "Roles: account does not have role"); - role.bearer[account] = false; - } - - /** - * @dev Check if an account has this role. - * @return bool - */ - function has( - Role storage role, - address account - ) internal view returns (bool) { - require(account != address(0), "Roles: account is the zero address"); - return role.bearer[account]; - } -} - -// File contracts/mixins/MixinLockManagerRole.sol - -pragma solidity 0.5.17; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinLockManagerRole { - using Roles for Roles.Role; - - event LockManagerAdded(address indexed account); - event LockManagerRemoved(address indexed account); - - Roles.Role private lockManagers; - - function _initializeMixinLockManagerRole(address sender) internal { - if (!isLockManager(sender)) { - lockManagers.add(sender); - } - } - - modifier onlyLockManager() { - require( - isLockManager(msg.sender), - "MixinLockManager: caller does not have the LockManager role" - ); - _; - } - - function isLockManager(address account) public view returns (bool) { - return lockManagers.has(account); - } - - function addLockManager(address account) public onlyLockManager { - lockManagers.add(account); - emit LockManagerAdded(account); - } - - function renounceLockManager() public { - lockManagers.remove(msg.sender); - emit LockManagerRemoved(msg.sender); - } -} - -// File contracts/mixins/MixinDisable.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisable is MixinLockManagerRole, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Disable(); - - function _initializeMixinDisable() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyLockManager onlyIfAlive { - emit Disable(); - isAlive = false; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** Function for the owner to update configuration variables. - * Should throw if called by other than owner. - */ - function configUnlock(string calldata _symbol, string calldata _URI) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapExchanges(address) external view returns (address); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - // allows the owner to set the exchange address to use for value conversions - // setting the _exchangeAddress to address(0) removes support for the token - function setExchange( - address _tokenAddress, - address _exchangeAddress - ) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File contracts/interfaces/hooks/ILockKeyCancelHook.sol - -pragma solidity 0.5.17; - -/** - * @notice Functions to be implemented by a keyCancelHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyCancelHook { - /** - * @notice If the lock owner has registered an implementer - * then this hook is called with every key cancel. - * @param operator the msg.sender issuing the cancel - * @param to the account which had the key canceled - * @param refund the amount sent to the `to` account (ETH or a ERC-20 token) - */ - function onKeyCancel(address operator, address to, uint256 refund) external; -} - -// File contracts/interfaces/hooks/ILockKeyPurchaseHook.sol - -pragma solidity 0.5.17; - -/** - * @notice Functions to be implemented by a keyPurchaseHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyPurchaseHook { - /** - * @notice Used to determine the purchase price before issueing a transaction. - * This allows the hook to offer a discount on purchases. - * This may revert to prevent a purchase. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @return the minimum value/price required to purchase a key with these settings - * @dev the lock's address is the `msg.sender` when this function is called via - * the lock's `purchasePriceFor` function - */ - function keyPurchasePrice( - address from, - address recipient, - address referrer, - bytes calldata data - ) external view returns (uint minKeyPrice); - - /** - * @notice If the lock owner has registered an implementer then this hook - * is called with every key sold. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @param minKeyPrice the price including any discount granted from calling this - * hook's `keyPurchasePrice` function - * @param pricePaid the value/pricePaid included with the purchase transaction - * @dev the lock's address is the `msg.sender` when this function is called - */ - function onKeyPurchase( - address from, - address recipient, - address referrer, - bytes calldata data, - uint minKeyPrice, - uint pricePaid - ) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is - IERC721Enumerable, - MixinLockManagerRole, - MixinFunds, - MixinDisable -{ - using Address for address; - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint internal _totalSupply; - - // The account which will receive funds on withdrawal - address public beneficiary; - - // The denominator component for values specified in basis points. - uint internal constant BASIS_POINTS_DEN = 10000; - - ILockKeyPurchaseHook public onKeyPurchaseHook; - ILockKeyCancelHook public onKeyCancelHook; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > _totalSupply, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyLockManagerOrBeneficiary() { - require( - isLockManager(msg.sender) || msg.sender == beneficiary, - "ONLY_LOCK_MANAGER_OR_BENEFICIARY" - ); - _; - } - - function _initializeMixinLockCore( - address _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - // The version number of the current implementation on this network - function publicLockVersion() public pure returns (uint) { - return 7; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw( - address _tokenAddress, - uint _amount - ) external onlyLockManagerOrBeneficiary { - uint balance = getBalance(_tokenAddress, address(this)); - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, _tokenAddress, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(_tokenAddress, beneficiary, amount); - } - - /** - * A function which lets the owner of the lock change the pricing for future purchases. - * This consists of 2 parts: The token address and the price in the given token. - * In order to set the token to ETH, use 0 for the token Address. - */ - function updateKeyPricing( - uint _keyPrice, - address _tokenAddress - ) external onlyLockManager onlyIfAlive { - uint oldKeyPrice = keyPrice; - address oldTokenAddress = tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - keyPrice = _keyPrice; - tokenAddress = _tokenAddress; - emit PricingChanged(oldKeyPrice, keyPrice, oldTokenAddress, tokenAddress); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary(address _beneficiary) external { - require( - msg.sender == beneficiary || isLockManager(msg.sender), - "ONLY_BENEFICIARY_OR_LOCKMANAGER" - ); - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - /** - * @notice Allows a lock manager to add or remove an event hook - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external onlyLockManager { - require( - _onKeyPurchaseHook == address(0) || _onKeyPurchaseHook.isContract(), - "INVALID_ON_KEY_SOLD_HOOK" - ); - require( - _onKeyCancelHook == address(0) || _onKeyCancelHook.isContract(), - "INVALID_ON_KEY_CANCEL_HOOK" - ); - onKeyPurchaseHook = ILockKeyPurchaseHook(_onKeyPurchaseHook); - onKeyCancelHook = ILockKeyCancelHook(_onKeyCancelHook); - } - - function totalSupply() public view returns (uint256) { - return _totalSupply; - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for managing `Key` data, as well as the * Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is MixinLockCore { - using SafeMath for uint; - - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Emitted when the Lock owner expires a user's Key - event ExpireKey(uint indexed tokenId); - - // Emitted when the expiration of a key is modified - event ExpirationChanged(uint indexed _tokenId, uint _amount, bool _timeAdded); - - event KeyManagerChanged(uint indexed _tokenId, address indexed _newManager); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with totalSupply into an array instead. - mapping(uint => address) internal _ownerOf; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // A given key has both an owner and a manager. - // If keyManager == address(0) then the key owner is also the manager - // Each key can have at most 1 keyManager. - mapping(uint => address) public keyManagerOf; - - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transferred - // Note: the approver may actually NOT have a key... and there can only - // be a single approved address - mapping(uint => address) private approved; - - // Keeping track of approved operators for a given Key manager. - // This approves a given operator for all keys managed by the calling "keyManager" - // The caller may not currently be the keyManager for ANY keys. - // These approvals are never reset/revoked automatically, unlike "approved", - // which is reset on transfer. - mapping(address => mapping(address => bool)) - private managerToOperatorApproved; - - // Ensure that the caller is the keyManager of the key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyManagerOrApproved(uint _tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(_ownerOf[_tokenId], msg.sender), - "ONLY_KEY_MANAGER_OR_APPROVED" - ); - _; - } - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _keyOwner) { - require( - keyByOwner[_keyOwner].expirationTimestamp > 0, - "HAS_NEVER_OWNED_KEY" - ); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _user) { - require(getHasValidKey(_user), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(_ownerOf[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_keyOwner`, either 0 or 1. - */ - function balanceOf(address _keyOwner) public view returns (uint) { - require(_keyOwner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_keyOwner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _keyOwner) public view returns (bool) { - return keyByOwner[_keyOwner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - */ - function getTokenIdFor(address _account) public view returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - require(owners.length > 0, "NO_OUTSTANDING_KEYS"); - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) public view returns (bool) { - return _ownerOf[_tokenId] == _keyOwner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) public view returns (uint) { - return keyByOwner[_keyOwner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - // Returns the owner of a given tokenId - function ownerOf( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - return _ownerOf[_tokenId]; - } - - /** - * @notice Public function for updating transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address with the manager's rights for the given key. - * Setting _keyManager to address(0) means the keyOwner is also the keyManager - */ - function setKeyManagerOf( - uint _tokenId, - address _keyManager - ) public isKey(_tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || isLockManager(msg.sender), - "UNAUTHORIZED_KEY_MANAGER_UPDATE" - ); - _setKeyManagerOf(_tokenId, _keyManager); - } - - function _setKeyManagerOf(uint _tokenId, address _keyManager) internal { - if (keyManagerOf[_tokenId] != _keyManager) { - keyManagerOf[_tokenId] = _keyManager; - _clearApproval(_tokenId); - emit KeyManagerChanged(_tokenId, address(0)); - } - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(_ownerOf[_tokenId], _approved, _tokenId); - } - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - address approvedRecipient = approved[_tokenId]; - return approvedRecipient; - } - - /** - * @dev Tells whether an operator is approved by a given keyManager - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - uint tokenId = keyByOwner[_owner].tokenId; - address keyManager = keyManagerOf[tokenId]; - if (keyManager == address(0)) { - return managerToOperatorApproved[_owner][_operator]; - } else { - return managerToOperatorApproved[keyManager][_operator]; - } - } - - /** - * Returns true if _keyManager is the manager of the key - * identified by _tokenId - */ - function _isKeyManager( - uint _tokenId, - address _keyManager - ) internal view returns (bool) { - if ( - keyManagerOf[_tokenId] == _keyManager || - (keyManagerOf[_tokenId] == address(0) && - isKeyOwner(_tokenId, _keyManager)) - ) { - return true; - } else { - return false; - } - } - - /** - * Assigns the key a new tokenId (from totalSupply) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner - // We increment the tokenId counter - _totalSupply++; - // we assign the incremented `_totalSupply` as the tokenId for the new key - _key.tokenId = _totalSupply; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _keyOwner, uint _tokenId) internal { - if (_ownerOf[_tokenId] != _keyOwner) { - // TODO: this may include duplicate entries - owners.push(_keyOwner); - // We register the owner of the tokenID - _ownerOf[_tokenId] = _keyOwner; - } - } - - /** - * @notice Modify the expirationTimestamp of a key - * by a given amount. - * @param _tokenId The ID of the key to modify. - * @param _deltaT The amount of time in seconds by which - * to modify the keys expirationTimestamp - * @param _addTime Choose whether to increase or decrease - * expirationTimestamp (false == decrease, true == increase) - * @dev Throws if owner does not have a valid key. - */ - function _timeMachine( - uint _tokenId, - uint256 _deltaT, - bool _addTime - ) internal { - address tokenOwner = _ownerOf[_tokenId]; - require(tokenOwner != address(0), "NON_EXISTENT_KEY"); - Key storage key = keyByOwner[tokenOwner]; - uint formerTimestamp = key.expirationTimestamp; - bool validKey = getHasValidKey(tokenOwner); - if (_addTime) { - if (validKey) { - key.expirationTimestamp = formerTimestamp.add(_deltaT); - } else { - key.expirationTimestamp = block.timestamp.add(_deltaT); - } - } else { - key.expirationTimestamp = formerTimestamp.sub(_deltaT); - } - emit ExpirationChanged(_tokenId, _deltaT, _addTime); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - managerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinERC721Enumerable.sol - -pragma solidity 0.5.17; - -/** - * @title Implements the ERC-721 Enumerable extension. - */ -contract MixinERC721Enumerable is - IERC721Enumerable, - ERC165, - MixinLockCore, // Implements totalSupply - MixinKeys -{ - function _initializeMixinERC721Enumerable() internal { - /** - * register the supported interface to conform to ERC721Enumerable via ERC165 - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - _registerInterface(0x780e9d63); - } - - /// @notice Enumerate valid NFTs - /// @dev Throws if `_index` >= `totalSupply()`. - /// @param _index A counter less than `totalSupply()` - /// @return The token identifier for the `_index`th NFT, - /// (sort order not specified) - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < _totalSupply, "OUT_OF_RANGE"); - return _index; - } - - /// @notice Enumerate NFTs assigned to an owner - /// @dev Throws if `_index` >= `balanceOf(_keyOwner)` or if - /// `_keyOwner` is the zero address, representing invalid NFTs. - /// @param _keyOwner An address where we are interested in NFTs owned by them - /// @param _index A counter less than `balanceOf(_keyOwner)` - /// @return The token identifier for the `_index`th NFT assigned to `_keyOwner`, - /// (sort order not specified) - function tokenOfOwnerByIndex( - address _keyOwner, - uint256 _index - ) public view returns (uint256) { - require(_index == 0, "ONLY_ONE_KEY_PER_OWNER"); - return getTokenIdFor(_keyOwner); - } -} - -// File contracts/mixins/MixinKeyGranterRole.sol - -pragma solidity 0.5.17; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinKeyGranterRole is MixinLockManagerRole { - using Roles for Roles.Role; - - event KeyGranterAdded(address indexed account); - event KeyGranterRemoved(address indexed account); - - Roles.Role private keyGranters; - - function _initializeMixinKeyGranterRole(address sender) internal { - if (!isKeyGranter(sender)) { - keyGranters.add(sender); - } - } - - modifier onlyKeyGranterOrManager() { - require( - isKeyGranter(msg.sender) || isLockManager(msg.sender), - "MixinKeyGranter: caller does not have the KeyGranter or LockManager role" - ); - _; - } - - function isKeyGranter(address account) public view returns (bool) { - return keyGranters.has(account); - } - - function addKeyGranter(address account) public onlyLockManager { - keyGranters.add(account); - emit KeyGranterAdded(account); - } - - function revokeKeyGranter(address _granter) public onlyLockManager { - keyGranters.remove(_granter); - emit KeyGranterRemoved(_granter); - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is MixinKeyGranterRole, MixinKeys { - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external onlyKeyGranterOrManager { - for (uint i = 0; i < _recipients.length; i++) { - address recipient = _recipients[i]; - uint expirationTimestamp = _expirationTimestamps[i]; - address keyManager = _keyManagers[i]; - - require(recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = keyByOwner[recipient]; - require( - expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - uint idTo = toKey.tokenId; - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(recipient, idTo); - } - // Set the key Manager - _setKeyManagerOf(idTo, keyManager); - emit KeyManagerChanged(idTo, keyManager); - - toKey.expirationTimestamp = expirationTimestamp; - // trigger event - emit Transfer( - address(0), // This is a creation. - recipient, - idTo - ); - } - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.17; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -library UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) internal pure returns (string memory _concatenatedString) { - return string(abi.encodePacked(_a, _b, _c, _d)); - } - - function uint2Str( - uint _i - ) internal pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) internal pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721Enumerable, - ERC165, - MixinLockManagerRole, - MixinLockCore, - MixinKeys -{ - using UnlockUtils for uint; - using UnlockUtils for address; - using UnlockUtils for string; - - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string public name; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - function _initializeMixinLockMetadata(string memory _lockName) internal { - ERC165.initialize(); - name = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyLockManager { - name = _lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol( - string calldata _lockSymbol - ) external onlyLockManager { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.globalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI( - string calldata _baseTokenURI - ) external onlyLockManager { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI( - uint256 _tokenId - ) external view isKey(_tokenId) returns (string memory) { - string memory URI; - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.globalBaseTokenURI(); - } else { - URI = baseTokenURI; - } - - return URI.strConcat(address(this).address2Str(), "/", _tokenId.uint2Str()); - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is MixinFunds, MixinDisable, MixinLockCore, MixinKeys { - using SafeMath for uint; - - event RenewKeyPurchase(address indexed owner, uint newExpiration); - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable onlyIfAlive notSoldOut { - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Assign the key - Key storage toKey = keyByOwner[_recipient]; - uint idTo = toKey.tokenId; - uint newTimeStamp; - - if (idTo == 0) { - // Assign a new tokenId (if a new owner or previously transferred) - _assignNewTokenId(toKey); - // refresh the cached value - idTo = toKey.tokenId; - _recordOwner(_recipient, idTo); - newTimeStamp = block.timestamp + expirationDuration; - toKey.expirationTimestamp = newTimeStamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - idTo - ); - } else if (toKey.expirationTimestamp > block.timestamp) { - // This is an existing owner trying to extend their key - newTimeStamp = toKey.expirationTimestamp.add(expirationDuration); - toKey.expirationTimestamp = newTimeStamp; - emit RenewKeyPurchase(_recipient, newTimeStamp); - } else { - // This is an existing owner trying to renew their expired key - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - newTimeStamp = block.timestamp + expirationDuration; - toKey.expirationTimestamp = newTimeStamp; - - // reset the key Manager to 0x00 - _setKeyManagerOf(idTo, address(0)); - - emit RenewKeyPurchase(_recipient, newTimeStamp); - } - - (uint inMemoryKeyPrice, uint discount, uint tokens) = _purchasePriceFor( - _recipient, - _referrer, - _data - ); - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - // Record price without any tips - unlockProtocol.recordKeyPurchase(inMemoryKeyPrice, _referrer); - - // We explicitly allow for greater amounts of ETH or tokens to allow 'donations' - uint pricePaid; - if (tokenAddress != address(0)) { - pricePaid = _value; - IERC20 token = IERC20(tokenAddress); - token.safeTransferFrom(msg.sender, address(this), _value); - } else { - pricePaid = msg.value; - } - require(pricePaid >= inMemoryKeyPrice, "INSUFFICIENT_VALUE"); - - if (address(onKeyPurchaseHook) != address(0)) { - onKeyPurchaseHook.onKeyPurchase( - msg.sender, - _recipient, - _referrer, - _data, - inMemoryKeyPrice, - pricePaid - ); - } - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint minKeyPrice) { - (minKeyPrice, , ) = _purchasePriceFor(_recipient, _referrer, _data); - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - * unlockDiscount and unlockTokens are the values returned from `computeAvailableDiscountFor` - */ - function _purchasePriceFor( - address _recipient, - address _referrer, - bytes memory _data - ) - internal - view - returns (uint minKeyPrice, uint unlockDiscount, uint unlockTokens) - { - if (address(onKeyPurchaseHook) != address(0)) { - minKeyPrice = onKeyPurchaseHook.keyPurchasePrice( - msg.sender, - _recipient, - _referrer, - _data - ); - } else { - minKeyPrice = keyPrice; - } - - if (minKeyPrice > 0) { - (unlockDiscount, unlockTokens) = unlockProtocol - .computeAvailableDiscountFor(_recipient, minKeyPrice); - require(unlockDiscount <= minKeyPrice, "INVALID_DISCOUNT_FROM_UNLOCK"); - minKeyPrice -= unlockDiscount; - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/cryptography/ECDSA.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * NOTE: This call _does not revert_ if the signature is invalid, or - * if the signer is otherwise unable to be retrieved. In those scenarios, - * the zero address is returned. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] - * JSON-RPC method. - * - * See {recover}. - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinSignatures.sol - -pragma solidity 0.5.17; - -contract MixinSignatures { - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyManager, uint nextAvailableNonce); - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyManagerToNonce; - - /// @notice Validates an off-chain approval signature. - /// @dev If valid the nonce is consumed, else revert. - modifier consumeOffchainApproval( - bytes32 _hash, - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s - ) { - require( - ecrecover(ECDSA.toEthSignedMessageHash(_hash), _v, _r, _s) == _keyManager, - "INVALID_SIGNATURE" - ); - keyManagerToNonce[_keyManager]++; - emit NonceChanged(_keyManager, keyManagerToNonce[_keyManager]); - _; - } - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external { - require( - _nextAvailableNonce > keyManagerToNonce[msg.sender], - "NONCE_ALREADY_USED" - ); - keyManagerToNonce[msg.sender] = _nextAvailableNonce; - emit NonceChanged(msg.sender, _nextAvailableNonce); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.17; - -contract MixinRefunds is - MixinLockManagerRole, - MixinSignatures, - MixinFunds, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyBasisPoints / BASIS_POINTS_DEN`. - uint public refundPenaltyBasisPoints; - - uint public freeTrialLength; - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - bytes32 private constant CANCEL_TYPEHASH = - keccak256("cancelAndRefundFor(address _keyOwner)"); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - function _initializeMixinRefunds() internal { - // default to 10% - refundPenaltyBasisPoints = 1000; - } - - /** - * @dev Invoked by the lock owner to destroy the user's ket and perform a refund and cancellation - * of the key - */ - function expireAndRefundFor( - address _keyOwner, - uint amount - ) external onlyLockManager hasValidKey(_keyOwner) { - _cancelAndRefund(_keyOwner, amount); - } - - /** - * @dev Destroys the key and sends a refund based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund( - uint _tokenId - ) external onlyKeyManagerOrApproved(_tokenId) { - address keyOwner = ownerOf(_tokenId); - uint refund = _getCancelAndRefundValue(keyOwner); - - _cancelAndRefund(keyOwner, refund); - } - - /** - * @dev Cancels a key managed by a different user and sends the funds to the msg.sender. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) - external - consumeOffchainApproval( - getCancelAndRefundApprovalHash(_keyManager, msg.sender), - _keyManager, - _v, - _r, - _s - ) - { - address keyOwner = ownerOf(_tokenId); - uint refund = _getCancelAndRefundValue(keyOwner); - _cancelAndRefund(keyOwner, refund); - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external onlyLockManager { - emit RefundPenaltyChanged(_freeTrialLength, _refundPenaltyBasisPoints); - - freeTrialLength = _freeTrialLength; - refundPenaltyBasisPoints = _refundPenaltyBasisPoints; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_keyOwner); - } - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // The specific function the signer is approving - CANCEL_TYPEHASH, - // Approval enables only one cancel call - keyManagerToNonce[_keyManager], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner, uint refund) internal { - Key storage key = keyByOwner[_keyOwner]; - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(tokenAddress, _keyOwner, refund); - } - - // inform the hook if there is one registered - if (address(onKeyCancelHook) != address(0)) { - onKeyCancelHook.onKeyCancel(msg.sender, _keyOwner, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _keyOwner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _keyOwner - ) private view hasValidKey(_keyOwner) returns (uint refund) { - Key storage key = keyByOwner[_keyOwner]; - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining + freeTrialLength >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - - // Apply the penalty if this is not a free trial - if ( - freeTrialLength == 0 || - timeRemaining + freeTrialLength < expirationDuration - ) { - uint penalty = keyPrice.mul(refundPenaltyBasisPoints) / BASIS_POINTS_DEN; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Receiver.sol@v2.4.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a {IERC721-safeTransferFrom}. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is - MixinLockManagerRole, - MixinFunds, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged(uint transferFeeBasisPoints); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeBasisPoints / BASIS_POINTS_DEN`. - uint public transferFeeBasisPoints; - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - */ - function shareKey( - address _to, - uint _tokenId, - uint _timeShared - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_to != address(0), "INVALID_ADDRESS"); - address keyOwner = _ownerOf[_tokenId]; - require(getHasValidKey(keyOwner), "KEY_NOT_VALID"); - Key storage fromKey = keyByOwner[keyOwner]; - Key storage toKey = keyByOwner[_to]; - uint idTo = toKey.tokenId; - uint time; - // get the remaining time for the origin key - uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; - // get the transfer fee based on amount of time wanted share - uint fee = getTransferFee(keyOwner, _timeShared); - uint timePlusFee = _timeShared.add(fee); - - // ensure that we don't try to share too much - if (timePlusFee < timeRemaining) { - // now we can safely set the time - time = _timeShared; - // deduct time from parent key, including transfer fee - _timeMachine(_tokenId, timePlusFee, false); - } else { - // we have to recalculate the fee here - fee = getTransferFee(keyOwner, timeRemaining); - time = timeRemaining - fee; - fromKey.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(_tokenId); - } - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(_to, idTo); - emit Transfer( - address(0), // This is a creation or time-sharing - _to, - idTo - ); - } else if (toKey.expirationTimestamp <= block.timestamp) { - // reset the key Manager for expired keys - _setKeyManagerOf(idTo, address(0)); - } - - // add time to new key - _timeMachine(idTo, time, true); - // trigger event - emit Transfer(keyOwner, _to, idTo); - - require( - _checkOnERC721Received(keyOwner, _to, _tokenId, ""), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) public onlyIfAlive hasValidKey(_from) onlyKeyManagerOrApproved(_tokenId) { - require(isKeyOwner(_tokenId, _from), "TRANSFER_FROM: NOT_KEY_OWNER"); - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_recipient != address(0), "INVALID_ADDRESS"); - uint fee = getTransferFee(_from, 0); - - Key storage fromKey = keyByOwner[_from]; - Key storage toKey = keyByOwner[_recipient]; - - uint previousExpiration = toKey.expirationTimestamp; - // subtract the fee from the senders key before the transfer - _timeMachine(_tokenId, fee, false); - - if (toKey.tokenId == 0) { - toKey.tokenId = _tokenId; - _recordOwner(_recipient, _tokenId); - // Clear any previous approvals - _clearApproval(_tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the sender's key expiration - // An expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = _tokenId; - - // Reset the key Manager to the key owner - _setKeyManagerOf(_tokenId, address(0)); - - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom(address _from, address _to, uint _tokenId) public { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) public { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeBasisPoints - ) external onlyLockManager { - emit TransferFeeChanged(_transferFeeBasisPoints); - transferFeeBasisPoints = _transferFeeBasisPoints; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _keyOwner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) public view hasValidKey(_keyOwner) returns (uint) { - Key storage key = keyByOwner[_keyOwner]; - uint timeToTransfer; - uint fee; - // Math: safeSub is not required since `hasValidKey` confirms timeToTransfer is positive - // this is for standard key transfers - if (_time == 0) { - timeToTransfer = key.expirationTimestamp - block.timestamp; - } else { - timeToTransfer = _time; - } - fee = timeToTransfer.mul(transferFeeBasisPoints) / BASIS_POINTS_DEN; - return fee; - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IPublicLock, - Initializable, - ERC165, - MixinLockManagerRole, - MixinKeyGranterRole, - MixinSignatures, - MixinFunds, - MixinDisable, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinERC721Enumerable, - MixinGrantKeys, - MixinPurchase, - MixinTransfer, - MixinRefunds -{ - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) public initializer { - MixinFunds._initializeMixinFunds(_tokenAddress); - MixinDisable._initializeMixinDisable(); - MixinLockCore._initializeMixinLockCore( - _lockCreator, - _expirationDuration, - _keyPrice, - _maxNumberOfKeys - ); - MixinLockMetadata._initializeMixinLockMetadata(_lockName); - MixinERC721Enumerable._initializeMixinERC721Enumerable(); - MixinRefunds._initializeMixinRefunds(); - MixinLockManagerRole._initializeMixinLockManagerRole(_lockCreator); - MixinKeyGranterRole._initializeMixinKeyGranterRole(_lockCreator); - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - } - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable {} -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV8.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV8.sol deleted file mode 100644 index 44eede0ae0a..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV8.sol +++ /dev/null @@ -1,3342 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.8.0 - -pragma solidity >=0.4.24 <0.7.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/IERC165.sol@v2.5.0 - -pragma solidity ^0.5.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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/introspection/ERC165.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts may inherit from this and call {_registerInterface} to declare - * their support of an interface. - */ -contract ERC165 is Initializable, IERC165 { - /* - * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 - */ - bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - function initialize() public initializer { - // Derived contracts need only register support for their own interfaces, - // we register support for ERC165 itself here - _registerInterface(_INTERFACE_ID_ERC165); - } - - /** - * @dev See {IERC165-supportsInterface}. - * - * Time complexity O(1), guaranteed to always use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) public view returns (bool) { - return _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See {IERC165-supportsInterface}. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } - - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. Does not include - * the optional functions; to access them see {ERC20Detailed}. - */ -interface IERC20 { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.5.0 - -pragma solidity ^0.5.5; - -/** - * @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 - * ==== - */ - function isContract(address account) internal view returns (bool) { - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != accountHash && codehash != 0x0); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - * - * _Available since v2.4.0._ - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC20/SafeERC20.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @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 ERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using SafeMath for uint256; - 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) - ); - } - - 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' - // solhint-disable-next-line max-line-length - 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).add(value); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender).sub( - value, - "SafeERC20: decreased allowance below zero" - ); - callOptionalReturn( - token, - abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - /** - * @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. - - // A Solidity high level call has three parts: - // 1. The target address is checked to verify it contains contract code - // 2. The call itself is made, and success asserted - // 3. The return value is decoded, which in turn checks the size of the returned data. - // solhint-disable-next-line max-line-length - require(address(token).isContract(), "SafeERC20: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = address(token).call(data); - require(success, "SafeERC20: low-level call failed"); - - if (returndata.length > 0) { - // Return data is optional - // solhint-disable-next-line max-line-length - require( - abi.decode(returndata, (bool)), - "SafeERC20: ERC20 operation did not succeed" - ); - } - } -} - -// File contracts/mixins/MixinFunds.sol - -pragma solidity 0.5.17; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - using Address for address payable; - using SafeERC20 for IERC20; - - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - function _initializeMixinFunds(address _tokenAddress) internal { - tokenAddress = _tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - } - - /** - * Gets the current balance of the account provided. - */ - function getBalance( - address _tokenAddress, - address _account - ) public view returns (uint) { - if (_tokenAddress == address(0)) { - return _account.balance; - } else { - return IERC20(_tokenAddress).balanceOf(_account); - } - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer( - address _tokenAddress, - address _to, - uint _amount - ) internal { - if (_amount > 0) { - if (_tokenAddress == address(0)) { - // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/ - address(uint160(_to)).sendValue(_amount); - } else { - IERC20 token = IERC20(_tokenAddress); - token.safeTransfer(_to, _amount); - } - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/access/Roles.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @title Roles - * @dev Library for managing addresses assigned to a Role. - */ -library Roles { - struct Role { - mapping(address => bool) bearer; - } - - /** - * @dev Give an account access to this role. - */ - function add(Role storage role, address account) internal { - require(!has(role, account), "Roles: account already has role"); - role.bearer[account] = true; - } - - /** - * @dev Remove an account's access to this role. - */ - function remove(Role storage role, address account) internal { - require(has(role, account), "Roles: account does not have role"); - role.bearer[account] = false; - } - - /** - * @dev Check if an account has this role. - * @return bool - */ - function has( - Role storage role, - address account - ) internal view returns (bool) { - require(account != address(0), "Roles: account is the zero address"); - return role.bearer[account]; - } -} - -// File contracts/mixins/MixinLockManagerRole.sol - -pragma solidity 0.5.17; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinLockManagerRole { - using Roles for Roles.Role; - - event LockManagerAdded(address indexed account); - event LockManagerRemoved(address indexed account); - - Roles.Role private lockManagers; - - function _initializeMixinLockManagerRole(address sender) internal { - if (!isLockManager(sender)) { - lockManagers.add(sender); - } - } - - modifier onlyLockManager() { - require( - isLockManager(msg.sender), - "MixinLockManager: caller does not have the LockManager role" - ); - _; - } - - function isLockManager(address account) public view returns (bool) { - return lockManagers.has(account); - } - - function addLockManager(address account) public onlyLockManager { - lockManagers.add(account); - emit LockManagerAdded(account); - } - - function renounceLockManager() public { - lockManagers.remove(msg.sender); - emit LockManagerRemoved(msg.sender); - } -} - -// File contracts/mixins/MixinDisable.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisable is MixinLockManagerRole, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Disable(); - - function _initializeMixinDisable() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyLockManager onlyIfAlive { - emit Disable(); - isAlive = false; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -contract IERC721 is Initializable, IERC165 { - event Transfer( - address indexed from, - address indexed to, - uint256 indexed tokenId - ); - event Approval( - address indexed owner, - address indexed approved, - uint256 indexed tokenId - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - function getApproved(uint256 tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -contract IERC721Enumerable is Initializable, IERC721 { - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI - ) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File contracts/interfaces/hooks/ILockKeyCancelHook.sol - -pragma solidity 0.5.17; - -/** - * @notice Functions to be implemented by a keyCancelHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyCancelHook { - /** - * @notice If the lock owner has registered an implementer - * then this hook is called with every key cancel. - * @param operator the msg.sender issuing the cancel - * @param to the account which had the key canceled - * @param refund the amount sent to the `to` account (ETH or a ERC-20 token) - */ - function onKeyCancel(address operator, address to, uint256 refund) external; -} - -// File contracts/interfaces/hooks/ILockKeyPurchaseHook.sol - -pragma solidity 0.5.17; - -/** - * @notice Functions to be implemented by a keyPurchaseHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyPurchaseHook { - /** - * @notice Used to determine the purchase price before issueing a transaction. - * This allows the hook to offer a discount on purchases. - * This may revert to prevent a purchase. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @return the minimum value/price required to purchase a key with these settings - * @dev the lock's address is the `msg.sender` when this function is called via - * the lock's `purchasePriceFor` function - */ - function keyPurchasePrice( - address from, - address recipient, - address referrer, - bytes calldata data - ) external view returns (uint minKeyPrice); - - /** - * @notice If the lock owner has registered an implementer then this hook - * is called with every key sold. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @param minKeyPrice the price including any discount granted from calling this - * hook's `keyPurchasePrice` function - * @param pricePaid the value/pricePaid included with the purchase transaction - * @dev the lock's address is the `msg.sender` when this function is called - */ - function onKeyPurchase( - address from, - address recipient, - address referrer, - bytes calldata data, - uint minKeyPrice, - uint pricePaid - ) external; -} - -// File contracts/mixins/MixinLockCore.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is - IERC721Enumerable, - MixinLockManagerRole, - MixinFunds, - MixinDisable -{ - using Address for address; - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - // TODO: add support for a timestamp instead of duration - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint internal _totalSupply; - - // The account which will receive funds on withdrawal - address public beneficiary; - - // The denominator component for values specified in basis points. - uint internal constant BASIS_POINTS_DEN = 10000; - - ILockKeyPurchaseHook public onKeyPurchaseHook; - ILockKeyCancelHook public onKeyCancelHook; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > _totalSupply, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyLockManagerOrBeneficiary() { - require( - isLockManager(msg.sender) || msg.sender == beneficiary, - "ONLY_LOCK_MANAGER_OR_BENEFICIARY" - ); - _; - } - - function _initializeMixinLockCore( - address _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - // The version number of the current implementation on this network - function publicLockVersion() public pure returns (uint) { - return 8; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw( - address _tokenAddress, - uint _amount - ) external onlyLockManagerOrBeneficiary { - uint balance = getBalance(_tokenAddress, address(this)); - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, _tokenAddress, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(_tokenAddress, beneficiary, amount); - } - - /** - * A function which lets the owner of the lock change the pricing for future purchases. - * This consists of 2 parts: The token address and the price in the given token. - * In order to set the token to ETH, use 0 for the token Address. - */ - function updateKeyPricing( - uint _keyPrice, - address _tokenAddress - ) external onlyLockManager onlyIfAlive { - uint oldKeyPrice = keyPrice; - address oldTokenAddress = tokenAddress; - require( - _tokenAddress == address(0) || IERC20(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - keyPrice = _keyPrice; - tokenAddress = _tokenAddress; - emit PricingChanged(oldKeyPrice, keyPrice, oldTokenAddress, tokenAddress); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary(address _beneficiary) external { - require( - msg.sender == beneficiary || isLockManager(msg.sender), - "ONLY_BENEFICIARY_OR_LOCKMANAGER" - ); - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - /** - * @notice Allows a lock manager to add or remove an event hook - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external onlyLockManager { - require( - _onKeyPurchaseHook == address(0) || _onKeyPurchaseHook.isContract(), - "INVALID_ON_KEY_SOLD_HOOK" - ); - require( - _onKeyCancelHook == address(0) || _onKeyCancelHook.isContract(), - "INVALID_ON_KEY_CANCEL_HOOK" - ); - onKeyPurchaseHook = ILockKeyPurchaseHook(_onKeyPurchaseHook); - onKeyCancelHook = ILockKeyCancelHook(_onKeyCancelHook); - } - - function totalSupply() public view returns (uint256) { - return _totalSupply; - } - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) public onlyLockManagerOrBeneficiary returns (bool) { - return IERC20(tokenAddress).approve(_spender, _amount); - } -} - -// File contracts/mixins/MixinKeys.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for managing `Key` data, as well as the * Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is MixinLockCore { - using SafeMath for uint; - - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Emitted when the Lock owner expires a user's Key - event ExpireKey(uint indexed tokenId); - - // Emitted when the expiration of a key is modified - event ExpirationChanged(uint indexed _tokenId, uint _amount, bool _timeAdded); - - event KeyManagerChanged(uint indexed _tokenId, address indexed _newManager); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with totalSupply into an array instead. - mapping(uint => address) internal _ownerOf; - - // Addresses of owners are also stored in an array. - // Addresses are never removed by design to avoid abuses around referals - address[] public owners; - - // A given key has both an owner and a manager. - // If keyManager == address(0) then the key owner is also the manager - // Each key can have at most 1 keyManager. - mapping(uint => address) public keyManagerOf; - - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transferred - // Note: the approver may actually NOT have a key... and there can only - // be a single approved address - mapping(uint => address) private approved; - - // Keeping track of approved operators for a given Key manager. - // This approves a given operator for all keys managed by the calling "keyManager" - // The caller may not currently be the keyManager for ANY keys. - // These approvals are never reset/revoked automatically, unlike "approved", - // which is reset on transfer. - mapping(address => mapping(address => bool)) - private managerToOperatorApproved; - - // Ensure that the caller is the keyManager of the key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyManagerOrApproved(uint _tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(_ownerOf[_tokenId], msg.sender), - "ONLY_KEY_MANAGER_OR_APPROVED" - ); - _; - } - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _keyOwner) { - require( - keyByOwner[_keyOwner].expirationTimestamp > 0, - "HAS_NEVER_OWNED_KEY" - ); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _user) { - require(getHasValidKey(_user), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(_ownerOf[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(isKeyOwner(_tokenId, msg.sender), "ONLY_KEY_OWNER"); - _; - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_keyOwner`, either 0 or 1. - */ - function balanceOf(address _keyOwner) public view returns (uint) { - require(_keyOwner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_keyOwner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey(address _keyOwner) public view returns (bool) { - return keyByOwner[_keyOwner].expirationTimestamp > block.timestamp; - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - */ - function getTokenIdFor(address _account) public view returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) public view returns (address[] memory) { - uint pageSize = _pageSize; - uint _startIndex = _page * pageSize; - uint endOfPageIndex; - - if (_startIndex + pageSize > owners.length) { - endOfPageIndex = owners.length; - pageSize = owners.length - _startIndex; - } else { - endOfPageIndex = (_startIndex + pageSize); - } - - // new temp in-memory array to hold pageSize number of requested owners: - address[] memory ownersByPage = new address[](pageSize); - uint pageIndex = 0; - - // Build the requested set of owners into a new temporary array: - for (uint i = _startIndex; i < endOfPageIndex; i++) { - ownersByPage[pageIndex] = owners[i]; - pageIndex++; - } - - return ownersByPage; - } - - /** - * Checks if the given address owns the given tokenId. - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) public view returns (bool) { - return _ownerOf[_tokenId] == _keyOwner; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) public view returns (uint) { - return keyByOwner[_keyOwner].expirationTimestamp; - } - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() public view returns (uint) { - return owners.length; - } - - // Returns the owner of a given tokenId - function ownerOf(uint _tokenId) public view returns (address) { - return _ownerOf[_tokenId]; - } - - /** - * @notice Public function for updating transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address with the manager's rights for the given key. - * Setting _keyManager to address(0) means the keyOwner is also the keyManager - */ - function setKeyManagerOf( - uint _tokenId, - address _keyManager - ) public isKey(_tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || isLockManager(msg.sender), - "UNAUTHORIZED_KEY_MANAGER_UPDATE" - ); - _setKeyManagerOf(_tokenId, _keyManager); - } - - function _setKeyManagerOf(uint _tokenId, address _keyManager) internal { - if (keyManagerOf[_tokenId] != _keyManager) { - keyManagerOf[_tokenId] = _keyManager; - _clearApproval(_tokenId); - emit KeyManagerChanged(_tokenId, address(0)); - } - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(_ownerOf[_tokenId], _approved, _tokenId); - } - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - address approvedRecipient = approved[_tokenId]; - return approvedRecipient; - } - - /** - * @dev Tells whether an operator is approved by a given keyManager - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - uint tokenId = keyByOwner[_owner].tokenId; - address keyManager = keyManagerOf[tokenId]; - if (keyManager == address(0)) { - return managerToOperatorApproved[_owner][_operator]; - } else { - return managerToOperatorApproved[keyManager][_operator]; - } - } - - /** - * Returns true if _keyManager is the manager of the key - * identified by _tokenId - */ - function _isKeyManager( - uint _tokenId, - address _keyManager - ) internal view returns (bool) { - if ( - keyManagerOf[_tokenId] == _keyManager || - (keyManagerOf[_tokenId] == address(0) && - isKeyOwner(_tokenId, _keyManager)) - ) { - return true; - } else { - return false; - } - } - - /** - * Assigns the key a new tokenId (from totalSupply) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner - // We increment the tokenId counter - _totalSupply++; - // we assign the incremented `_totalSupply` as the tokenId for the new key - _key.tokenId = _totalSupply; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _keyOwner, uint _tokenId) internal { - if (_ownerOf[_tokenId] != _keyOwner) { - // TODO: this may include duplicate entries - owners.push(_keyOwner); - // We register the owner of the tokenID - _ownerOf[_tokenId] = _keyOwner; - } - } - - /** - * @notice Modify the expirationTimestamp of a key - * by a given amount. - * @param _tokenId The ID of the key to modify. - * @param _deltaT The amount of time in seconds by which - * to modify the keys expirationTimestamp - * @param _addTime Choose whether to increase or decrease - * expirationTimestamp (false == decrease, true == increase) - * @dev Throws if owner does not have a valid key. - */ - function _timeMachine( - uint _tokenId, - uint256 _deltaT, - bool _addTime - ) internal { - address tokenOwner = _ownerOf[_tokenId]; - require(tokenOwner != address(0), "NON_EXISTENT_KEY"); - Key storage key = keyByOwner[tokenOwner]; - uint formerTimestamp = key.expirationTimestamp; - bool validKey = getHasValidKey(tokenOwner); - if (_addTime) { - if (validKey) { - key.expirationTimestamp = formerTimestamp.add(_deltaT); - } else { - key.expirationTimestamp = block.timestamp.add(_deltaT); - } - } else { - key.expirationTimestamp = formerTimestamp.sub(_deltaT); - } - emit ExpirationChanged(_tokenId, _deltaT, _addTime); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - managerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } -} - -// File contracts/mixins/MixinERC721Enumerable.sol - -pragma solidity 0.5.17; - -/** - * @title Implements the ERC-721 Enumerable extension. - */ -contract MixinERC721Enumerable is - IERC721Enumerable, - ERC165, - MixinLockCore, // Implements totalSupply - MixinKeys -{ - function _initializeMixinERC721Enumerable() internal { - /** - * register the supported interface to conform to ERC721Enumerable via ERC165 - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - _registerInterface(0x780e9d63); - } - - /// @notice Enumerate valid NFTs - /// @dev Throws if `_index` >= `totalSupply()`. - /// @param _index A counter less than `totalSupply()` - /// @return The token identifier for the `_index`th NFT, - /// (sort order not specified) - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < _totalSupply, "OUT_OF_RANGE"); - return _index; - } - - /// @notice Enumerate NFTs assigned to an owner - /// @dev Throws if `_index` >= `balanceOf(_keyOwner)` or if - /// `_keyOwner` is the zero address, representing invalid NFTs. - /// @param _keyOwner An address where we are interested in NFTs owned by them - /// @param _index A counter less than `balanceOf(_keyOwner)` - /// @return The token identifier for the `_index`th NFT assigned to `_keyOwner`, - /// (sort order not specified) - function tokenOfOwnerByIndex( - address _keyOwner, - uint256 _index - ) public view returns (uint256) { - require(_index == 0, "ONLY_ONE_KEY_PER_OWNER"); - return getTokenIdFor(_keyOwner); - } -} - -// File contracts/mixins/MixinKeyGranterRole.sol - -pragma solidity 0.5.17; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinKeyGranterRole is MixinLockManagerRole { - using Roles for Roles.Role; - - event KeyGranterAdded(address indexed account); - event KeyGranterRemoved(address indexed account); - - Roles.Role private keyGranters; - - function _initializeMixinKeyGranterRole(address sender) internal { - if (!isKeyGranter(sender)) { - keyGranters.add(sender); - } - } - - modifier onlyKeyGranterOrManager() { - require( - isKeyGranter(msg.sender) || isLockManager(msg.sender), - "MixinKeyGranter: caller does not have the KeyGranter or LockManager role" - ); - _; - } - - function isKeyGranter(address account) public view returns (bool) { - return keyGranters.has(account); - } - - function addKeyGranter(address account) public onlyLockManager { - keyGranters.add(account); - emit KeyGranterAdded(account); - } - - function revokeKeyGranter(address _granter) public onlyLockManager { - keyGranters.remove(_granter); - emit KeyGranterRemoved(_granter); - } -} - -// File contracts/mixins/MixinGrantKeys.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is MixinKeyGranterRole, MixinKeys { - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external onlyKeyGranterOrManager { - for (uint i = 0; i < _recipients.length; i++) { - address recipient = _recipients[i]; - uint expirationTimestamp = _expirationTimestamps[i]; - address keyManager = _keyManagers[i]; - - require(recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = keyByOwner[recipient]; - require( - expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - uint idTo = toKey.tokenId; - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(recipient, idTo); - } - // Set the key Manager - _setKeyManagerOf(idTo, keyManager); - emit KeyManagerChanged(idTo, keyManager); - - toKey.expirationTimestamp = expirationTimestamp; - // trigger event - emit Transfer( - address(0), // This is a creation. - recipient, - idTo - ); - } - } -} - -// File contracts/UnlockUtils.sol - -pragma solidity 0.5.17; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -library UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) internal pure returns (string memory _concatenatedString) { - return string(abi.encodePacked(_a, _b, _c, _d)); - } - - function uint2Str( - uint _i - ) internal pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len - 1; - while (c != 0) { - bstr[k--] = bytes1(uint8(48 + (c % 10))); - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) internal pure returns (string memory) { - bytes32 value = bytes32(uint256(_addr)); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - IERC721Enumerable, - ERC165, - MixinLockManagerRole, - MixinLockCore, - MixinKeys -{ - using UnlockUtils for uint; - using UnlockUtils for address; - using UnlockUtils for string; - - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string public name; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - function _initializeMixinLockMetadata(string memory _lockName) internal { - ERC165.initialize(); - name = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyLockManager { - name = _lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol( - string calldata _lockSymbol - ) external onlyLockManager { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.globalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI( - string calldata _baseTokenURI - ) external onlyLockManager { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @param _tokenId The iD of the token for which we want to retrieve the URI. - * If 0 is passed here, we just return the appropriate baseTokenURI. - * If a custom URI has been set we don't return the lock address. - * It may be included in the custom baseTokenURI if needed. - * @dev URIs are defined in RFC 3986. The URI may point to a JSON file - * that conforms to the "ERC721 Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI(uint256 _tokenId) external view returns (string memory) { - string memory URI; - string memory tokenId; - string memory lockAddress = address(this).address2Str(); - string memory seperator; - - if (_tokenId != 0) { - tokenId = _tokenId.uint2Str(); - } else { - tokenId = ""; - } - - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.globalBaseTokenURI(); - seperator = "/"; - } else { - URI = baseTokenURI; - seperator = ""; - lockAddress = ""; - } - - return URI.strConcat(lockAddress, seperator, tokenId); - } -} - -// File contracts/mixins/MixinPurchase.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is MixinFunds, MixinDisable, MixinLockCore, MixinKeys { - using SafeMath for uint; - - event RenewKeyPurchase(address indexed owner, uint newExpiration); - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable onlyIfAlive notSoldOut { - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Assign the key - Key storage toKey = keyByOwner[_recipient]; - uint idTo = toKey.tokenId; - uint newTimeStamp; - - if (idTo == 0) { - // Assign a new tokenId (if a new owner or previously transferred) - _assignNewTokenId(toKey); - // refresh the cached value - idTo = toKey.tokenId; - _recordOwner(_recipient, idTo); - newTimeStamp = block.timestamp + expirationDuration; - toKey.expirationTimestamp = newTimeStamp; - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - idTo - ); - } else if (toKey.expirationTimestamp > block.timestamp) { - // This is an existing owner trying to extend their key - newTimeStamp = toKey.expirationTimestamp.add(expirationDuration); - toKey.expirationTimestamp = newTimeStamp; - emit RenewKeyPurchase(_recipient, newTimeStamp); - } else { - // This is an existing owner trying to renew their expired key - // SafeAdd is not required here since expirationDuration is capped to a tiny value - // (relative to the size of a uint) - newTimeStamp = block.timestamp + expirationDuration; - toKey.expirationTimestamp = newTimeStamp; - - // reset the key Manager to 0x00 - _setKeyManagerOf(idTo, address(0)); - - emit RenewKeyPurchase(_recipient, newTimeStamp); - } - - (uint inMemoryKeyPrice, uint discount, uint tokens) = _purchasePriceFor( - _recipient, - _referrer, - _data - ); - if (discount > 0) { - unlockProtocol.recordConsumedDiscount(discount, tokens); - } - - // Record price without any tips - unlockProtocol.recordKeyPurchase(inMemoryKeyPrice, _referrer); - - // We explicitly allow for greater amounts of ETH or tokens to allow 'donations' - uint pricePaid; - if (tokenAddress != address(0)) { - pricePaid = _value; - IERC20 token = IERC20(tokenAddress); - token.safeTransferFrom(msg.sender, address(this), _value); - } else { - pricePaid = msg.value; - } - require(pricePaid >= inMemoryKeyPrice, "INSUFFICIENT_VALUE"); - - if (address(onKeyPurchaseHook) != address(0)) { - onKeyPurchaseHook.onKeyPurchase( - msg.sender, - _recipient, - _referrer, - _data, - inMemoryKeyPrice, - pricePaid - ); - } - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint minKeyPrice) { - (minKeyPrice, , ) = _purchasePriceFor(_recipient, _referrer, _data); - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - * unlockDiscount and unlockTokens are the values returned from `computeAvailableDiscountFor` - */ - function _purchasePriceFor( - address _recipient, - address _referrer, - bytes memory _data - ) - internal - view - returns (uint minKeyPrice, uint unlockDiscount, uint unlockTokens) - { - if (address(onKeyPurchaseHook) != address(0)) { - minKeyPrice = onKeyPurchaseHook.keyPurchasePrice( - msg.sender, - _recipient, - _referrer, - _data - ); - } else { - minKeyPrice = keyPrice; - } - - if (minKeyPrice > 0) { - (unlockDiscount, unlockTokens) = unlockProtocol - .computeAvailableDiscountFor(_recipient, minKeyPrice); - require(unlockDiscount <= minKeyPrice, "INVALID_DISCOUNT_FROM_UNLOCK"); - minKeyPrice -= unlockDiscount; - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/cryptography/ECDSA.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * NOTE: This call _does not revert_ if the signature is invalid, or - * if the signer is otherwise unable to be retrieved. In those scenarios, - * the zero address is returned. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover( - bytes32 hash, - bytes memory signature - ) internal pure returns (address) { - // Check the signature length - if (signature.length != 65) { - return (address(0)); - } - - // Divide the signature in r, s and v variables - bytes32 r; - bytes32 s; - uint8 v; - - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - // solhint-disable-next-line no-inline-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if ( - uint256(s) > - 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 - ) { - return address(0); - } - - if (v != 27 && v != 28) { - return address(0); - } - - // If the signature is valid (and not malleable), return the signer address - return ecrecover(hash, v, r, s); - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * replicates the behavior of the - * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] - * JSON-RPC method. - * - * See {recover}. - */ - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return - keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } -} - -// File contracts/mixins/MixinSignatures.sol - -pragma solidity 0.5.17; - -contract MixinSignatures { - /// @notice emits anytime the nonce used for off-chain approvals changes. - event NonceChanged(address indexed keyManager, uint nextAvailableNonce); - - // Stores a nonce per user to use for signed messages - mapping(address => uint) public keyManagerToNonce; - - /// @notice Validates an off-chain approval signature. - /// @dev If valid the nonce is consumed, else revert. - modifier consumeOffchainApproval( - bytes32 _hash, - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s - ) { - require( - ecrecover(ECDSA.toEthSignedMessageHash(_hash), _v, _r, _s) == _keyManager, - "INVALID_SIGNATURE" - ); - keyManagerToNonce[_keyManager]++; - emit NonceChanged(_keyManager, keyManagerToNonce[_keyManager]); - _; - } - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external { - require( - _nextAvailableNonce > keyManagerToNonce[msg.sender], - "NONCE_ALREADY_USED" - ); - keyManagerToNonce[msg.sender] = _nextAvailableNonce; - emit NonceChanged(msg.sender, _nextAvailableNonce); - } -} - -// File contracts/mixins/MixinRefunds.sol - -pragma solidity 0.5.17; - -contract MixinRefunds is - MixinLockManagerRole, - MixinSignatures, - MixinFunds, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyBasisPoints / BASIS_POINTS_DEN`. - uint public refundPenaltyBasisPoints; - - uint public freeTrialLength; - - /// @notice The typehash per the EIP-712 standard - /// @dev This can be computed in JS instead of read from the contract - bytes32 private constant CANCEL_TYPEHASH = - keccak256("cancelAndRefundFor(address _keyOwner)"); - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - function _initializeMixinRefunds() internal { - // default to 10% - refundPenaltyBasisPoints = 1000; - } - - /** - * @dev Invoked by the lock owner to destroy the user's ket and perform a refund and cancellation - * of the key - */ - function expireAndRefundFor( - address _keyOwner, - uint amount - ) external onlyLockManager hasValidKey(_keyOwner) { - _cancelAndRefund(_keyOwner, amount); - } - - /** - * @dev Destroys the key and sends a refund based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund( - uint _tokenId - ) external onlyKeyManagerOrApproved(_tokenId) { - address keyOwner = ownerOf(_tokenId); - uint refund = _getCancelAndRefundValue(keyOwner); - - _cancelAndRefund(keyOwner, refund); - } - - /** - * @dev Cancels a key managed by a different user and sends the funds to the msg.sender. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyOwner - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) - external - consumeOffchainApproval( - getCancelAndRefundApprovalHash(_keyManager, msg.sender), - _keyManager, - _v, - _r, - _s - ) - { - address keyOwner = ownerOf(_tokenId); - uint refund = _getCancelAndRefundValue(keyOwner); - _cancelAndRefund(keyOwner, refund); - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external onlyLockManager { - emit RefundPenaltyChanged(_freeTrialLength, _refundPenaltyBasisPoints); - - freeTrialLength = _freeTrialLength; - refundPenaltyBasisPoints = _refundPenaltyBasisPoints; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_keyOwner); - } - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) public view returns (bytes32 approvalHash) { - return - keccak256( - abi.encodePacked( - // Approval is specific to this Lock - address(this), - // The specific function the signer is approving - CANCEL_TYPEHASH, - // Approval enables only one cancel call - keyManagerToNonce[_keyManager], - // Approval allows only one account to broadcast the tx - _txSender - ) - ); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address _keyOwner, uint refund) internal { - Key storage key = keyByOwner[_keyOwner]; - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(tokenAddress, _keyOwner, refund); - } - - // inform the hook if there is one registered - if (address(onKeyCancelHook) != address(0)) { - onKeyCancelHook.onKeyCancel(msg.sender, _keyOwner, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _keyOwner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _keyOwner - ) private view hasValidKey(_keyOwner) returns (uint refund) { - Key storage key = keyByOwner[_keyOwner]; - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining + freeTrialLength >= expirationDuration) { - refund = keyPrice; - } else { - // Math: using safeMul in case keyPrice or timeRemaining is very large - refund = keyPrice.mul(timeRemaining) / expirationDuration; - } - - // Apply the penalty if this is not a free trial - if ( - freeTrialLength == 0 || - timeRemaining + freeTrialLength < expirationDuration - ) { - uint penalty = keyPrice.mul(refundPenaltyBasisPoints) / BASIS_POINTS_DEN; - if (refund > penalty) { - // Math: safeSub is not required since the if confirms this won't underflow - refund -= penalty; - } else { - refund = 0; - } - } - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Receiver.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -contract IERC721Receiver { - /** - * @notice Handle the receipt of an NFT - * @dev The ERC721 smart contract calls this function on the recipient - * after a {IERC721-safeTransferFrom}. This function MUST return the function selector, - * otherwise the caller will revert the transaction. The selector to be - * returned can be obtained as `this.onERC721Received.selector`. This - * function MAY throw to revert and reject the transfer. - * Note: the ERC721 contract address is always the message sender. - * @param operator The address which called `safeTransferFrom` function - * @param from The address which previously owned the token - * @param tokenId The NFT identifier which is being transferred - * @param data Additional data with no specified format - * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes memory data - ) public returns (bytes4); -} - -// File contracts/mixins/MixinTransfer.sol - -pragma solidity 0.5.17; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is - MixinLockManagerRole, - MixinFunds, - MixinLockCore, - MixinKeys -{ - using SafeMath for uint; - using Address for address; - - event TransferFeeChanged(uint transferFeeBasisPoints); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeBasisPoints / BASIS_POINTS_DEN`. - uint public transferFeeBasisPoints; - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - */ - function shareKey( - address _to, - uint _tokenId, - uint _timeShared - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_to != address(0), "INVALID_ADDRESS"); - address keyOwner = _ownerOf[_tokenId]; - require(getHasValidKey(keyOwner), "KEY_NOT_VALID"); - Key storage fromKey = keyByOwner[keyOwner]; - Key storage toKey = keyByOwner[_to]; - uint idTo = toKey.tokenId; - uint time; - // get the remaining time for the origin key - uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; - // get the transfer fee based on amount of time wanted share - uint fee = getTransferFee(keyOwner, _timeShared); - uint timePlusFee = _timeShared.add(fee); - - // ensure that we don't try to share too much - if (timePlusFee < timeRemaining) { - // now we can safely set the time - time = _timeShared; - // deduct time from parent key, including transfer fee - _timeMachine(_tokenId, timePlusFee, false); - } else { - // we have to recalculate the fee here - fee = getTransferFee(keyOwner, timeRemaining); - time = timeRemaining - fee; - fromKey.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(_tokenId); - } - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(_to, idTo); - emit Transfer( - address(0), // This is a creation or time-sharing - _to, - idTo - ); - } else if (toKey.expirationTimestamp <= block.timestamp) { - // reset the key Manager for expired keys - _setKeyManagerOf(idTo, address(0)); - } - - // add time to new key - _timeMachine(idTo, time, true); - // trigger event - emit Transfer(keyOwner, _to, idTo); - - require( - _checkOnERC721Received(keyOwner, _to, _tokenId, ""), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) public onlyIfAlive hasValidKey(_from) onlyKeyManagerOrApproved(_tokenId) { - require(isKeyOwner(_tokenId, _from), "TRANSFER_FROM: NOT_KEY_OWNER"); - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_recipient != address(0), "INVALID_ADDRESS"); - uint fee = getTransferFee(_from, 0); - - Key storage fromKey = keyByOwner[_from]; - Key storage toKey = keyByOwner[_recipient]; - - uint previousExpiration = toKey.expirationTimestamp; - // subtract the fee from the senders key before the transfer - _timeMachine(_tokenId, fee, false); - - if (toKey.tokenId == 0) { - toKey.tokenId = _tokenId; - _recordOwner(_recipient, _tokenId); - // Clear any previous approvals - _clearApproval(_tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the sender's key expiration - // An expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = _tokenId; - - // Reset the key Manager to the key owner - _setKeyManagerOf(_tokenId, address(0)); - - _recordOwner(_recipient, _tokenId); - } else { - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = fromKey.expirationTimestamp.add( - previousExpiration - block.timestamp - ); - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) public returns (bool success) { - uint maxTimeToSend = _value * expirationDuration; - Key storage fromKey = keyByOwner[msg.sender]; - uint timeRemaining = fromKey.expirationTimestamp.sub(block.timestamp); - if (maxTimeToSend < timeRemaining) { - shareKey(_to, fromKey.tokenId, maxTimeToSend); - } else { - transferFrom(msg.sender, _to, fromKey.tokenId); - } - - // Errors will cause a revert - return true; - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom(address _from, address _to, uint _tokenId) public { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) public { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeBasisPoints - ) external onlyLockManager { - emit TransferFeeChanged(_transferFeeBasisPoints); - transferFeeBasisPoints = _transferFeeBasisPoints; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _keyOwner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) public view returns (uint) { - if (!getHasValidKey(_keyOwner)) { - return 0; - } else { - Key storage key = keyByOwner[_keyOwner]; - uint timeToTransfer; - uint fee; - // Math: safeSub is not required since `hasValidKey` confirms timeToTransfer is positive - // this is for standard key transfers - if (_time == 0) { - timeToTransfer = key.expirationTimestamp - block.timestamp; - } else { - timeToTransfer = _time; - } - fee = timeToTransfer.mul(transferFeeBasisPoints) / BASIS_POINTS_DEN; - return fee; - } - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721Receiver(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } -} - -// File contracts/PublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - IPublicLock, - Initializable, - ERC165, - MixinLockManagerRole, - MixinKeyGranterRole, - MixinSignatures, - MixinFunds, - MixinDisable, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinERC721Enumerable, - MixinGrantKeys, - MixinPurchase, - MixinTransfer, - MixinRefunds -{ - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName - ) public initializer { - MixinFunds._initializeMixinFunds(_tokenAddress); - MixinDisable._initializeMixinDisable(); - MixinLockCore._initializeMixinLockCore( - _lockCreator, - _expirationDuration, - _keyPrice, - _maxNumberOfKeys - ); - MixinLockMetadata._initializeMixinLockMetadata(_lockName); - MixinERC721Enumerable._initializeMixinERC721Enumerable(); - MixinRefunds._initializeMixinRefunds(); - MixinLockManagerRole._initializeMixinLockManagerRole(_lockCreator); - MixinKeyGranterRole._initializeMixinKeyGranterRole(_lockCreator); - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - } - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable {} -} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol deleted file mode 100644 index 638322f5f0d..00000000000 --- a/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol +++ /dev/null @@ -1,3702 +0,0 @@ -// Sources flattened with hardhat v2.8.0 https://hardhat.org -// SPDX-License-Identifier: MIT - -// File contracts/interfaces/IPublicLock.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @title The PublicLock Interface - */ - -interface IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - // roles - function DEFAULT_ADMIN_ROLE() external pure returns (bytes32 role); - - function KEY_GRANTER_ROLE() external pure returns (bytes32 role); - - function LOCK_MANAGER_ROLE() external pure returns (bytes32 role); - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() external pure returns (uint16); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function to change the default duration of each key in the lock - * @notice keys previously bought are unaffected by this change (i.e. - * existing keys timestamps are not recalculated/updated) - * @param _newExpirationDuration the new amount of time for each key purchased - * or zero (0) for a non-expiring key - */ - function setExpirationDuration(uint _newExpirationDuration) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook, - address _onValidKeyHook, - address _onTokenURIHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _keyManager optional address to grant managing rights to a specific address on creation - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - address _keyManager, - bytes calldata _data - ) external payable; - - /** - * @param _gasRefundValue price in wei or token in smallest price unit - * @dev Set the value to be refunded to the sender on purchase - */ - function setGasRefundValue(uint256 _gasRefundValue) external; - - /** - * _gasRefundValue price in wei or token in smallest price unit - * @dev Returns the value/rpice to be refunded to the sender on purchase - */ - function gasRefundValue() external view returns (uint256 _gasRefundValue); - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function onValidKeyHook() external view returns (bool); - - function onTokenURIHook() external view returns (string memory); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - /** - * @dev Change the maximum number of keys the lock can edit - * @param _maxNumberOfKeys uint the maximum number of keys - */ - function setMaxNumberOfKeys(uint _maxNumberOfKeys) external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) external view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - function approve(address to, uint256 tokenId) external; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return operator The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint256 _tokenId - ) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address _owner, - address operator - ) external view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes calldata data - ) external; - - function totalSupply() external view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) external view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) external view returns (uint256); - - /** - * Innherited from Open Zeppelin AccessControl.sol - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - function grantRole(bytes32 role, address account) external; - - function revokeRole(bytes32 role, address account) external; - - function renounceRole(bytes32 role, address account) external; - - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} - -// File @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (utils/Address.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Collection of functions related to the address type - */ -library AddressUpgradeable { - /** - * @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 - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - assembly { - size := extcodesize(account) - } - return size > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data - ) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return - functionCallWithValue( - target, - data, - value, - "Address: low-level call with value failed" - ); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require( - address(this).balance >= value, - "Address: insufficient balance for call" - ); - require(isContract(target), "Address: call to non-contract"); - - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data - ) internal view returns (bytes memory) { - return - functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// File @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) - -pragma solidity ^0.8.0; - -/** - * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed - * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an - * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer - * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. - * - * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as - * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. - * - * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure - * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. - * - * [CAUTION] - * ==== - * Avoid leaving a contract uninitialized. - * - * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation - * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the - * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: - * - * [.hljs-theme-light.nopadding] - * ``` - * /// @custom:oz-upgrades-unsafe-allow constructor - * constructor() initializer {} - * ``` - * ==== - */ -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Modifier to protect an initializer function from being invoked twice. - */ - modifier initializer() { - // If the contract is initializing we ignore whether _initialized is set in order to support multiple - // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the - // contract may have been reentered. - require( - _initializing ? _isConstructor() : !_initialized, - "Initializable: contract is already initialized" - ); - - bool isTopLevelCall = !_initializing; - if (isTopLevelCall) { - _initializing = true; - _initialized = true; - } - - _; - - if (isTopLevelCall) { - _initializing = false; - } - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} modifier, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - function _isConstructor() private view returns (bool) { - return !AddressUpgradeable.isContract(address(this)); - } -} - -// File @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol@v4.4.2 -// 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 IERC165Upgradeable { - /** - * @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); -} - -// File @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - -pragma solidity ^0.8.0; - -/** - * @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 ERC165Upgradeable is Initializable, IERC165Upgradeable { - function __ERC165_init() internal onlyInitializing { - __ERC165_init_unchained(); - } - - function __ERC165_init_unchained() internal onlyInitializing {} - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual override returns (bool) { - return interfaceId == type(IERC165Upgradeable).interfaceId; - } - - uint256[50] private __gap; -} - -// File @openzeppelin/contracts-upgradeable/utils/introspection/ERC165StorageUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Storage based implementation of the {IERC165} interface. - * - * Contracts may inherit from this and call {_registerInterface} to declare - * their support of an interface. - */ -abstract contract ERC165StorageUpgradeable is Initializable, ERC165Upgradeable { - function __ERC165Storage_init() internal onlyInitializing { - __ERC165_init_unchained(); - __ERC165Storage_init_unchained(); - } - - function __ERC165Storage_init_unchained() internal onlyInitializing {} - - /** - * @dev Mapping of interface ids to whether or not it's supported. - */ - mapping(bytes4 => bool) private _supportedInterfaces; - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual override returns (bool) { - return - super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId]; - } - - /** - * @dev Registers the contract as an implementer of the interface defined by - * `interfaceId`. Support of the actual ERC165 interface is automatic and - * registering its interface id is not required. - * - * See {IERC165-supportsInterface}. - * - * Requirements: - * - * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). - */ - function _registerInterface(bytes4 interfaceId) internal virtual { - require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); - _supportedInterfaces[interfaceId] = true; - } - - uint256[49] private __gap; -} - -// File @openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20Upgradeable { - /** - * @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 `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, 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 `sender` to `recipient` 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 sender, - address recipient, - uint256 amount - ) external returns (bool); - - /** - * @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); -} - -// File @openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) - -pragma solidity ^0.8.0; - -/** - * @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 SafeERC20Upgradeable { - using AddressUpgradeable for address; - - function safeTransfer( - IERC20Upgradeable token, - address to, - uint256 value - ) internal { - _callOptionalReturn( - token, - abi.encodeWithSelector(token.transfer.selector, to, value) - ); - } - - function safeTransferFrom( - IERC20Upgradeable 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( - IERC20Upgradeable 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( - IERC20Upgradeable 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( - IERC20Upgradeable 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) - ); - } - } - - /** - * @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( - IERC20Upgradeable 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" - ); - } - } -} - -// File contracts/mixins/MixinFunds.sol -pragma solidity ^0.8.0; - -/** - * @title An implementation of the money related functions. - * @author HardlyDifficult (unlock-protocol.com) - */ -contract MixinFunds { - using AddressUpgradeable for address payable; - using SafeERC20Upgradeable for IERC20Upgradeable; - - /** - * The token-type that this Lock is priced in. If 0, then use ETH, else this is - * a ERC20 token address. - */ - address public tokenAddress; - - function _initializeMixinFunds(address _tokenAddress) internal { - tokenAddress = _tokenAddress; - require( - _tokenAddress == address(0) || - IERC20Upgradeable(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - } - - /** - * Transfers funds from the contract to the account provided. - * - * Security: be wary of re-entrancy when calling this function. - */ - function _transfer( - address _tokenAddress, - address payable _to, - uint _amount - ) internal { - if (_amount > 0) { - if (_tokenAddress == address(0)) { - // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/ - _to.sendValue(_amount); - } else { - IERC20Upgradeable token = IERC20Upgradeable(_tokenAddress); - token.safeTransfer(_to, _amount); - } - } - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File @openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - -pragma solidity ^0.8.0; - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControlUpgradeable { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged( - bytes32 indexed role, - bytes32 indexed previousAdminRole, - bytes32 indexed newAdminRole - ); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted( - bytes32 indexed role, - address indexed account, - address indexed sender - ); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked( - bytes32 indexed role, - address indexed account, - address indexed sender - ); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} - -// File @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol@v4.4.2 -// 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 ContextUpgradeable is Initializable { - function __Context_init() internal onlyInitializing { - __Context_init_unchained(); - } - - function __Context_init_unchained() internal onlyInitializing {} - - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } - - uint256[50] private __gap; -} - -// File @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) - -pragma solidity ^0.8.0; - -/** - * @dev String operations. - */ -library StringsUpgradeable { - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - // Inspired by OraclizeAPI's implementation - MIT licence - // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol - - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - if (value == 0) { - return "0x00"; - } - uint256 temp = value; - uint256 length = 0; - while (temp != 0) { - length++; - temp >>= 8; - } - return toHexString(value, length); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString( - uint256 value, - uint256 length - ) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } -} - -// File @openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControlUpgradeable is - Initializable, - ContextUpgradeable, - IAccessControlUpgradeable, - ERC165Upgradeable -{ - function __AccessControl_init() internal onlyInitializing { - __Context_init_unchained(); - __ERC165_init_unchained(); - __AccessControl_init_unchained(); - } - - function __AccessControl_init_unchained() internal onlyInitializing {} - - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role, _msgSender()); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual override returns (bool) { - return - interfaceId == type(IAccessControlUpgradeable).interfaceId || - super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole( - bytes32 role, - address account - ) public view override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - StringsUpgradeable.toHexString(uint160(account), 20), - " is missing role ", - StringsUpgradeable.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole( - bytes32 role, - address account - ) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole( - bytes32 role, - address account - ) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require( - account == _msgSender(), - "AccessControl: can only renounce roles for self" - ); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } - - uint256[49] private __gap; -} - -// File contracts/mixins/MixinRoles.sol -pragma solidity ^0.8.0; - -// This contract mostly follows the pattern established by openzeppelin in -// openzeppelin/contracts-ethereum-package/contracts/access/roles - -contract MixinRoles is AccessControlUpgradeable { - // roles - bytes32 public constant LOCK_MANAGER_ROLE = keccak256("LOCK_MANAGER"); - bytes32 public constant KEY_GRANTER_ROLE = keccak256("KEY_GRANTER"); - - // events - event LockManagerAdded(address indexed account); - event LockManagerRemoved(address indexed account); - event KeyGranterAdded(address indexed account); - event KeyGranterRemoved(address indexed account); - - // initializer - function _initializeMixinRoles(address sender) internal { - // for admin mamangers to add other lock admins - _setRoleAdmin(LOCK_MANAGER_ROLE, LOCK_MANAGER_ROLE); - - // for lock managers to add/remove key granters - _setRoleAdmin(KEY_GRANTER_ROLE, LOCK_MANAGER_ROLE); - - if (!isLockManager(sender)) { - _setupRole(LOCK_MANAGER_ROLE, sender); - } - if (!isKeyGranter(sender)) { - _setupRole(KEY_GRANTER_ROLE, sender); - } - } - - // modifiers - modifier onlyLockManager() { - require( - hasRole(LOCK_MANAGER_ROLE, msg.sender), - "MixinRoles: caller does not have the LockManager role" - ); - _; - } - - modifier onlyKeyGranterOrManager() { - require( - isKeyGranter(msg.sender) || isLockManager(msg.sender), - "MixinRoles: caller does not have the KeyGranter or LockManager role" - ); - _; - } - - // lock manager functions - function isLockManager(address account) public view returns (bool) { - return hasRole(LOCK_MANAGER_ROLE, account); - } - - function addLockManager(address account) public onlyLockManager { - grantRole(LOCK_MANAGER_ROLE, account); - emit LockManagerAdded(account); - } - - function renounceLockManager() public { - renounceRole(LOCK_MANAGER_ROLE, msg.sender); - emit LockManagerRemoved(msg.sender); - } - - // key granter functions - function isKeyGranter(address account) public view returns (bool) { - return hasRole(KEY_GRANTER_ROLE, account); - } - - function addKeyGranter(address account) public onlyLockManager { - grantRole(KEY_GRANTER_ROLE, account); - emit KeyGranterAdded(account); - } - - function revokeKeyGranter(address _granter) public onlyLockManager { - revokeRole(KEY_GRANTER_ROLE, _granter); - emit KeyGranterRemoved(_granter); - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinDisable.sol -pragma solidity ^0.8.0; - -/** - * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) - * and then destroy it. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinDisable is MixinRoles, MixinFunds { - // Used to disable payable functions when deprecating an old lock - bool public isAlive; - - event Disable(); - - function _initializeMixinDisable() internal { - isAlive = true; - } - - // Only allow usage when contract is Alive - modifier onlyIfAlive() { - require(isAlive, "LOCK_DEPRECATED"); - _; - } - - /** - * @dev Used to disable lock before migrating keys and/or destroying contract - */ - function disableLock() external onlyLockManager onlyIfAlive { - emit Disable(); - isAlive = false; - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/interfaces/IUnlock.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev deploy a ProxyAdmin contract used to upgrade locks - */ - function initializeProxyAdmin() external; - - // store contract proxy admin address - function proxyAdminAddress() external view; - - /** - * @notice Create lock (legacy) - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _expirationDuration the duration of the lock (pass 0 for unlimited duration) - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _keyPrice the price of each key - * @param _maxNumberOfKeys the maximum nimbers of keys to be edited - * @param _lockName the name of the lock - * param _salt [deprec] -- kept only for backwards copatibility - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - * @dev internally call `createUpgradeableLock` - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 // _salt - ) external returns (address); - - /** - * @notice Create lock (default) - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param data bytes containing the call to initialize the lock template - * @dev this call is passed as encoded function - for instance: - * bytes memory data = abi.encodeWithSignature( - * 'initialize(address,uint256,address,uint256,uint256,string)', - * msg.sender, - * _expirationDuration, - * _tokenAddress, - * _keyPrice, - * _maxNumberOfKeys, - * _lockName - * ); - * @return address of the create lock - */ - function createUpgradeableLock(bytes memory data) external returns (address); - - /** - * @notice Upgrade a lock to a specific version - * @dev only available for publicLockVersion > 10 (proxyAdmin /required) - * @param lockAddress the existing lock address - * @param version the version number you are targeting - * Likely implemented with OpenZeppelin TransparentProxy contract - */ - function upgradeLock( - address payable lockAddress, - uint16 version - ) external returns (address); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. - * @dev [DEPRECATED] Kept for backwards compatibility - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. - * @dev [DEPRECATED] Kept for backwards compatibility - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - // Function to read the chainId field. - function chainId() external view returns (uint); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI, - uint _chainId - ) external; - - /** - * @notice Add a PublicLock template to be used for future calls to `createLock`. - * @dev This is used to upgrade conytract per version number - */ - function addLockTemplate(address impl, uint16 version) external; - - // match lock templates addresses with version numbers - function publicLockImpls(uint16 _version) external view; - - // match version numbers with lock templates addresses - function publicLockVersions(address _impl) external view; - - // the latest existing lock template version - function publicLockLatestVersion() external view; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - // Initialize the Ownable contract, granting contract ownership to the specified sender - function __initializeOwnable(address sender) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File contracts/interfaces/hooks/ILockKeyCancelHook.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @notice Functions to be implemented by a keyCancelHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyCancelHook { - /** - * @notice If the lock owner has registered an implementer - * then this hook is called with every key cancel. - * @param operator the msg.sender issuing the cancel - * @param to the account which had the key canceled - * @param refund the amount sent to the `to` account (ETH or a ERC-20 token) - */ - function onKeyCancel(address operator, address to, uint256 refund) external; -} - -// File contracts/interfaces/hooks/ILockKeyPurchaseHook.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @notice Functions to be implemented by a keyPurchaseHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockKeyPurchaseHook { - /** - * @notice Used to determine the purchase price before issueing a transaction. - * This allows the hook to offer a discount on purchases. - * This may revert to prevent a purchase. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @return minKeyPrice the minimum value/price required to purchase a key with these settings - * @dev the lock's address is the `msg.sender` when this function is called via - * the lock's `purchasePriceFor` function - */ - function keyPurchasePrice( - address from, - address recipient, - address referrer, - bytes calldata data - ) external view returns (uint minKeyPrice); - - /** - * @notice If the lock owner has registered an implementer then this hook - * is called with every key sold. - * @param from the msg.sender making the purchase - * @param recipient the account which will be granted a key - * @param referrer the account which referred this key sale - * @param data arbitrary data populated by the front-end which initiated the sale - * @param minKeyPrice the price including any discount granted from calling this - * hook's `keyPurchasePrice` function - * @param pricePaid the value/pricePaid included with the purchase transaction - * @dev the lock's address is the `msg.sender` when this function is called - */ - function onKeyPurchase( - address from, - address recipient, - address referrer, - bytes calldata data, - uint minKeyPrice, - uint pricePaid - ) external; -} - -// File contracts/interfaces/hooks/ILockValidKeyHook.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @notice Functions to be implemented by a hasValidKey Hook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockValidKeyHook { - /** - * @notice If the lock owner has registered an implementer then this hook - * is called every time balanceOf is called - * @param lockAddress the address of the current lock - * @param keyOwner the potential owner of the key for which we are retrieving the `balanceof` - * @param expirationTimestamp the key expiration timestamp - */ - function hasValidKey( - address lockAddress, - address keyOwner, - uint256 expirationTimestamp, - bool isValidKey - ) external view returns (bool); -} - -// File contracts/interfaces/hooks/ILockTokenURIHook.sol -pragma solidity >=0.5.17 <0.9.0; - -/** - * @notice Functions to be implemented by a tokenURIHook. - * @dev Lock hooks are configured by calling `setEventHooks` on the lock. - */ -interface ILockTokenURIHook { - /** - * @notice If the lock owner has registered an implementer - * then this hook is called every time `tokenURI()` is called - * @param lockAddress the address of the lock - * @param operator the msg.sender issuing the call - * @param owner the owner of the key for which we are retrieving the `tokenUri` - * @param keyId the id (tokenId) of the key (if applicable) - * @param expirationTimestamp the key expiration timestamp - * @return the tokenURI - */ - function tokenURI( - address lockAddress, - address operator, - address owner, - uint256 keyId, - uint expirationTimestamp - ) external view returns (string memory); -} - -// File contracts/mixins/MixinLockCore.sol -pragma solidity ^0.8.0; - -// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; - -/** - * @title Mixin for core lock data and functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockCore is MixinRoles, MixinFunds, MixinDisable { - using AddressUpgradeable for address; - - event Withdrawal( - address indexed sender, - address indexed tokenAddress, - address indexed beneficiary, - uint amount - ); - - event PricingChanged( - uint oldKeyPrice, - uint keyPrice, - address oldTokenAddress, - address tokenAddress - ); - - /** - * @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 - ); - - // Unlock Protocol address - // TODO: should we make that private/internal? - IUnlock public unlockProtocol; - - // Duration in seconds for which the keys are valid, after creation - // should we take a smaller type use less gas? - uint public expirationDuration; - - // price in wei of the next key - // TODO: allow support for a keyPriceCalculator which could set prices dynamically - uint public keyPrice; - - // Max number of keys sold if the keyReleaseMechanism is public - uint public maxNumberOfKeys; - - // A count of how many new key purchases there have been - uint internal _totalSupply; - - // The account which will receive funds on withdrawal - address payable public beneficiary; - - // The denominator component for values specified in basis points. - uint internal constant BASIS_POINTS_DEN = 10000; - - ILockKeyPurchaseHook public onKeyPurchaseHook; - ILockKeyCancelHook public onKeyCancelHook; - ILockValidKeyHook public onValidKeyHook; - ILockTokenURIHook public onTokenURIHook; - - // Ensure that the Lock has not sold all of its keys. - modifier notSoldOut() { - require(maxNumberOfKeys > _totalSupply, "LOCK_SOLD_OUT"); - _; - } - - modifier onlyLockManagerOrBeneficiary() { - require( - isLockManager(msg.sender) || msg.sender == beneficiary, - "ONLY_LOCK_MANAGER_OR_BENEFICIARY" - ); - _; - } - - function _initializeMixinLockCore( - address payable _beneficiary, - uint _expirationDuration, - uint _keyPrice, - uint _maxNumberOfKeys - ) internal { - require( - _expirationDuration <= 100 * 365 * 24 * 60 * 60, - "MAX_EXPIRATION_100_YEARS" - ); - unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. - beneficiary = _beneficiary; - expirationDuration = _expirationDuration == 0 - ? type(uint).max - : _expirationDuration; - keyPrice = _keyPrice; - maxNumberOfKeys = _maxNumberOfKeys; - } - - // The version number of the current implementation on this network - function publicLockVersion() public pure returns (uint16) { - return 9; - } - - /** - * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * - * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw( - address _tokenAddress, - uint _amount - ) external onlyLockManagerOrBeneficiary { - // get balance - uint balance; - if (_tokenAddress == address(0)) { - balance = address(this).balance; - } else { - balance = IERC20Upgradeable(_tokenAddress).balanceOf(address(this)); - } - - uint amount; - if (_amount == 0 || _amount > balance) { - require(balance > 0, "NOT_ENOUGH_FUNDS"); - amount = balance; - } else { - amount = _amount; - } - - emit Withdrawal(msg.sender, _tokenAddress, beneficiary, amount); - // Security: re-entrancy not a risk as this is the last line of an external function - _transfer(_tokenAddress, beneficiary, amount); - } - - /** - * A function which lets the owner of the lock change the pricing for future purchases. - * This consists of 2 parts: The token address and the price in the given token. - * In order to set the token to ETH, use 0 for the token Address. - */ - function updateKeyPricing( - uint _keyPrice, - address _tokenAddress - ) external onlyLockManager onlyIfAlive { - uint oldKeyPrice = keyPrice; - address oldTokenAddress = tokenAddress; - require( - _tokenAddress == address(0) || - IERC20Upgradeable(_tokenAddress).totalSupply() > 0, - "INVALID_TOKEN" - ); - keyPrice = _keyPrice; - tokenAddress = _tokenAddress; - emit PricingChanged(oldKeyPrice, keyPrice, oldTokenAddress, tokenAddress); - } - - /** - * A function which lets the owner of the lock update the beneficiary account, - * which receives funds on withdrawal. - */ - function updateBeneficiary( - address payable _beneficiary - ) external onlyLockManagerOrBeneficiary { - require(_beneficiary != address(0), "INVALID_ADDRESS"); - beneficiary = _beneficiary; - } - - /** - * @notice Allows a lock manager to add or remove an event hook - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook, - address _onValidKeyHook, - address _onTokenURIHook - ) external onlyLockManager { - require( - _onKeyPurchaseHook == address(0) || _onKeyPurchaseHook.isContract(), - "INVALID_ON_KEY_SOLD_HOOK" - ); - require( - _onKeyCancelHook == address(0) || _onKeyCancelHook.isContract(), - "INVALID_ON_KEY_CANCEL_HOOK" - ); - require( - _onValidKeyHook == address(0) || _onValidKeyHook.isContract(), - "INVALID_ON_VALID_KEY_HOOK" - ); - require( - _onTokenURIHook == address(0) || _onTokenURIHook.isContract(), - "INVALID_ON_TOKEN_URI_HOOK" - ); - onKeyPurchaseHook = ILockKeyPurchaseHook(_onKeyPurchaseHook); - onKeyCancelHook = ILockKeyCancelHook(_onKeyCancelHook); - onTokenURIHook = ILockTokenURIHook(_onTokenURIHook); - onValidKeyHook = ILockValidKeyHook(_onValidKeyHook); - } - - function totalSupply() public view returns (uint256) { - return _totalSupply; - } - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) public onlyLockManagerOrBeneficiary returns (bool) { - return IERC20Upgradeable(tokenAddress).approve(_spender, _amount); - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinKeys.sol -pragma solidity ^0.8.0; - -/** - * @title Mixin for managing `Key` data, as well as the * Approval related functions needed to meet the ERC721 - * standard. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinKeys is MixinLockCore { - // The struct for a key - struct Key { - uint tokenId; - uint expirationTimestamp; - } - - // Emitted when the Lock owner expires a user's Key - event ExpireKey(uint indexed tokenId); - - // Emitted when the expiration of a key is modified - event ExpirationChanged(uint indexed _tokenId, uint _amount, bool _timeAdded); - - event KeyManagerChanged(uint indexed _tokenId, address indexed _newManager); - - // Keys - // Each owner can have at most exactly one key - // TODO: could we use public here? (this could be confusing though because it getter will - // return 0 values when missing a key) - mapping(address => Key) internal keyByOwner; - - // Each tokenId can have at most exactly one owner at a time. - // Returns 0 if the token does not exist - // TODO: once we decouple tokenId from owner address (incl in js), then we can consider - // merging this with totalSupply into an array instead. - mapping(uint => address) internal _ownerOf; - - // Keep track of the total number of unique owners for this lock (both expired and valid). - // This may be larger than totalSupply - uint public numberOfOwners; - - // A given key has both an owner and a manager. - // If keyManager == address(0) then the key owner is also the manager - // Each key can have at most 1 keyManager. - mapping(uint => address) public keyManagerOf; - - // Keeping track of approved transfers - // This is a mapping of addresses which have approved - // the transfer of a key to another address where their key can be transferred - // Note: the approver may actually NOT have a key... and there can only - // be a single approved address - mapping(uint => address) private approved; - - // Keeping track of approved operators for a given Key manager. - // This approves a given operator for all keys managed by the calling "keyManager" - // The caller may not currently be the keyManager for ANY keys. - // These approvals are never reset/revoked automatically, unlike "approved", - // which is reset on transfer. - mapping(address => mapping(address => bool)) - private managerToOperatorApproved; - - // Ensure that the caller is the keyManager of the key - // or that the caller has been approved - // for ownership of that key - modifier onlyKeyManagerOrApproved(uint _tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || - _isApproved(_tokenId, msg.sender) || - isApprovedForAll(_ownerOf[_tokenId], msg.sender), - "ONLY_KEY_MANAGER_OR_APPROVED" - ); - _; - } - - // Ensures that an owner owns or has owned a key in the past - modifier ownsOrHasOwnedKey(address _keyOwner) { - require( - keyByOwner[_keyOwner].expirationTimestamp > 0, - "HAS_NEVER_OWNED_KEY" - ); - _; - } - - // Ensures that an owner has a valid key - modifier hasValidKey(address _user) { - require(getHasValidKey(_user), "KEY_NOT_VALID"); - _; - } - - // Ensures that a key has an owner - modifier isKey(uint _tokenId) { - require(_ownerOf[_tokenId] != address(0), "NO_SUCH_KEY"); - _; - } - - // Ensure that the caller owns the key - modifier onlyKeyOwner(uint _tokenId) { - require(ownerOf(_tokenId) == msg.sender, "ONLY_KEY_OWNER"); - _; - } - - /** - * In the specific case of a Lock, each owner can own only at most 1 key. - * @return The number of NFTs owned by `_keyOwner`, either 0 or 1. - */ - function balanceOf(address _keyOwner) public view returns (uint) { - require(_keyOwner != address(0), "INVALID_ADDRESS"); - return getHasValidKey(_keyOwner) ? 1 : 0; - } - - /** - * Checks if the user has a non-expired key. - */ - function getHasValidKey( - address _keyOwner - ) public view returns (bool isValid) { - isValid = keyByOwner[_keyOwner].expirationTimestamp > block.timestamp; - - // use hook if it exists - if (address(onValidKeyHook) != address(0)) { - isValid = onValidKeyHook.hasValidKey( - address(this), - _keyOwner, - keyByOwner[_keyOwner].expirationTimestamp, - isValid - ); - } - } - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - */ - function getTokenIdFor(address _account) public view returns (uint) { - return keyByOwner[_account].tokenId; - } - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) public view returns (uint) { - return keyByOwner[_keyOwner].expirationTimestamp; - } - - // Returns the owner of a given tokenId - function ownerOf(uint _tokenId) public view returns (address) { - return _ownerOf[_tokenId]; - } - - /** - * @notice Public function for updating transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address with the manager's rights for the given key. - * Setting _keyManager to address(0) means the keyOwner is also the keyManager - */ - function setKeyManagerOf( - uint _tokenId, - address _keyManager - ) public isKey(_tokenId) { - require( - _isKeyManager(_tokenId, msg.sender) || isLockManager(msg.sender), - "UNAUTHORIZED_KEY_MANAGER_UPDATE" - ); - _setKeyManagerOf(_tokenId, _keyManager); - } - - function _setKeyManagerOf(uint _tokenId, address _keyManager) internal { - if (keyManagerOf[_tokenId] != _keyManager) { - keyManagerOf[_tokenId] = _keyManager; - _clearApproval(_tokenId); - emit KeyManagerChanged(_tokenId, _keyManager); - } - } - - /** - * This approves _approved to get ownership of _tokenId. - * Note: that since this is used for both purchase and transfer approvals - * the approved token may not exist. - */ - function approve( - address _approved, - uint _tokenId - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require(msg.sender != _approved, "APPROVE_SELF"); - - approved[_tokenId] = _approved; - emit Approval(_ownerOf[_tokenId], _approved, _tokenId); - } - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved( - uint _tokenId - ) public view isKey(_tokenId) returns (address) { - address approvedRecipient = approved[_tokenId]; - return approvedRecipient; - } - - /** - * @dev Tells whether an operator is approved by a given keyManager - * @param _owner owner address which you want to query the approval of - * @param _operator operator address which you want to query the approval of - * @return bool whether the given operator is approved by the given owner - */ - function isApprovedForAll( - address _owner, - address _operator - ) public view returns (bool) { - uint tokenId = keyByOwner[_owner].tokenId; - address keyManager = keyManagerOf[tokenId]; - if (keyManager == address(0)) { - return managerToOperatorApproved[_owner][_operator]; - } else { - return managerToOperatorApproved[keyManager][_operator]; - } - } - - /** - * Returns true if _keyManager is the manager of the key - * identified by _tokenId - */ - function _isKeyManager( - uint _tokenId, - address _keyManager - ) internal view returns (bool) { - if ( - keyManagerOf[_tokenId] == _keyManager || - (keyManagerOf[_tokenId] == address(0) && ownerOf(_tokenId) == _keyManager) - ) { - return true; - } else { - return false; - } - } - - /** - * Assigns the key a new tokenId (from totalSupply) if it does not already have - * one assigned. - */ - function _assignNewTokenId(Key storage _key) internal { - if (_key.tokenId == 0) { - // This is a brand new owner - // We increment the tokenId counter - _totalSupply++; - // we assign the incremented `_totalSupply` as the tokenId for the new key - _key.tokenId = _totalSupply; - } - } - - /** - * Records the owner of a given tokenId - */ - function _recordOwner(address _keyOwner, uint _tokenId) internal { - // check expiration ts should be set to know if owner had previously registered a key - Key memory key = keyByOwner[_keyOwner]; - if (key.expirationTimestamp == 0) { - numberOfOwners++; - } - - // We register the owner of the tokenID - _ownerOf[_tokenId] = _keyOwner; - } - - /** - * @notice Modify the expirationTimestamp of a key - * by a given amount. - * @param _tokenId The ID of the key to modify. - * @param _deltaT The amount of time in seconds by which - * to modify the keys expirationTimestamp - * @param _addTime Choose whether to increase or decrease - * expirationTimestamp (false == decrease, true == increase) - * @dev Throws if owner does not have a valid key. - */ - function _timeMachine( - uint _tokenId, - uint256 _deltaT, - bool _addTime - ) internal { - address tokenOwner = ownerOf(_tokenId); - require(tokenOwner != address(0), "NON_EXISTENT_KEY"); - Key storage key = keyByOwner[tokenOwner]; - uint formerTimestamp = key.expirationTimestamp; - bool validKey = getHasValidKey(tokenOwner); - if (_addTime) { - if (validKey) { - key.expirationTimestamp = formerTimestamp + _deltaT; - } else { - key.expirationTimestamp = block.timestamp + _deltaT; - } - } else { - key.expirationTimestamp = formerTimestamp - _deltaT; - } - emit ExpirationChanged(_tokenId, _deltaT, _addTime); - } - - /** - * @dev Sets or unsets the approval of a given operator - * An operator is allowed to transfer all tokens of the sender on their behalf - * @param _to operator address to set the approval - * @param _approved representing the status of the approval to be set - */ - function setApprovalForAll(address _to, bool _approved) public onlyIfAlive { - require(_to != msg.sender, "APPROVE_SELF"); - managerToOperatorApproved[msg.sender][_to] = _approved; - emit ApprovalForAll(msg.sender, _to, _approved); - } - - /** - * @dev Checks if the given user is approved to transfer the tokenId. - */ - function _isApproved( - uint _tokenId, - address _user - ) internal view returns (bool) { - return approved[_tokenId] == _user; - } - - /** - * @dev Function to clear current approval of a given token ID - * @param _tokenId uint256 ID of the token to be transferred - */ - function _clearApproval(uint256 _tokenId) internal { - if (approved[_tokenId] != address(0)) { - approved[_tokenId] = address(0); - } - } - - /** - * @dev Change the maximum number of keys the lock can edit - * @param _maxNumberOfKeys uint the maximum number of keys - */ - function setMaxNumberOfKeys(uint _maxNumberOfKeys) external onlyLockManager { - require( - _maxNumberOfKeys > _totalSupply, - "maxNumberOfKeys is smaller than existing supply" - ); - maxNumberOfKeys = _maxNumberOfKeys; - } - - /** - * A function to change the default duration of each key in the lock - * @notice keys previously bought are unaffected by this change (i.e. - * existing keys timestamps are not recalculated/updated) - * @param _newExpirationDuration the new amount of time for each key purchased - * or zero (0) for a non-expiring key - */ - function setExpirationDuration( - uint _newExpirationDuration - ) external onlyLockManager { - expirationDuration = _newExpirationDuration; - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinERC721Enumerable.sol -pragma solidity ^0.8.0; - -// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; - -/** - * @title Implements the ERC-721 Enumerable extension. - */ -contract MixinERC721Enumerable is - ERC165StorageUpgradeable, - MixinLockCore, // Implements totalSupply - MixinKeys -{ - function _initializeMixinERC721Enumerable() internal { - /** - * register the supported interface to conform to ERC721Enumerable via ERC165 - * 0x780e9d63 === - * bytes4(keccak256('totalSupply()')) ^ - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ - * bytes4(keccak256('tokenByIndex(uint256)')) - */ - _registerInterface(0x780e9d63); - } - - /// @notice Enumerate valid NFTs - /// @dev Throws if `_index` >= `totalSupply()`. - /// @param _index A counter less than `totalSupply()` - /// @return The token identifier for the `_index`th NFT, - /// (sort order not specified) - function tokenByIndex(uint256 _index) public view returns (uint256) { - require(_index < _totalSupply, "OUT_OF_RANGE"); - return _index; - } - - /// @notice Enumerate NFTs assigned to an owner - /// @dev Throws if `_index` >= `balanceOf(_keyOwner)` or if - /// `_keyOwner` is the zero address, representing invalid NFTs. - /// @param _keyOwner An address where we are interested in NFTs owned by them - /// @param _index A counter less than `balanceOf(_keyOwner)` - /// @return The token identifier for the `_index`th NFT assigned to `_keyOwner`, - /// (sort order not specified) - function tokenOfOwnerByIndex( - address _keyOwner, - uint256 _index - ) public view returns (uint256) { - require( - _index < balanceOf(_keyOwner) && _keyOwner != address(0), - "ONLY_ONE_KEY_PER_OWNER" - ); - return getTokenIdFor(_keyOwner); - } - - function supportsInterface( - bytes4 interfaceId - ) - public - view - virtual - override(AccessControlUpgradeable, ERC165StorageUpgradeable) - returns (bool) - { - return super.supportsInterface(interfaceId); - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinGrantKeys.sol -pragma solidity ^0.8.0; - -/** - * @title Mixin allowing the Lock owner to grant / gift keys to users. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinGrantKeys is MixinRoles, MixinKeys { - /** - * Allows the Lock owner to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external onlyKeyGranterOrManager { - for (uint i = 0; i < _recipients.length; i++) { - address recipient = _recipients[i]; - uint expirationTimestamp = _expirationTimestamps[i]; - address keyManager = _keyManagers[i]; - - require(recipient != address(0), "INVALID_ADDRESS"); - - Key storage toKey = keyByOwner[recipient]; - require( - expirationTimestamp > toKey.expirationTimestamp, - "ALREADY_OWNS_KEY" - ); - - uint idTo = toKey.tokenId; - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(recipient, idTo); - } - // Set the key Manager - _setKeyManagerOf(idTo, keyManager); - emit KeyManagerChanged(idTo, keyManager); - - toKey.expirationTimestamp = expirationTimestamp; - // trigger event - emit Transfer( - address(0), // This is a creation. - recipient, - idTo - ); - } - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/UnlockUtils.sol -pragma solidity >=0.5.17 <0.8.5; - -// This contract provides some utility methods for use with the unlock protocol smart contracts. -// Borrowed from: -// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 - -library UnlockUtils { - function strConcat( - string memory _a, - string memory _b, - string memory _c, - string memory _d - ) internal pure returns (string memory _concatenatedString) { - return string(abi.encodePacked(_a, _b, _c, _d)); - } - - function uint2Str( - uint _i - ) internal pure returns (string memory _uintAsString) { - // make a copy of the param to avoid security/no-assign-params error - uint c = _i; - if (_i == 0) { - return "0"; - } - uint j = _i; - uint len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint k = len; - while (c != 0) { - k = k - 1; - uint8 temp = (48 + uint8(c - (c / 10) * 10)); - bytes1 b1 = bytes1(temp); - bstr[k] = b1; - c /= 10; - } - return string(bstr); - } - - function address2Str(address _addr) internal pure returns (string memory) { - bytes32 value = bytes32(uint256(uint160(_addr))); - bytes memory alphabet = "0123456789abcdef"; - bytes memory str = new bytes(42); - str[0] = "0"; - str[1] = "x"; - for (uint i = 0; i < 20; i++) { - str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; - str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; - } - return string(str); - } -} - -// File contracts/mixins/MixinLockMetadata.sol -pragma solidity ^0.8.0; - -// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; - -/** - * @title Mixin for metadata about the Lock. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinLockMetadata is - ERC165StorageUpgradeable, - MixinRoles, - MixinLockCore, - MixinKeys -{ - using UnlockUtils for uint; - using UnlockUtils for address; - using UnlockUtils for string; - - /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner - string public name; - - /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner - string private lockSymbol; - - // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. - string private baseTokenURI; - - event NewLockSymbol(string symbol); - - function _initializeMixinLockMetadata(string calldata _lockName) internal { - ERC165StorageUpgradeable.__ERC165Storage_init(); - name = _lockName; - // registering the optional erc721 metadata interface with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x5b5e139f); - } - - /** - * Allows the Lock owner to assign a descriptive name for this Lock. - */ - function updateLockName(string calldata _lockName) external onlyLockManager { - name = _lockName; - } - - /** - * Allows the Lock owner to assign a Symbol for this Lock. - */ - function updateLockSymbol( - string calldata _lockSymbol - ) external onlyLockManager { - lockSymbol = _lockSymbol; - emit NewLockSymbol(_lockSymbol); - } - - /** - * @dev Gets the token symbol - * @return string representing the token name - */ - function symbol() external view returns (string memory) { - if (bytes(lockSymbol).length == 0) { - return unlockProtocol.globalTokenSymbol(); - } else { - return lockSymbol; - } - } - - /** - * Allows the Lock owner to update the baseTokenURI for this Lock. - */ - function setBaseTokenURI( - string calldata _baseTokenURI - ) external onlyLockManager { - baseTokenURI = _baseTokenURI; - } - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @param _tokenId The iD of the token for which we want to retrieve the URI. - * If 0 is passed here, we just return the appropriate baseTokenURI. - * If a custom URI has been set we don't return the lock address. - * It may be included in the custom baseTokenURI if needed. - * @dev URIs are defined in RFC 3986. The URI may point to a JSON file - * that conforms to the "ERC721 Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - */ - function tokenURI(uint256 _tokenId) external view returns (string memory) { - string memory URI; - string memory tokenId; - string memory lockAddress = address(this).address2Str(); - string memory seperator; - - if (_tokenId != 0) { - tokenId = _tokenId.uint2Str(); - } else { - tokenId = ""; - } - - if (address(onTokenURIHook) != address(0)) { - address tokenOwner = ownerOf(_tokenId); - uint expirationTimestamp = keyExpirationTimestampFor(tokenOwner); - - return - onTokenURIHook.tokenURI( - address(this), - msg.sender, - tokenOwner, - _tokenId, - expirationTimestamp - ); - } - - if (bytes(baseTokenURI).length == 0) { - URI = unlockProtocol.globalBaseTokenURI(); - seperator = "/"; - } else { - URI = baseTokenURI; - seperator = ""; - lockAddress = ""; - } - - return URI.strConcat(lockAddress, seperator, tokenId); - } - - function supportsInterface( - bytes4 interfaceId - ) - public - view - virtual - override(AccessControlUpgradeable, ERC165StorageUpgradeable) - returns (bool) - { - return super.supportsInterface(interfaceId); - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinPurchase.sol -pragma solidity ^0.8.0; - -/** - * @title Mixin for the purchase-related functions. - * @author HardlyDifficult - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ -contract MixinPurchase is MixinFunds, MixinDisable, MixinLockCore, MixinKeys { - event RenewKeyPurchase(address indexed owner, uint newExpiration); - - event GasRefunded( - address indexed receiver, - uint refundedAmount, - address tokenAddress - ); - - event UnlockCallFailed(address indexed lockAddress, address unlockAddress); - - // default to 0 - uint256 private _gasRefundValue; - - /** - * @dev Set the value/price to be refunded to the sender on purchase - */ - - function setGasRefundValue(uint256 _refundValue) external onlyLockManager { - _gasRefundValue = _refundValue; - } - - /** - * @dev Returns value/price to be refunded to the sender on purchase - */ - function gasRefundValue() external view returns (uint256 _refundValue) { - return _gasRefundValue; - } - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _keyManager optional address to grant managing rights to a specific address on creation - * @param _data arbitrary data populated by the front-end which initiated the sale - * @notice when called for an existing and non-expired key, the `_keyManager` param will be ignored - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - address _keyManager, - bytes calldata _data - ) external payable onlyIfAlive notSoldOut { - require(_recipient != address(0), "INVALID_ADDRESS"); - - // Assign the key - Key storage toKey = keyByOwner[_recipient]; - uint idTo = toKey.tokenId; - uint newTimeStamp; - - if (idTo == 0) { - // Assign a new tokenId (if a new owner or previously transferred) - _assignNewTokenId(toKey); - // refresh the cached value - idTo = toKey.tokenId; - _recordOwner(_recipient, idTo); - // check for a non-expiring key - if (expirationDuration == type(uint).max) { - newTimeStamp = type(uint).max; - } else { - newTimeStamp = block.timestamp + expirationDuration; - } - toKey.expirationTimestamp = newTimeStamp; - - // set key manager - _setKeyManagerOf(idTo, _keyManager); - - // trigger event - emit Transfer( - address(0), // This is a creation. - _recipient, - idTo - ); - } else if (toKey.expirationTimestamp > block.timestamp) { - // prevent re-purchase of a valid non-expiring key - require( - toKey.expirationTimestamp != type(uint).max, - "A valid non-expiring key can not be purchased twice" - ); - - // This is an existing owner trying to extend their key - newTimeStamp = toKey.expirationTimestamp + expirationDuration; - toKey.expirationTimestamp = newTimeStamp; - - emit RenewKeyPurchase(_recipient, newTimeStamp); - } else { - // This is an existing owner trying to renew their expired or cancelled key - if (expirationDuration == type(uint).max) { - newTimeStamp = type(uint).max; - } else { - newTimeStamp = block.timestamp + expirationDuration; - } - toKey.expirationTimestamp = newTimeStamp; - - _setKeyManagerOf(idTo, _keyManager); - - emit RenewKeyPurchase(_recipient, newTimeStamp); - } - - uint inMemoryKeyPrice = _purchasePriceFor(_recipient, _referrer, _data); - - // make sure unlock is a contract, and we catch possible reverts - if (address(unlockProtocol).code.length > 0) { - try - unlockProtocol.recordKeyPurchase(inMemoryKeyPrice, _referrer) - {} catch { - // emit missing unlock - emit UnlockCallFailed(address(this), address(unlockProtocol)); - } - } else { - // emit missing unlock - emit UnlockCallFailed(address(this), address(unlockProtocol)); - } - - // We explicitly allow for greater amounts of ETH or tokens to allow 'donations' - uint pricePaid; - if (tokenAddress != address(0)) { - pricePaid = _value; - IERC20Upgradeable token = IERC20Upgradeable(tokenAddress); - token.transferFrom(msg.sender, address(this), pricePaid); - } else { - pricePaid = msg.value; - } - require(pricePaid >= inMemoryKeyPrice, "INSUFFICIENT_VALUE"); - - if (address(onKeyPurchaseHook) != address(0)) { - onKeyPurchaseHook.onKeyPurchase( - msg.sender, - _recipient, - _referrer, - _data, - inMemoryKeyPrice, - pricePaid - ); - } - - // refund gas - if (_gasRefundValue != 0) { - if (tokenAddress != address(0)) { - IERC20Upgradeable token = IERC20Upgradeable(tokenAddress); - token.transferFrom(address(this), msg.sender, _gasRefundValue); - } else { - (bool success, ) = msg.sender.call{value: _gasRefundValue}(""); - require(success, "Refund failed."); - } - emit GasRefunded(msg.sender, _gasRefundValue, tokenAddress); - } - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint minKeyPrice) { - minKeyPrice = _purchasePriceFor(_recipient, _referrer, _data); - } - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook - */ - function _purchasePriceFor( - address _recipient, - address _referrer, - bytes memory _data - ) internal view returns (uint minKeyPrice) { - if (address(onKeyPurchaseHook) != address(0)) { - minKeyPrice = onKeyPurchaseHook.keyPurchasePrice( - msg.sender, - _recipient, - _referrer, - _data - ); - } else { - minKeyPrice = keyPrice; - } - return minKeyPrice; - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/mixins/MixinRefunds.sol -pragma solidity ^0.8.0; - -contract MixinRefunds is MixinRoles, MixinFunds, MixinLockCore, MixinKeys { - // CancelAndRefund will return funds based on time remaining minus this penalty. - // This is calculated as `proRatedRefund * refundPenaltyBasisPoints / BASIS_POINTS_DEN`. - uint public refundPenaltyBasisPoints; - - uint public freeTrialLength; - - event CancelKey( - uint indexed tokenId, - address indexed owner, - address indexed sendTo, - uint refund - ); - - event RefundPenaltyChanged( - uint freeTrialLength, - uint refundPenaltyBasisPoints - ); - - function _initializeMixinRefunds() internal { - // default to 10% - refundPenaltyBasisPoints = 1000; - } - - /** - * @dev Invoked by the lock owner to destroy the user's ket and perform a refund and cancellation - * of the key - */ - function expireAndRefundFor( - address payable _keyOwner, - uint amount - ) external onlyLockManager hasValidKey(_keyOwner) { - _cancelAndRefund(_keyOwner, amount); - } - - /** - * @dev Destroys the key and sends a refund based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund( - uint _tokenId - ) external onlyKeyManagerOrApproved(_tokenId) { - address payable keyOwner = payable(ownerOf(_tokenId)); - uint refund = _getCancelAndRefundValue(keyOwner); - - _cancelAndRefund(keyOwner, refund); - } - - /** - * Allow the owner to change the refund penalty. - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external onlyLockManager { - emit RefundPenaltyChanged(_freeTrialLength, _refundPenaltyBasisPoints); - - freeTrialLength = _freeTrialLength; - refundPenaltyBasisPoints = _refundPenaltyBasisPoints; - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund) { - return _getCancelAndRefundValue(_keyOwner); - } - - /** - * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. - */ - function _cancelAndRefund(address payable _keyOwner, uint refund) internal { - Key storage key = keyByOwner[_keyOwner]; - - emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); - // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead - // of 0 so that we can still differentiate hasKey from hasValidKey. - key.expirationTimestamp = block.timestamp; - - if (refund > 0) { - // Security: doing this last to avoid re-entrancy concerns - _transfer(tokenAddress, _keyOwner, refund); - } - - // inform the hook if there is one registered - if (address(onKeyCancelHook) != address(0)) { - onKeyCancelHook.onKeyCancel(msg.sender, _keyOwner, refund); - } - } - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * a cancelAndRefund now. - * @param _keyOwner The owner of the key check the refund value for. - */ - function _getCancelAndRefundValue( - address _keyOwner - ) private view hasValidKey(_keyOwner) returns (uint refund) { - Key storage key = keyByOwner[_keyOwner]; - - // return entire purchased price if key is non-expiring - if (expirationDuration == type(uint).max) { - return keyPrice; - } - - // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive - uint timeRemaining = key.expirationTimestamp - block.timestamp; - if (timeRemaining + freeTrialLength >= expirationDuration) { - refund = keyPrice; - } else { - refund = (keyPrice * timeRemaining) / expirationDuration; - } - - // Apply the penalty if this is not a free trial - if ( - freeTrialLength == 0 || - timeRemaining + freeTrialLength < expirationDuration - ) { - uint penalty = (keyPrice * refundPenaltyBasisPoints) / BASIS_POINTS_DEN; - if (refund > penalty) { - refund -= penalty; - } else { - refund = 0; - } - } - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File @openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol@v4.4.2 -// OpenZeppelin Contracts v4.4.1 (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 IERC721ReceiverUpgradeable { - /** - * @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 `IERC721.onERC721Received.selector`. - */ - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes calldata data - ) external returns (bytes4); -} - -// File contracts/mixins/MixinTransfer.sol -pragma solidity ^0.8.0; - -/** - * @title Mixin for the transfer-related functions needed to meet the ERC721 - * standard. - * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply - * separates logically groupings of code to ease readability. - */ - -contract MixinTransfer is MixinRoles, MixinFunds, MixinLockCore, MixinKeys { - using AddressUpgradeable for address; - - event TransferFeeChanged(uint transferFeeBasisPoints); - - // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) - bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; - - // The fee relative to keyPrice to charge when transfering a Key to another account - // (potentially on a 0x marketplace). - // This is calculated as `keyPrice * transferFeeBasisPoints / BASIS_POINTS_DEN`. - uint public transferFeeBasisPoints; - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - */ - function shareKey( - address _to, - uint _tokenId, - uint _timeShared - ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_to != address(0), "INVALID_ADDRESS"); - address keyOwner = _ownerOf[_tokenId]; - require(getHasValidKey(keyOwner), "KEY_NOT_VALID"); - require(keyOwner != _to, "TRANSFER_TO_SELF"); - - Key storage fromKey = keyByOwner[keyOwner]; - Key storage toKey = keyByOwner[_to]; - uint idTo = toKey.tokenId; - uint time; - // get the remaining time for the origin key - uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; - // get the transfer fee based on amount of time wanted share - uint fee = getTransferFee(keyOwner, _timeShared); - uint timePlusFee = _timeShared + fee; - - // ensure that we don't try to share too much - if (timePlusFee < timeRemaining) { - // now we can safely set the time - time = _timeShared; - // deduct time from parent key, including transfer fee - _timeMachine(_tokenId, timePlusFee, false); - } else { - // we have to recalculate the fee here - fee = getTransferFee(keyOwner, timeRemaining); - time = timeRemaining - fee; - fromKey.expirationTimestamp = block.timestamp; // Effectively expiring the key - emit ExpireKey(_tokenId); - } - - if (idTo == 0) { - _assignNewTokenId(toKey); - idTo = toKey.tokenId; - _recordOwner(_to, idTo); - emit Transfer( - address(0), // This is a creation or time-sharing - _to, - idTo - ); - } else if (toKey.expirationTimestamp <= block.timestamp) { - // reset the key Manager for expired keys - _setKeyManagerOf(idTo, address(0)); - } - - // add time to new key - _timeMachine(idTo, time, true); - // trigger event - emit Transfer(keyOwner, _to, idTo); - - require( - _checkOnERC721Received(keyOwner, _to, idTo, ""), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - function transferFrom( - address _from, - address _recipient, - uint _tokenId - ) public onlyIfAlive hasValidKey(_from) onlyKeyManagerOrApproved(_tokenId) { - require(ownerOf(_tokenId) == _from, "TRANSFER_FROM: NOT_KEY_OWNER"); - require( - transferFeeBasisPoints < BASIS_POINTS_DEN, - "KEY_TRANSFERS_DISABLED" - ); - require(_recipient != address(0), "INVALID_ADDRESS"); - require(_from != _recipient, "TRANSFER_TO_SELF"); - uint fee = getTransferFee(_from, 0); - - Key storage fromKey = keyByOwner[_from]; - Key storage toKey = keyByOwner[_recipient]; - - uint previousExpiration = toKey.expirationTimestamp; - // subtract the fee from the senders key before the transfer - _timeMachine(_tokenId, fee, false); - - if (toKey.tokenId == 0) { - toKey.tokenId = _tokenId; - _recordOwner(_recipient, _tokenId); - // Clear any previous approvals - _clearApproval(_tokenId); - } - - if (previousExpiration <= block.timestamp) { - // The recipient did not have a key, or had a key but it expired. The new expiration is the sender's key expiration - // An expired key is no longer a valid key, so the new tokenID is the sender's tokenID - toKey.expirationTimestamp = fromKey.expirationTimestamp; - toKey.tokenId = _tokenId; - - // Reset the key Manager to the key owner - _setKeyManagerOf(_tokenId, address(0)); - - _recordOwner(_recipient, _tokenId); - } else { - require( - expirationDuration != type(uint).max, - "Recipient already owns a non-expiring key" - ); - // The recipient has a non expired key. We just add them the corresponding remaining time - // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow - toKey.expirationTimestamp = - fromKey.expirationTimestamp + - previousExpiration - - block.timestamp; - } - - // Effectively expiring the key for the previous owner - fromKey.expirationTimestamp = block.timestamp; - - // Set the tokenID to 0 for the previous owner to avoid duplicates - fromKey.tokenId = 0; - - // trigger event - emit Transfer(_from, _recipient, _tokenId); - } - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) public returns (bool success) { - uint maxTimeToSend = _value * expirationDuration; - Key storage fromKey = keyByOwner[msg.sender]; - uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; - if (maxTimeToSend < timeRemaining) { - shareKey(_to, fromKey.tokenId, maxTimeToSend); - } else { - transferFrom(msg.sender, _to, fromKey.tokenId); - } - - // Errors will cause a revert - return true; - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address - * @dev This works identically to the other function with an extra data parameter, - * except this function just sets data to '' - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - */ - function safeTransferFrom(address _from, address _to, uint _tokenId) public { - safeTransferFrom(_from, _to, _tokenId, ""); - } - - /** - * @notice Transfers the ownership of an NFT from one address to another address. - * When transfer is complete, this functions - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @param _from The current owner of the NFT - * @param _to The new owner - * @param _tokenId The NFT to transfer - * @param _data Additional data with no specified format, sent in call to `_to` - */ - function safeTransferFrom( - address _from, - address _to, - uint _tokenId, - bytes memory _data - ) public { - transferFrom(_from, _to, _tokenId); - require( - _checkOnERC721Received(_from, _to, _tokenId, _data), - "NON_COMPLIANT_ERC721_RECEIVER" - ); - } - - /** - * Allow the Lock owner to change the transfer fee. - */ - function updateTransferFee( - uint _transferFeeBasisPoints - ) external onlyLockManager { - emit TransferFeeChanged(_transferFeeBasisPoints); - transferFeeBasisPoints = _transferFeeBasisPoints; - } - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @param _keyOwner The owner of the key check the transfer fee for. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) public view returns (uint) { - if (!getHasValidKey(_keyOwner)) { - return 0; - } else { - Key storage key = keyByOwner[_keyOwner]; - uint timeToTransfer; - uint fee; - // Math: safeSub is not required since `hasValidKey` confirms timeToTransfer is positive - // this is for standard key transfers - if (_time == 0) { - timeToTransfer = key.expirationTimestamp - block.timestamp; - } else { - timeToTransfer = _time; - } - fee = (timeToTransfer * transferFeeBasisPoints) / BASIS_POINTS_DEN; - return fee; - } - } - - /** - * @dev Internal function to invoke `onERC721Received` on a target address - * The call is not executed if the target address is not a contract - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param _data bytes optional data to send along with the call - * @return whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory _data - ) internal returns (bool) { - if (!to.isContract()) { - return true; - } - bytes4 retval = IERC721ReceiverUpgradeable(to).onERC721Received( - msg.sender, - from, - tokenId, - _data - ); - return (retval == _ERC721_RECEIVED); - } - - uint256[1000] private __safe_upgrade_gap; -} - -// File contracts/PublicLock.sol -pragma solidity ^0.8.4; - -/** - * @title The Lock contract - * @author Julien Genestoux (unlock-protocol.com) - * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. - * Every ERC-721 compliant contract must implement the ERC165 interface. - * https://eips.ethereum.org/EIPS/eip-721 - */ -contract PublicLock is - Initializable, - ERC165StorageUpgradeable, - MixinRoles, - MixinFunds, - MixinDisable, - MixinLockCore, - MixinKeys, - MixinLockMetadata, - MixinERC721Enumerable, - MixinGrantKeys, - MixinPurchase, - MixinTransfer, - MixinRefunds -{ - function initialize( - address payable _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) public initializer { - MixinFunds._initializeMixinFunds(_tokenAddress); - MixinDisable._initializeMixinDisable(); - MixinLockCore._initializeMixinLockCore( - _lockCreator, - _expirationDuration, - _keyPrice, - _maxNumberOfKeys - ); - MixinLockMetadata._initializeMixinLockMetadata(_lockName); - MixinERC721Enumerable._initializeMixinERC721Enumerable(); - MixinRefunds._initializeMixinRefunds(); - MixinRoles._initializeMixinRoles(_lockCreator); - // registering the interface for erc721 with ERC165.sol using - // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 - _registerInterface(0x80ac58cd); - } - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - receive() external payable {} - - /** - Overrides - */ - function supportsInterface( - bytes4 interfaceId - ) - public - view - virtual - override( - MixinERC721Enumerable, - MixinLockMetadata, - AccessControlUpgradeable, - ERC165StorageUpgradeable - ) - returns (bool) - { - return super.supportsInterface(interfaceId); - } -} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV9.sol b/packages/contracts/src/contracts/Unlock/IUnlockV9.sol deleted file mode 100644 index 136ba888c5d..00000000000 --- a/packages/contracts/src/contracts/Unlock/IUnlockV9.sol +++ /dev/null @@ -1,166 +0,0 @@ -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlockV9 { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external returns (address); - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - // Function to read the chainId field. - function chainId() external view returns (uint); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI, - uint _chainId - ) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV9.sol b/packages/contracts/src/contracts/Unlock/UnlockV9.sol deleted file mode 100644 index 4d74aac4b79..00000000000 --- a/packages/contracts/src/contracts/Unlock/UnlockV9.sol +++ /dev/null @@ -1,1591 +0,0 @@ -// Sources flattened with hardhat v2.4.1 https://hardhat.org - -// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.8.0 - -pragma solidity >=0.4.24 <0.7.0; - -/** - * @title Initializable - * - * @dev Helper contract to support initializer functions. To use it, replace - * the constructor with a function that has the `initializer` modifier. - * WARNING: Unlike constructors, initializer functions must be manually - * invoked. This applies both to deploying an Initializable contract, as well - * as extending an Initializable contract via inheritance. - * WARNING: When used with inheritance, manual care must be taken to not invoke - * a parent initializer twice, or ensure that all initializers are idempotent, - * because this is not dealt with automatically as with constructors. - */ -contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - */ - bool private initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private initializing; - - /** - * @dev Modifier to use in the initializer function of a contract. - */ - modifier initializer() { - require( - initializing || isConstructor() || !initialized, - "Contract instance has already been initialized" - ); - - bool isTopLevelCall = !initializing; - if (isTopLevelCall) { - initializing = true; - initialized = true; - } - - _; - - if (isTopLevelCall) { - initializing = false; - } - } - - /// @dev Returns true if and only if the function is running in the constructor - function isConstructor() private view returns (bool) { - // extcodesize checks the size of the code stored in an address, and - // address returns the current address. Since the code is still not - // deployed when running a constructor, any checks on its code size will - // yield zero, making it an effective way to detect if a contract is - // under construction or not. - address self = address(this); - uint256 cs; - assembly { - cs := extcodesize(self) - } - return cs == 0; - } - - // Reserved storage space to allow for layout changes in the future. - uint256[50] private ______gap; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.5.0 - -pragma solidity ^0.5.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 GSN 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. - */ -contract Context is Initializable { - // Empty internal constructor, to prevent people from mistakenly deploying - // an instance of this contract, which should be used via inheritance. - constructor() internal {} - - // solhint-disable-previous-line no-empty-blocks - - function _msgSender() internal view returns (address payable) { - return msg.sender; - } - - function _msgData() internal view returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @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. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Initializable, Context { - address private _owner; - - event OwnershipTransferred( - address indexed previousOwner, - address indexed newOwner - ); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - function initialize(address sender) public initializer { - _owner = sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return _msgSender() == _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 onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = 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 onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } - - uint256[50] private ______gap; -} - -// File hardlydifficult-ethereum-contracts/contracts/proxies/Clone2Factory.sol@v0.11.1 - -pragma solidity ^0.5.0; - -// From https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol -// Updated to support Solidity 5, switch to `create2` and revert on fail -library Clone2Factory { - /** - * @notice Uses create2 to deploy a clone to a pre-determined address. - * @param target the address of the template contract, containing the logic for this contract. - * @param salt a salt used to determine the contract address before the transaction is mined, - * may be random or sequential. - * The salt to use with the create2 call can be `msg.sender+salt` in order to - * prevent an attacker from front-running another user's deployment. - * @return proxyAddress the address of the newly deployed contract. - * @dev Using `bytes12` for the salt saves 6 gas over using `uint96` (requires another shift). - * Will revert on fail. - */ - function createClone2( - address target, - bytes32 salt - ) internal returns (address proxyAddress) { - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - - // Create the bytecode for deployment based on the Minimal Proxy Standard (EIP-1167) - // bytecode: 0x0 - mstore( - pointer, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - mstore(add(pointer, 0x14), shl(96, target)) - mstore( - add(pointer, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - - // `create2` consumes all available gas if called with a salt that's already been consumed - // we check if the address is available first so that doesn't happen - // Costs ~958 gas - - // Calculate the hash - let contractCodeHash := keccak256(pointer, 0x37) - - // salt: 0x100 - mstore(add(pointer, 0x100), salt) - - // addressSeed: 0x40 - // 0xff - mstore( - add(pointer, 0x40), - 0xff00000000000000000000000000000000000000000000000000000000000000 - ) - // this - mstore(add(pointer, 0x41), shl(96, address)) - // salt - mstore(add(pointer, 0x55), mload(add(pointer, 0x100))) - // hash - mstore(add(pointer, 0x75), contractCodeHash) - - proxyAddress := keccak256(add(pointer, 0x40), 0x55) - - switch extcodesize(proxyAddress) - case 0 { - // Deploy the contract, returning the address or 0 on fail - proxyAddress := create2(0, pointer, 0x37, mload(add(pointer, 0x100))) - } - default { - proxyAddress := 0 - } - } - - // Revert if the deployment fails (possible if salt was already used) - require(proxyAddress != address(0), "PROXY_DEPLOY_FAILED"); - } -} - -// File contracts/interfaces/IPublicLock.sol - -pragma solidity 0.5.17; - -/** - * @title The PublicLock Interface - */ - -contract IPublicLock { - // See indentationissue description here: - // https://github.com/duaraghav8/Ethlint/issues/268 - // solium-disable indentation - - /// Functions - - function initialize( - address _lockCreator, - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName - ) external; - - /** - * @notice Allow the contract to accept tips in ETH sent directly to the contract. - * @dev This is okay to use even if the lock is priced in ERC-20 tokens - */ - function() external payable; - - /** - * @dev Never used directly - */ - function initialize() external; - - /** - * @notice The version number of the current implementation on this network. - * @return The current version number. - */ - function publicLockVersion() public pure returns (uint); - - /** - * @notice Gets the current balance of the account provided. - * @param _tokenAddress The token type to retrieve the balance of. - * @param _account The account to get the balance of. - * @return The number of tokens of the given type for the given address, possibly 0. - */ - function getBalance( - address _tokenAddress, - address _account - ) external view returns (uint); - - /** - * @notice Used to disable lock before migrating keys and/or destroying contract. - * @dev Throws if called by other than a lock manager. - * @dev Throws if lock contract has already been disabled. - */ - function disableLock() external; - - /** - * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. - * @dev Throws if called by other than a lock manager or beneficiary - * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually - * the same as `tokenAddress` in MixinFunds. - * @param _amount specifies the max amount to withdraw, which may be reduced when - * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. - * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` - * use cases. - */ - function withdraw(address _tokenAddress, uint _amount) external; - - /** - * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. - * @param _spender address that can spend tokens belonging to the lock - * @param _amount amount of tokens that can be spent by the spender - */ - function approveBeneficiary( - address _spender, - uint _amount - ) external returns (bool); - - /** - * A function which lets a Lock manager of the lock to change the price for future purchases. - * @dev Throws if called by other than a Lock manager - * @dev Throws if lock has been disabled - * @dev Throws if _tokenAddress is not a valid token - * @param _keyPrice The new price to set for keys - * @param _tokenAddress The address of the erc20 token to use for pricing the keys, - * or 0 to use ETH - */ - function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; - - /** - * A function which lets a Lock manager update the beneficiary account, - * which receives funds on withdrawal. - * @dev Throws if called by other than a Lock manager or beneficiary - * @dev Throws if _beneficiary is address(0) - * @param _beneficiary The new address to set as the beneficiary - */ - function updateBeneficiary(address _beneficiary) external; - - /** - * Checks if the user has a non-expired key. - * @param _user The address of the key owner - */ - function getHasValidKey(address _user) external view returns (bool); - - /** - * @notice Find the tokenId for a given user - * @return The tokenId of the NFT, else returns 0 - * @param _account The address of the key owner - */ - function getTokenIdFor(address _account) external view returns (uint); - - /** - * A function which returns a subset of the keys for this Lock as an array - * @param _page the page of key owners requested when faceted by page size - * @param _pageSize the number of Key Owners requested per page - * @dev Throws if there are no key owners yet - */ - function getOwnersByPage( - uint _page, - uint _pageSize - ) external view returns (address[] memory); - - /** - * Checks if the given address owns the given tokenId. - * @param _tokenId The tokenId of the key to check - * @param _keyOwner The potential key owners address - */ - function isKeyOwner( - uint _tokenId, - address _keyOwner - ) external view returns (bool); - - /** - * @dev Returns the key's ExpirationTimestamp field for a given owner. - * @param _keyOwner address of the user for whom we search the key - * @dev Returns 0 if the owner has never owned a key for this lock - */ - function keyExpirationTimestampFor( - address _keyOwner - ) external view returns (uint timestamp); - - /** - * Public function which returns the total number of unique owners (both expired - * and valid). This may be larger than totalSupply. - */ - function numberOfOwners() external view returns (uint); - - /** - * Allows a Lock manager to assign a descriptive name for this Lock. - * @param _lockName The new name for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockName(string calldata _lockName) external; - - /** - * Allows a Lock manager to assign a Symbol for this Lock. - * @param _lockSymbol The new Symbol for the lock - * @dev Throws if called by other than a Lock manager - */ - function updateLockSymbol(string calldata _lockSymbol) external; - - /** - * @dev Gets the token symbol - * @return string representing the token symbol - */ - function symbol() external view returns (string memory); - - /** - * Allows a Lock manager to update the baseTokenURI for this Lock. - * @dev Throws if called by other than a Lock manager - * @param _baseTokenURI String representing the base of the URI for this lock. - */ - function setBaseTokenURI(string calldata _baseTokenURI) external; - - /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. - * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - * 3986. The URI may point to a JSON file that conforms to the "ERC721 - * Metadata JSON Schema". - * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md - * @param _tokenId The tokenID we're inquiring about - * @return String representing the URI for the requested token - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - /** - * Allows a Lock manager to add or remove an event hook - * @param _onKeyPurchaseHook Hook called when the `purchase` function is called - * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called - */ - function setEventHooks( - address _onKeyPurchaseHook, - address _onKeyCancelHook - ) external; - - /** - * Allows a Lock manager to give a collection of users a key with no charge. - * Each key may be assigned a different expiration date. - * @dev Throws if called by other than a Lock manager - * @param _recipients An array of receiving addresses - * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted - */ - function grantKeys( - address[] calldata _recipients, - uint[] calldata _expirationTimestamps, - address[] calldata _keyManagers - ) external; - - /** - * @dev Purchase function - * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount - * (_value is ignored when using ETH) - * @param _recipient address of the recipient of the purchased key - * @param _referrer address of the user making the referral - * @param _data arbitrary data populated by the front-end which initiated the sale - * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). - * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the - * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more - * than keyPrice is approved for spending). - */ - function purchase( - uint256 _value, - address _recipient, - address _referrer, - bytes calldata _data - ) external payable; - - /** - * @notice returns the minimum price paid for a purchase with these params. - * @dev this considers any discount from Unlock or the OnKeyPurchase hook. - */ - function purchasePriceFor( - address _recipient, - address _referrer, - bytes calldata _data - ) external view returns (uint); - - /** - * Allow a Lock manager to change the transfer fee. - * @dev Throws if called by other than a Lock manager - * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). - * Ex: 200 bps = 2% - */ - function updateTransferFee(uint _transferFeeBasisPoints) external; - - /** - * Determines how much of a fee a key owner would need to pay in order to - * transfer the key to another account. This is pro-rated so the fee goes down - * overtime. - * @dev Throws if _keyOwner does not have a valid key - * @param _keyOwner The owner of the key check the transfer fee for. - * @param _time The amount of time to calculate the fee for. - * @return The transfer fee in seconds. - */ - function getTransferFee( - address _keyOwner, - uint _time - ) external view returns (uint); - - /** - * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key - * @param _keyOwner The key owner to whom we wish to send a refund to - * @param amount The amount to refund the key-owner - * @dev Throws if called by other than a Lock manager - * @dev Throws if _keyOwner does not have a valid key - */ - function expireAndRefundFor(address _keyOwner, uint amount) external; - - /** - * @dev allows the key manager to expire a given tokenId - * and send a refund to the keyOwner based on the amount of time remaining. - * @param _tokenId The id of the key to cancel. - */ - function cancelAndRefund(uint _tokenId) external; - - /** - * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. - * @param _keyManager the key managed by this user will be canceled - * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager - * @param _tokenId The key to cancel - */ - function cancelAndRefundFor( - address _keyManager, - uint8 _v, - bytes32 _r, - bytes32 _s, - uint _tokenId - ) external; - - /** - * @notice Sets the minimum nonce for a valid off-chain approval message from the - * senders account. - * @dev This can be used to invalidate a previously signed message. - */ - function invalidateOffchainApproval(uint _nextAvailableNonce) external; - - /** - * Allow a Lock manager to change the refund penalty. - * @dev Throws if called by other than a Lock manager - * @param _freeTrialLength The new duration of free trials for this lock - * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) - */ - function updateRefundPenalty( - uint _freeTrialLength, - uint _refundPenaltyBasisPoints - ) external; - - /** - * @dev Determines how much of a refund a key owner would receive if they issued - * @param _keyOwner The key owner to get the refund value for. - * a cancelAndRefund block.timestamp. - * Note that due to the time required to mine a tx, the actual refund amount will be lower - * than what the user reads from this call. - */ - function getCancelAndRefundValueFor( - address _keyOwner - ) external view returns (uint refund); - - function keyManagerToNonce(address) external view returns (uint256); - - /** - * @notice returns the hash to sign in order to allow another user to cancel on your behalf. - * @dev this can be computed in JS instead of read from the contract. - * @param _keyManager The key manager's address (also the message signer) - * @param _txSender The address cancelling cancel on behalf of the keyOwner - * @return approvalHash The hash to sign - */ - function getCancelAndRefundApprovalHash( - address _keyManager, - address _txSender - ) external view returns (bytes32 approvalHash); - - function addKeyGranter(address account) external; - - function addLockManager(address account) external; - - function isKeyGranter(address account) external view returns (bool); - - function isLockManager(address account) external view returns (bool); - - function onKeyPurchaseHook() external view returns (address); - - function onKeyCancelHook() external view returns (address); - - function revokeKeyGranter(address _granter) external; - - function renounceLockManager() external; - - ///=================================================================== - /// Auto-generated getter functions from public state variables - - function beneficiary() external view returns (address); - - function expirationDuration() external view returns (uint256); - - function freeTrialLength() external view returns (uint256); - - function isAlive() external view returns (bool); - - function keyPrice() external view returns (uint256); - - function maxNumberOfKeys() external view returns (uint256); - - function owners(uint256) external view returns (address); - - function refundPenaltyBasisPoints() external view returns (uint256); - - function tokenAddress() external view returns (address); - - function transferFeeBasisPoints() external view returns (uint256); - - function unlockProtocol() external view returns (address); - - function keyManagerOf(uint) external view returns (address); - - ///=================================================================== - - /** - * @notice Allows the key owner to safely share their key (parent key) by - * transferring a portion of the remaining time to a new key (child key). - * @dev Throws if key is not valid. - * @dev Throws if `_to` is the zero address - * @param _to The recipient of the shared key - * @param _tokenId the key to share - * @param _timeShared The amount of time shared - * checks if `_to` is a smart contract (code size > 0). If so, it calls - * `onERC721Received` on `_to` and throws if the return value is not - * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. - * @dev Emit Transfer event - */ - function shareKey(address _to, uint _tokenId, uint _timeShared) external; - - /** - * @notice Update transfer and cancel rights for a given key - * @param _tokenId The id of the key to assign rights for - * @param _keyManager The address to assign the rights to for the given key - */ - function setKeyManagerOf(uint _tokenId, address _keyManager) external; - - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - ///=================================================================== - - /// From ERC165.sol - function supportsInterface(bytes4 interfaceId) external view returns (bool); - - ///=================================================================== - - /// From ERC-721 - /** - * @dev Returns the number of NFTs in `owner`'s account. - */ - function balanceOf(address _owner) public view returns (uint256 balance); - - /** - * @dev Returns the owner of the NFT specified by `tokenId`. - */ - function ownerOf(uint256 tokenId) public view returns (address _owner); - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * - * - * Requirements: - * - `from`, `to` cannot be zero. - * - `tokenId` must be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this - * NFT by either `approve` or `setApprovalForAll`. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public; - - /** - * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to - * another (`to`). - * - * Requirements: - * - If the caller is not `from`, it must be approved to move this NFT by - * either `approve` or `setApprovalForAll`. - */ - function transferFrom(address from, address to, uint256 tokenId) public; - - function approve(address to, uint256 tokenId) public; - - /** - * @notice Get the approved address for a single NFT - * @dev Throws if `_tokenId` is not a valid NFT. - * @param _tokenId The NFT to find the approved address for - * @return The approved address for this NFT, or the zero address if there is none - */ - function getApproved(uint256 _tokenId) public view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) public; - - function isApprovedForAll( - address _owner, - address operator - ) public view returns (bool); - - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public; - - function totalSupply() public view returns (uint256); - - function tokenOfOwnerByIndex( - address _owner, - uint256 index - ) public view returns (uint256 tokenId); - - function tokenByIndex(uint256 index) public view returns (uint256); - - /** - * @notice An ERC-20 style transfer. - * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). - * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user - * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. - */ - function transfer(address _to, uint _value) external returns (bool success); -} - -// File contracts/interfaces/IUnlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock Interface - **/ - -interface IUnlock { - // Use initialize instead of a constructor to support proxies(for upgradeability via zos). - function initialize(address _unlockOwner) external; - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string calldata _lockName, - bytes12 _salt - ) external; - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - */ - function recordKeyPurchase( - uint _value, - address _referrer // solhint-disable-line no-unused-vars - ) external; - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint _tokens // solhint-disable-line no-unused-vars - ) external; - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - */ - function computeAvailableDiscountFor( - address _purchaser, // solhint-disable-line no-unused-vars - uint _keyPrice // solhint-disable-line no-unused-vars - ) external view returns (uint discount, uint tokens); - - // Function to read the globalTokenURI field. - function globalBaseTokenURI() external view returns (string memory); - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory); - - // Function to read the globalTokenSymbol field. - function globalTokenSymbol() external view returns (string memory); - - // Function to read the chainId field. - function chainId() external view returns (uint); - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory); - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI, - uint _chainId - ) external; - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate(address payable _publicLockAddress) external; - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external; - - function grossNetworkProduct() external view returns (uint); - - function totalDiscountGranted() external view returns (uint); - - function locks( - address - ) - external - view - returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); - - // The address of the public lock template, used when `createLock` is called - function publicLockAddress() external view returns (address); - - // Map token address to exchange contract address if the token is supported - // Used for GDP calculations - function uniswapOracles(address) external view returns (address); - - // The WETH token address, used for value calculations - function weth() external view returns (address); - - // The UDT token address, used to mint tokens on referral - function udt() external view returns (address); - - // The approx amount of gas required to purchase a key - function estimatedGasForPurchase() external view returns (uint); - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16); - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle(address _tokenAddress, address _oracleAddress) external; - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() external view returns (bool); - - /** - * @dev Returns the address of the current owner. - */ - function owner() external view returns (address); - - /** - * @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() external; - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) external; -} - -// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.5.0 - -pragma solidity ^0.5.5; - -/** - * @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 - * ==== - */ - function isContract(address account) internal view returns (bool) { - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { - codehash := extcodehash(account) - } - return (codehash != accountHash && codehash != 0x0); - } - - /** - * @dev Converts an `address` into `address payable`. Note that this is - * simply a type cast: the actual underlying value is not changed. - * - * _Available since v2.4.0._ - */ - function toPayable(address account) internal pure returns (address payable) { - return address(uint160(account)); - } - - /** - * @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]. - * - * _Available since v2.4.0._ - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-call-value - (bool success, ) = recipient.call.value(amount)(""); - require( - success, - "Address: unable to send value, recipient may have reverted" - ); - } -} - -// File hardlydifficult-eth/contracts/protocols/Uniswap/IUniswapOracle.sol@v1.1.2 - -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0; - -interface IUniswapOracle { - function PERIOD() external returns (uint); - - function factory() external returns (address); - - function update(address _tokenIn, address _tokenOut) external; - - function consult( - address _tokenIn, - uint _amountIn, - address _tokenOut - ) external view returns (uint _amountOut); - - function updateAndConsult( - address _tokenIn, - uint _amountIn, - address _tokenOut - ) external returns (uint _amountOut); -} - -// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.5.0 - -pragma solidity ^0.5.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - * - * _Available since v2.4.0._ - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - * - * _Available since v2.4.0._ - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } -} - -// File contracts/interfaces/IMintableERC20.sol - -pragma solidity 0.5.17; - -interface IMintableERC20 { - function mint(address account, uint256 amount) external returns (bool); - - function transfer(address recipient, uint256 amount) external returns (bool); - - function totalSupply() external returns (uint); - - function balanceOf(address account) external returns (uint256); -} - -// File contracts/Unlock.sol - -pragma solidity 0.5.17; - -/** - * @title The Unlock contract - * @author Julien Genestoux (unlock-protocol.com) - * This smart contract has 3 main roles: - * 1. Distribute discounts to discount token holders - * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. - * 3. Create & deploy Public Lock contracts. - * In order to achieve these 3 elements, it keeps track of several things such as - * a. Deployed locks addresses and balances of discount tokens granted by each lock. - * b. The total network product (sum of all key sales, net of discounts) - * c. Total of discounts granted - * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim - * discounts and cannot be used/transferred for a given period) - * e. Growth rate of Network Product - * f. Growth rate of Discount tokens supply - * The smart contract has an owner who only can perform the following - * - Upgrades - * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most - * 50% of GNP growth rate) - * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and - * in the wild. - * The partial implementation includes the following features: - * a. Keeping track of deployed locks - * b. Keeping track of GNP - */ - -/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. -/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization -contract Unlock is IUnlock, Initializable, Ownable { - using Address for address; - using Clone2Factory for address; - using SafeMath for uint; - - /** - * The struct for a lock - * We use deployed to keep track of deployments. - * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, - * which would be the same values when the lock is not set. - */ - struct LockBalances { - bool deployed; - uint totalSales; // This is in wei - uint yieldedDiscountTokens; - } - - modifier onlyFromDeployedLock() { - require(locks[msg.sender].deployed, "ONLY_LOCKS"); - _; - } - - uint public grossNetworkProduct; - - uint public totalDiscountGranted; - - // We keep track of deployed locks to ensure that callers are all deployed locks. - mapping(address => LockBalances) public locks; - - // global base token URI - // Used by locks where the owner has not set a custom base URI. - string public globalBaseTokenURI; - - // global base token symbol - // Used by locks where the owner has not set a custom symbol - string public globalTokenSymbol; - - // The address of the public lock template, used when `createLock` is called - address public publicLockAddress; - - // Map token address to oracle contract address if the token is supported - // Used for GDP calculations - mapping(address => IUniswapOracle) public uniswapOracles; - - // The WETH token address, used for value calculations - address public weth; - - // The UDT token address, used to mint tokens on referral - address public udt; - - // The approx amount of gas required to purchase a key - uint public estimatedGasForPurchase; - - // Blockchain ID the network id on which this version of Unlock is operating - uint public chainId; - - // Events - event NewLock(address indexed lockOwner, address indexed newLockAddress); - - event ConfigUnlock( - address udt, - address weth, - uint estimatedGasForPurchase, - string globalTokenSymbol, - string globalTokenURI, - uint chainId - ); - - event SetLockTemplate(address publicLockAddress); - - event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); - - // Use initialize instead of a constructor to support proxies (for upgradeability via zos). - function initialize(address _unlockOwner) public initializer { - // We must manually initialize Ownable.sol - Ownable.initialize(_unlockOwner); - } - - /** - * @dev Create lock - * This deploys a lock for a creator. It also keeps track of the deployed lock. - * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. - * @param _salt an identifier for the Lock, which is unique for the user. - * This may be implemented as a sequence ID or with RNG. It's used with `create2` - * to know the lock's address before the transaction is mined. - */ - function createLock( - uint _expirationDuration, - address _tokenAddress, - uint _keyPrice, - uint _maxNumberOfKeys, - string memory _lockName, - bytes12 _salt - ) public { - require(publicLockAddress != address(0), "MISSING_LOCK_TEMPLATE"); - - // create lock - bytes32 salt; - // solium-disable-next-line - assembly { - let pointer := mload(0x40) - // The salt is the msg.sender - mstore(pointer, shl(96, caller)) - // followed by the _salt provided - mstore(add(pointer, 0x14), _salt) - salt := mload(pointer) - } - address payable newLock = address( - uint160(publicLockAddress.createClone2(salt)) - ); - IPublicLock(newLock).initialize( - msg.sender, - _expirationDuration, - _tokenAddress, - _keyPrice, - _maxNumberOfKeys, - _lockName - ); - - // Assign the new Lock - locks[newLock] = LockBalances({ - deployed: true, - totalSales: 0, - yieldedDiscountTokens: 0 - }); - - // trigger event - emit NewLock(msg.sender, newLock); - } - - /** - * This function returns the discount available for a user, when purchasing a - * a key from a lock. - * This does not modify the state. It returns both the discount and the number of tokens - * consumed to grant that discount. - * TODO: actually implement this. - */ - function computeAvailableDiscountFor( - address /* _purchaser */, - uint /* _keyPrice */ - ) public view returns (uint discount, uint tokens) { - // TODO: implement me - return (0, 0); - } - - /** - * This function keeps track of the added GDP, as well as grants of discount tokens - * to the referrer, if applicable. - * The number of discount tokens granted is based on the value of the referal, - * the current growth rate and the lock's discount token distribution rate - * This function is invoked by a previously deployed lock only. - * TODO: actually implement - */ - function recordKeyPurchase( - uint _value, - address _referrer - ) public onlyFromDeployedLock { - if (_value > 0) { - uint valueInETH; - address tokenAddress = IPublicLock(msg.sender).tokenAddress(); - if (tokenAddress != address(0) && tokenAddress != weth) { - // If priced in an ERC-20 token, find the supported uniswap oracle - IUniswapOracle oracle = uniswapOracles[tokenAddress]; - if (address(oracle) != address(0)) { - valueInETH = oracle.updateAndConsult(tokenAddress, _value, weth); - } - } else { - // If priced in ETH (or value is 0), no conversion is required - valueInETH = _value; - } - - grossNetworkProduct = grossNetworkProduct.add(valueInETH); - // If GNP does not overflow, the lock totalSales should be safe - locks[msg.sender].totalSales += valueInETH; - - // Mint UDT - if (_referrer != address(0)) { - IUniswapOracle udtOracle = uniswapOracles[udt]; - if (address(udtOracle) != address(0)) { - // Get the value of 1 UDT (w/ 18 decimals) in ETH - uint udtPrice = udtOracle.updateAndConsult(udt, 10 ** 18, weth); - - // tokensToDistribute is either == to the gas cost times 1.25 to cover the 20% dev cut - uint tokensToDistribute = (estimatedGasForPurchase * tx.gasprice).mul( - 125 * 10 ** 18 - ) / - 100 / - udtPrice; - - // or tokensToDistribute is capped by network GDP growth - uint maxTokens = 0; - if (chainId > 1) { - // non mainnet: we distribute tokens using asymptotic curve between 0 and 0.5 - // maxTokens = IMintableERC20(udt).balanceOf(address(this)).mul((valueInETH / grossNetworkProduct) / (2 + 2 * valueInETH / grossNetworkProduct)); - maxTokens = - IMintableERC20(udt).balanceOf(address(this)).mul(valueInETH) / - (2 + (2 * valueInETH) / grossNetworkProduct) / - grossNetworkProduct; - } else { - // Mainnet: we mint new token using log curve - maxTokens = - IMintableERC20(udt).totalSupply().mul(valueInETH) / - 2 / - grossNetworkProduct; - } - - // cap to GDP growth! - if (tokensToDistribute > maxTokens) { - tokensToDistribute = maxTokens; - } - - if (tokensToDistribute > 0) { - // 80% goes to the referrer, 20% to the Unlock dev - round in favor of the referrer - uint devReward = tokensToDistribute.mul(20) / 100; - if (chainId > 1) { - uint balance = IMintableERC20(udt).balanceOf(address(this)); - if (balance > tokensToDistribute) { - // Only distribute if there are enough tokens - IMintableERC20(udt).transfer( - _referrer, - tokensToDistribute - devReward - ); - IMintableERC20(udt).transfer(owner(), devReward); - } - } else { - // No distribnution - IMintableERC20(udt).mint( - _referrer, - tokensToDistribute - devReward - ); - IMintableERC20(udt).mint(owner(), devReward); - } - } - } - } - } - } - - /** - * This function will keep track of consumed discounts by a given user. - * It will also grant discount tokens to the creator who is granting the discount based on the - * amount of discount and compensation rate. - * This function is invoked by a previously deployed lock only. - */ - function recordConsumedDiscount( - uint _discount, - uint /* _tokens */ - ) public onlyFromDeployedLock { - // TODO: implement me - totalDiscountGranted += _discount; - return; - } - - // The version number of the current Unlock implementation on this network - function unlockVersion() external pure returns (uint16) { - return 9; - } - - /** - * @notice Allows the owner to update configuration variables - */ - function configUnlock( - address _udt, - address _weth, - uint _estimatedGasForPurchase, - string calldata _symbol, - string calldata _URI, - uint _chainId - ) external onlyOwner { - udt = _udt; - weth = _weth; - estimatedGasForPurchase = _estimatedGasForPurchase; - - globalTokenSymbol = _symbol; - globalBaseTokenURI = _URI; - - chainId = _chainId; - - emit ConfigUnlock( - _udt, - _weth, - _estimatedGasForPurchase, - _symbol, - _URI, - _chainId - ); - } - - /** - * @notice Upgrade the PublicLock template used for future calls to `createLock`. - * @dev This will initialize the template and revokeOwnership. - */ - function setLockTemplate( - address payable _publicLockAddress - ) external onlyOwner { - // First claim the template so that no-one else could - // this will revert if the template was already initialized. - IPublicLock(_publicLockAddress).initialize( - address(this), - 0, - address(0), - 0, - 0, - "" - ); - IPublicLock(_publicLockAddress).renounceLockManager(); - - publicLockAddress = _publicLockAddress; - - emit SetLockTemplate(_publicLockAddress); - } - - /** - * @notice allows the owner to set the oracle address to use for value conversions - * setting the _oracleAddress to address(0) removes support for the token - * @dev This will also call update to ensure at least one datapoint has been recorded. - */ - function setOracle( - address _tokenAddress, - address _oracleAddress - ) external onlyOwner { - uniswapOracles[_tokenAddress] = IUniswapOracle(_oracleAddress); - if (_oracleAddress != address(0)) { - IUniswapOracle(_oracleAddress).update(_tokenAddress, weth); - } - } - - // Allows the owner to change the value tracking variables as needed. - function resetTrackedValue( - uint _grossNetworkProduct, - uint _totalDiscountGranted - ) external onlyOwner { - grossNetworkProduct = _grossNetworkProduct; - totalDiscountGranted = _totalDiscountGranted; - - emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); - } - - /** - * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalBaseTokenURI() external view returns (string memory) { - return globalBaseTokenURI; - } - - /** - * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. - */ - function getGlobalTokenSymbol() external view returns (string memory) { - return globalTokenSymbol; - } -} diff --git a/packages/unlock-js/scripts/compressAbi.js b/packages/unlock-js/scripts/compressAbi.js index f14dda0165c..4e0cdb7e955 100644 --- a/packages/unlock-js/scripts/compressAbi.js +++ b/packages/unlock-js/scripts/compressAbi.js @@ -11,8 +11,8 @@ const fs = require('fs') const path = require('path') const abis = require('@unlock-protocol/contracts') -const unlockVersions = ['v9', 'v10', 'v11', 'v12', 'v13'] -const publicLockVersions = ['v9', 'v10', 'v11', 'v12', 'v13', 'v14'] +const unlockVersions = ['v10', 'v11', 'v12', 'v13'] +const publicLockVersions = ['v10', 'v11', 'v12', 'v13', 'v14'] const data = { PublicLock: publicLockVersions.reduce( diff --git a/packages/unlock-js/src/abis.ts b/packages/unlock-js/src/abis.ts index b7cccec5799..f74f7501d4f 100644 --- a/packages/unlock-js/src/abis.ts +++ b/packages/unlock-js/src/abis.ts @@ -4,111 +4,6 @@ const abis = { "PublicLock": { - "v9": { - "contractName": "PublicLock", - "abi": [ - "event Approval (address indexed owner,address indexed approved,uint256 indexed tokenId)", - "event ApprovalForAll (address indexed owner,address indexed operator,bool approved)", - "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", - "event Disable ()", - "event ExpirationChanged (uint256 indexed _tokenId,uint256 _amount,bool _timeAdded)", - "event ExpireKey (uint256 indexed tokenId)", - "event GasRefunded (address indexed receiver,uint256 refundedAmount,address tokenAddress)", - "event KeyGranterAdded (address indexed account)", - "event KeyGranterRemoved (address indexed account)", - "event KeyManagerChanged (uint256 indexed _tokenId,address indexed _newManager)", - "event LockManagerAdded (address indexed account)", - "event LockManagerRemoved (address indexed account)", - "event NewLockSymbol (string symbol)", - "event PricingChanged (uint256 oldKeyPrice,uint256 keyPrice,address oldTokenAddress,address tokenAddress)", - "event RefundPenaltyChanged (uint256 freeTrialLength,uint256 refundPenaltyBasisPoints)", - "event RenewKeyPurchase (address indexed owner,uint256 newExpiration)", - "event RoleAdminChanged (bytes32 indexed role,bytes32 indexed previousAdminRole,bytes32 indexed newAdminRole)", - "event RoleGranted (bytes32 indexed role,address indexed account,address indexed sender)", - "event RoleRevoked (bytes32 indexed role,address indexed account,address indexed sender)", - "event Transfer (address indexed from,address indexed to,uint256 indexed tokenId)", - "event TransferFeeChanged (uint256 transferFeeBasisPoints)", - "event UnlockCallFailed (address indexed lockAddress,address unlockAddress)", - "event Withdrawal (address indexed sender,address indexed tokenAddress,address indexed beneficiary,uint256 amount)", - "function DEFAULT_ADMIN_ROLE() view returns (bytes32)", - "function KEY_GRANTER_ROLE() view returns (bytes32)", - "function LOCK_MANAGER_ROLE() view returns (bytes32)", - "function addKeyGranter(address account)", - "function addLockManager(address account)", - "function approve(address _approved,uint256 _tokenId)", - "function approveBeneficiary(address _spender,uint256 _amount) returns (bool)", - "function balanceOf(address _keyOwner) view returns (uint256)", - "function beneficiary() view returns (address)", - "function cancelAndRefund(uint256 _tokenId)", - "function disableLock()", - "function expirationDuration() view returns (uint256)", - "function expireAndRefundFor(address _keyOwner,uint256 amount)", - "function freeTrialLength() view returns (uint256)", - "function gasRefundValue() view returns (uint256 _refundValue)", - "function getApproved(uint256 _tokenId) view returns (address)", - "function getCancelAndRefundValueFor(address _keyOwner) view returns (uint256 refund)", - "function getHasValidKey(address _keyOwner) view returns (bool isValid)", - "function getRoleAdmin(bytes32 role) view returns (bytes32)", - "function getTokenIdFor(address _account) view returns (uint256)", - "function getTransferFee(address _keyOwner,uint256 _time) view returns (uint256)", - "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps,address[] _keyManagers)", - "function grantRole(bytes32 role,address account)", - "function hasRole(bytes32 role,address account) view returns (bool)", - "function initialize(address _lockCreator,uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", - "function isAlive() view returns (bool)", - "function isApprovedForAll(address _owner,address _operator) view returns (bool)", - "function isKeyGranter(address account) view returns (bool)", - "function isLockManager(address account) view returns (bool)", - "function keyExpirationTimestampFor(address _keyOwner) view returns (uint256)", - "function keyManagerOf(uint256) view returns (address)", - "function keyPrice() view returns (uint256)", - "function maxNumberOfKeys() view returns (uint256)", - "function name() view returns (string)", - "function numberOfOwners() view returns (uint256)", - "function onKeyCancelHook() view returns (address)", - "function onKeyPurchaseHook() view returns (address)", - "function onTokenURIHook() view returns (address)", - "function onValidKeyHook() view returns (address)", - "function ownerOf(uint256 _tokenId) view returns (address)", - "function publicLockVersion() pure returns (uint16)", - "function purchase(uint256 _value,address _recipient,address _referrer,address _keyManager,bytes _data) payable", - "function purchasePriceFor(address _recipient,address _referrer,bytes _data) view returns (uint256 minKeyPrice)", - "function refundPenaltyBasisPoints() view returns (uint256)", - "function renounceLockManager()", - "function renounceRole(bytes32 role,address account)", - "function revokeKeyGranter(address _granter)", - "function revokeRole(bytes32 role,address account)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId)", - "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data)", - "function setApprovalForAll(address _to,bool _approved)", - "function setBaseTokenURI(string _baseTokenURI)", - "function setEventHooks(address _onKeyPurchaseHook,address _onKeyCancelHook,address _onValidKeyHook,address _onTokenURIHook)", - "function setExpirationDuration(uint256 _newExpirationDuration)", - "function setGasRefundValue(uint256 _refundValue)", - "function setKeyManagerOf(uint256 _tokenId,address _keyManager)", - "function setMaxNumberOfKeys(uint256 _maxNumberOfKeys)", - "function shareKey(address _to,uint256 _tokenId,uint256 _timeShared)", - "function supportsInterface(bytes4 interfaceId) view returns (bool)", - "function symbol() view returns (string)", - "function tokenAddress() view returns (address)", - "function tokenByIndex(uint256 _index) view returns (uint256)", - "function tokenOfOwnerByIndex(address _keyOwner,uint256 _index) view returns (uint256)", - "function tokenURI(uint256 _tokenId) view returns (string)", - "function totalSupply() view returns (uint256)", - "function transfer(address _to,uint256 _value) returns (bool success)", - "function transferFeeBasisPoints() view returns (uint256)", - "function transferFrom(address _from,address _recipient,uint256 _tokenId)", - "function unlockProtocol() view returns (address)", - "function updateBeneficiary(address _beneficiary)", - "function updateKeyPricing(uint256 _keyPrice,address _tokenAddress)", - "function updateLockName(string _lockName)", - "function updateLockSymbol(string _lockSymbol)", - "function updateRefundPenalty(uint256 _freeTrialLength,uint256 _refundPenaltyBasisPoints)", - "function updateTransferFee(uint256 _transferFeeBasisPoints)", - "function withdraw(address _tokenAddress,uint256 _amount)" - ], - "bytecodeHash": "0x0cf7c1b77621773fd65811a23143e5e49946d2de75c18934b495940cab871397" - }, "v10": { "contractName": "PublicLock", "abi": [ @@ -840,44 +735,6 @@ const abis = { } }, "Unlock": { - "v9": { - "contractName": "Unlock", - "abi": [ - "event ConfigUnlock (address udt,address weth,uint256 estimatedGasForPurchase,string globalTokenSymbol,string globalTokenURI,uint256 chainId)", - "event NewLock (address indexed lockOwner,address indexed newLockAddress)", - "event OwnershipTransferred (address indexed previousOwner,address indexed newOwner)", - "event ResetTrackedValue (uint256 grossNetworkProduct,uint256 totalDiscountGranted)", - "event SetLockTemplate (address publicLockAddress)", - "function chainId() constant view returns (uint256)", - "function estimatedGasForPurchase() constant view returns (uint256)", - "function globalBaseTokenURI() constant view returns (string)", - "function globalTokenSymbol() constant view returns (string)", - "function grossNetworkProduct() constant view returns (uint256)", - "function isOwner() constant view returns (bool)", - "function locks(address) constant view returns (bool deployed,uint256 totalSales,uint256 yieldedDiscountTokens)", - "function owner() constant view returns (address)", - "function publicLockAddress() constant view returns (address)", - "function renounceOwnership()", - "function totalDiscountGranted() constant view returns (uint256)", - "function transferOwnership(address newOwner)", - "function udt() constant view returns (address)", - "function uniswapOracles(address) constant view returns (address)", - "function weth() constant view returns (address)", - "function initialize(address _unlockOwner)", - "function createLock(uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName,bytes12 _salt)", - "function computeAvailableDiscountFor(address,uint256) constant view returns (uint256 discount,uint256 tokens)", - "function recordKeyPurchase(uint256 _value,address _referrer)", - "function recordConsumedDiscount(uint256 _discount,uint256)", - "function unlockVersion() constant pure returns (uint16)", - "function configUnlock(address _udt,address _weth,uint256 _estimatedGasForPurchase,string _symbol,string _URI,uint256 _chainId)", - "function setLockTemplate(address _publicLockAddress)", - "function setOracle(address _tokenAddress,address _oracleAddress)", - "function resetTrackedValue(uint256 _grossNetworkProduct,uint256 _totalDiscountGranted)", - "function getGlobalBaseTokenURI() constant view returns (string)", - "function getGlobalTokenSymbol() constant view returns (string)" - ], - "bytecodeHash": "0xc5ea0fd202dd361f7dcc45b751f2c2d46a796e3a53c7e75dc1c16cf5285b5a8e" - }, "v10": { "contractName": "Unlock", "abi": [ From a3fba90527758d17875cc83a0eb9fdd779b2553d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:14:43 +0200 Subject: [PATCH 12/27] remove versions from subgraph compiling --- subgraph/introspection.json | 264 ++++++++++++++++++++++++++++++++ subgraph/src/unlock.ts | 2 +- subgraph/subgraph.template.yaml | 8 +- subgraph/tests/keys-v8.test.ts | 162 -------------------- subgraph/tests/locks-v8.test.ts | 108 ------------- 5 files changed, 266 insertions(+), 278 deletions(-) delete mode 100644 subgraph/tests/keys-v8.test.ts delete mode 100644 subgraph/tests/locks-v8.test.ts diff --git a/subgraph/introspection.json b/subgraph/introspection.json index dfbf9ad0f86..cca9397ed97 100644 --- a/subgraph/introspection.json +++ b/subgraph/introspection.json @@ -1822,6 +1822,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "lock__lastKeyRenewedAt", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "lock__deployer", "description": null, @@ -2177,6 +2183,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "lastKeyRenewedAt", + "description": "The timestamp of the block in which the last key was renewed", + "args": [], + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deployer", "description": "Address of the lock deployer", @@ -2299,6 +2317,30 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "keyGranters", + "description": "Key Granters role for key.\nThe lock creator is the default KeyGranter.\nThe primary reason for this role is to support additional purchase mechanisms beyond direct key purchases like credit-card purchases.\n", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -4383,6 +4425,102 @@ }, "defaultValue": null }, + { + "name": "lastKeyRenewedAt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_not", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_gt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_lt", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_gte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_lte", + "description": null, + "type": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "lastKeyRenewedAt_not_in", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + } + } + }, + "defaultValue": null + }, { "name": "deployer", "description": null, @@ -4701,6 +4839,114 @@ }, "defaultValue": null }, + { + "name": "keyGranters", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "keyGranters_not", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "keyGranters_contains", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "keyGranters_contains_nocase", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "keyGranters_not_contains", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "keyGranters_not_contains_nocase", + "description": null, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Bytes", + "ofType": null + } + } + }, + "defaultValue": null + }, { "name": "_change_block", "description": "Filter for the block changed event.", @@ -4842,6 +5088,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "lastKeyRenewedAt", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deployer", "description": null, @@ -4865,6 +5117,12 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "keyGranters", + "description": null, + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null @@ -8587,6 +8845,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "lock__lastKeyRenewedAt", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "lock__deployer", "description": null, diff --git a/subgraph/src/unlock.ts b/subgraph/src/unlock.ts index c3d226b63da..e143facb89a 100644 --- a/subgraph/src/unlock.ts +++ b/subgraph/src/unlock.ts @@ -59,7 +59,7 @@ export function handleNewLock(event: NewLock): void { // fetch lock version let lockContract = PublicLockMerged.bind(lockAddress) let version = BigInt.fromI32(0) - let publicLockVersion = lockContract.try_publicLockVersion1() + let publicLockVersion = lockContract.try_publicLockVersion() if (!publicLockVersion.reverted) { version = BigInt.fromI32(publicLockVersion.value) } diff --git a/subgraph/subgraph.template.yaml b/subgraph/subgraph.template.yaml index 61307819df6..b4733e5e00f 100644 --- a/subgraph/subgraph.template.yaml +++ b/subgraph/subgraph.template.yaml @@ -5,7 +5,7 @@ features: schema: file: ./schema.graphql dataSources: -{{#deployments}} +{{#deployments}} - kind: ethereum name: {{ name }} network: {{ network }} @@ -26,8 +26,6 @@ dataSources: file: ./abis/PublicLock.json - name: PublicLockV11 file: ./abis/PublicLockV11.json - - name: PublicLockV7 - file: ./abis/PublicLockV7.json eventHandlers: - event: NewLock(indexed address,indexed address) handler: handleNewLock @@ -65,10 +63,6 @@ templates: file: ./abis/PublicLockV11.json - name: PublicLockV12 file: ./abis/PublicLockV12.json - - name: PublicLockV8 - file: ./abis/PublicLockV8.json - - name: PublicLockV7 - file: ./abis/PublicLockV7.json eventHandlers: - event: LockConfig(uint256,uint256,uint256) handler: handleLockConfig diff --git a/subgraph/tests/keys-v8.test.ts b/subgraph/tests/keys-v8.test.ts deleted file mode 100644 index 32ea85b6993..00000000000 --- a/subgraph/tests/keys-v8.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { - afterAll, - assert, - clearStore, - dataSourceMock, - describe, - test, -} from 'matchstick-as/assembly/index' -import { Address, BigInt } from '@graphprotocol/graph-ts' -import { - handleTransfer, - handleExpireKey, - handleExpirationChangedUntilV11, - handleKeyManagerChanged, - handleRenewKeyPurchase, -} from '../src/public-lock' -import { - createTransferEvent, - createExpirationChangedEventUntilV11, - createExpireKeyEvent, - createKeyManagerChangedEvent, - createRenewKeyPurchaseEvent, - mockDataSourceV8, - updateExpirationV8, -} from './keys-utils' -import { - keyOwnerAddress, - now, - nullAddress, - tokenId, - tokenURI, - expiration, - lockAddressV8, - lockManagers, -} from './constants' - -// mock contract functions -import './mocks' - -const keyIDV8 = `${lockAddressV8}-${tokenId}` - -describe('Key transfers (v8)', () => { - test('Creation of a new key (v8)', () => { - mockDataSourceV8() - const newTransferEvent = createTransferEvent( - Address.fromString(nullAddress), - Address.fromString(keyOwnerAddress), - BigInt.fromU32(tokenId) - ) - handleTransfer(newTransferEvent) - - assert.entityCount('Key', 1) - assert.fieldEquals('Key', keyIDV8, 'lock', lockAddressV8) - assert.fieldEquals('Key', keyIDV8, 'owner', keyOwnerAddress) - assert.fieldEquals('Key', keyIDV8, 'tokenId', `${tokenId}`) - assert.fieldEquals('Key', keyIDV8, 'tokenURI', `${tokenURI}`) - assert.fieldEquals('Key', keyIDV8, 'expiration', `${expiration}`) - assert.fieldEquals('Key', keyIDV8, 'createdAtBlock', '1') - assert.fieldEquals('Key', keyIDV8, 'createdAt', '1') - assert.fieldEquals('Key', keyIDV8, 'manager', lockManagers[0]) - }) - - afterAll(() => { - clearStore() - dataSourceMock.resetValues() - }) -}) - -describe('Change in expiration timestamp', () => { - test('should increase key timestamp (v8)', () => { - mockDataSourceV8() - // create a key - const newTransferEvent = createTransferEvent( - Address.fromString(nullAddress), - Address.fromString(keyOwnerAddress), - BigInt.fromU32(tokenId) - ) - handleTransfer(newTransferEvent) - - // mock and test - updateExpirationV8(BigInt.fromU64(expiration + 1000)) - const newExpirationEvent = createExpirationChangedEventUntilV11( - BigInt.fromU32(tokenId), - BigInt.fromU32(1000), - true - ) - - handleExpirationChangedUntilV11(newExpirationEvent) - assert.fieldEquals('Key', keyIDV8, 'expiration', `${expiration + 1000}`) - dataSourceMock.resetValues() - }) -}) - -describe('Key is expired by lock manager', () => { - test('should update the key expiration (v8)', () => { - mockDataSourceV8() - // create a key - const newTransferEvent = createTransferEvent( - Address.fromString(nullAddress), - Address.fromString(keyOwnerAddress), - BigInt.fromU32(tokenId) - ) - handleTransfer(newTransferEvent) - - // mock and test - updateExpirationV8() - const newExpireKeyEvent = createExpireKeyEvent(BigInt.fromU32(tokenId)) - - handleExpireKey(newExpireKeyEvent) - assert.fieldEquals('Key', keyIDV8, 'expiration', `${now}`) - dataSourceMock.resetValues() - }) -}) - -describe('Key managers', () => { - const newKeyManagerAddress = '0x0000000000000000000000000000000000000132' - - test('key manager changed (v8)', () => { - mockDataSourceV8() - - // create a key - const newTransferEvent = createTransferEvent( - Address.fromString(nullAddress), - Address.fromString(keyOwnerAddress), - BigInt.fromU32(tokenId) - ) - handleTransfer(newTransferEvent) - - const newKeyManagerChanged = createKeyManagerChangedEvent( - BigInt.fromU32(tokenId), - Address.fromString(newKeyManagerAddress) - ) - - handleKeyManagerChanged(newKeyManagerChanged) - assert.fieldEquals('Key', keyIDV8, 'manager', newKeyManagerAddress) - dataSourceMock.resetValues() - }) -}) - -describe('RenewKeyPurchase (lock { - test('extend a key by the correct time (v8)', () => { - mockDataSourceV8() - - // create a key - const newTransferEvent = createTransferEvent( - Address.fromString(nullAddress), - Address.fromString(keyOwnerAddress), - BigInt.fromU32(tokenId) - ) - handleTransfer(newTransferEvent) - - updateExpirationV8() - const newExpiration = expiration + 1000 - const newRenewKeyPurchase = createRenewKeyPurchaseEvent( - Address.fromString(keyOwnerAddress), - BigInt.fromU64(newExpiration) - ) - handleRenewKeyPurchase(newRenewKeyPurchase) - assert.fieldEquals('Key', keyIDV8, 'expiration', `${newExpiration}`) - dataSourceMock.resetValues() - }) -}) diff --git a/subgraph/tests/locks-v8.test.ts b/subgraph/tests/locks-v8.test.ts deleted file mode 100644 index a340754c9e8..00000000000 --- a/subgraph/tests/locks-v8.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { - assert, - describe, - test, - clearStore, - beforeAll, - afterAll, -} from 'matchstick-as/assembly/index' -import { Address } from '@graphprotocol/graph-ts' - -import { handleNewLock } from '../src/unlock' -import { - handleLockManagerAdded, - handleKeyGranterAdded, -} from '../src/public-lock' - -import { createNewLockEvent, mockDataSourceV8 } from './locks-utils' -import { - createKeyGranterAddedEvent, - createLockManagerAddedEvent, -} from './keys-utils' - -import { - duration, - lockManagers, - lockOwner, - nullAddress, - maxNumberOfKeys, - lockAddressV8, - keyGranters, -} from './constants' - -// mock contract functions -import './mocks' - -describe('Describe Locks events (v8)', () => { - beforeAll(() => { - mockDataSourceV8() - const newLockEvent = createNewLockEvent( - Address.fromString(lockOwner), - Address.fromString(lockAddressV8) - ) - handleNewLock(newLockEvent) - }) - test('Creation of a new lock (v8)', () => { - assert.entityCount('Lock', 1) - assert.fieldEquals('Lock', lockAddressV8, 'address', lockAddressV8) - assert.fieldEquals('Lock', lockAddressV8, 'createdAtBlock', '1') - assert.fieldEquals('Lock', lockAddressV8, 'version', '8') - assert.fieldEquals('Lock', lockAddressV8, 'price', '1000') - assert.fieldEquals('Lock', lockAddressV8, 'name', 'My lock v8') - assert.fieldEquals( - 'Lock', - lockAddressV8, - 'expirationDuration', - `${duration}` - ) - assert.fieldEquals('Lock', lockAddressV8, 'tokenAddress', nullAddress) - assert.fieldEquals('Lock', lockAddressV8, 'lockManagers', `[${lockOwner}]`) - assert.fieldEquals('Lock', lockAddressV8, 'keyGranters', `[${lockOwner}]`) - - assert.fieldEquals('Lock', lockAddressV8, 'totalKeys', '0') - assert.fieldEquals('Lock', lockAddressV8, 'numberOfReceipts', '0') - assert.fieldEquals( - 'Lock', - lockAddressV8, - 'maxNumberOfKeys', - `${maxNumberOfKeys}` - ) - assert.fieldEquals('Lock', lockAddressV8, 'maxKeysPerAddress', '1') - }) - - test('Lock manager added (v8)', () => { - mockDataSourceV8() - assert.fieldEquals('Lock', lockAddressV8, 'lockManagers', `[${lockOwner}]`) - const newLockManagerAdded = createLockManagerAddedEvent( - Address.fromString(lockManagers[0]) - ) - handleLockManagerAdded(newLockManagerAdded) - - assert.fieldEquals( - 'Lock', - lockAddressV8, - 'lockManagers', - `[${lockOwner}, ${lockManagers[0]}]` - ) - }) - - test('Key granter added (v8)', () => { - mockDataSourceV8() - assert.fieldEquals('Lock', lockAddressV8, 'keyGranters', `[${lockOwner}]`) - const newKeyGranterAdded = createKeyGranterAddedEvent( - Address.fromString(keyGranters[0]) - ) - handleKeyGranterAdded(newKeyGranterAdded) - - assert.fieldEquals( - 'Lock', - lockAddressV8, - 'keyGranters', - `[${lockOwner}, ${keyGranters[0]}]` - ) - }) - - afterAll(() => { - clearStore() - }) -}) From 24a5139a9cc82114643a140bace17d4f0d99afcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:25:31 +0200 Subject: [PATCH 13/27] delete LockSerializers --- governance/scripts/deployments/serializer.js | 26 -- governance/tasks/deploy.js | 6 - governance/test/scripts/deploy/lock.js | 9 +- .../src/abis/utils/LockSerializer.json | 247 ------------------ .../src/contracts/utils/LockSerializer.sol | 155 ----------- .../contracts/utils/LockSerializer.sol | 148 ----------- .../test/Lock/purchaseWithoutUnlock.js | 2 +- .../test/LockSerializer/_compareValues.js | 37 --- .../test/LockSerializer/serialize.js | 104 -------- 9 files changed, 2 insertions(+), 732 deletions(-) delete mode 100644 governance/scripts/deployments/serializer.js delete mode 100644 packages/contracts/src/abis/utils/LockSerializer.json delete mode 100644 packages/contracts/src/contracts/utils/LockSerializer.sol delete mode 100644 smart-contracts/contracts/utils/LockSerializer.sol delete mode 100644 smart-contracts/test/LockSerializer/_compareValues.js delete mode 100644 smart-contracts/test/LockSerializer/serialize.js diff --git a/governance/scripts/deployments/serializer.js b/governance/scripts/deployments/serializer.js deleted file mode 100644 index f9684e22a4f..00000000000 --- a/governance/scripts/deployments/serializer.js +++ /dev/null @@ -1,26 +0,0 @@ -const { ethers } = require('hardhat') - -async function main() { - const LockSerializer = await ethers.getContractFactory('LockSerializer') - const serializer = await LockSerializer.deploy() - await serializer.deployed() - - // eslint-disable-next-line no-console - console.log( - `SERIALIZER > deployed to : ${serializer.address} (tx: ${serializer.deployTransaction.hash})` - ) - - return serializer.address -} - -// execute as standalone -if (require.main === module) { - main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error) - process.exit(1) - }) -} - -module.exports = main diff --git a/governance/tasks/deploy.js b/governance/tasks/deploy.js index 3d9fa819d12..a3839265794 100644 --- a/governance/tasks/deploy.js +++ b/governance/tasks/deploy.js @@ -117,12 +117,6 @@ task('deploy:template', 'Deploy PublicLock contract') return await templateDeployer({ publicLockVersion }) }) -task('deploy:serializer', 'Deploy LockSerializer').setAction(async () => { - // eslint-disable-next-line global-require - const serializerDeployer = require('../scripts/deployments/serializer') - return await serializerDeployer() -}) - task('deploy:governor', 'Deploy governor contracts') .addParam('upAddress', 'address of the ERC20 token to use for governance') .addOptionalParam('timelockAddress', 'address of a timelock contract') diff --git a/governance/test/scripts/deploy/lock.js b/governance/test/scripts/deploy/lock.js index d0dd2bdeccc..757954d1d63 100644 --- a/governance/test/scripts/deploy/lock.js +++ b/governance/test/scripts/deploy/lock.js @@ -1,6 +1,6 @@ const { ethers } = require('hardhat') const { UnlockV9 } = require('@unlock-protocol/contracts') -const { PublicLockV8, LockSerializer } = require('@unlock-protocol/contracts') +const { PublicLockV8 } = require('@unlock-protocol/contracts') const assert = require('assert') const { @@ -75,13 +75,6 @@ describe('Scripts/deploy:lock', () => { .connect(unlockOwner) .setLockTemplate(await publicLock.getAddress()) - // deploy serializer - const LockSerializerFactory = await ethers.getContractFactory( - LockSerializer.abi, - LockSerializer.bytecode - ) - serializer = await LockSerializerFactory.deploy() - // deploy locks await Promise.all( Object.keys(Locks) diff --git a/packages/contracts/src/abis/utils/LockSerializer.json b/packages/contracts/src/abis/utils/LockSerializer.json deleted file mode 100644 index e4f9da31494..00000000000 --- a/packages/contracts/src/abis/utils/LockSerializer.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "LockSerializer", - "sourceName": "contracts/utils/LockSerializer.sol", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newLockAddress", - "type": "address" - } - ], - "name": "LockCLoned", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "lockAddress", - "type": "address" - } - ], - "name": "serialize", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "expirationDuration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "tokenURISample", - "type": "string" - }, - { - "internalType": "uint256", - "name": "publicLockVersion", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "numberOfOwners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "keyOwners", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "keyManagers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "expirationTimestamps", - "type": "uint256[]" - } - ], - "internalType": "struct LockSerializer.Lock", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IPublicLockV8", - "name": "lock", - "type": "address" - } - ], - "name": "serializeFees", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "freeTrialLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "refundPenaltyBasisPoints", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "transferFeeBasisPoints", - "type": "uint256" - } - ], - "internalType": "struct LockSerializer.LockFees", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IPublicLockV8", - "name": "lock", - "type": "address" - } - ], - "name": "serializeMetadata", - "outputs": [ - { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "string", - "name": "tokenURISample", - "type": "string" - } - ], - "internalType": "struct LockSerializer.LockMetadata", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IPublicLockV8", - "name": "lock", - "type": "address" - } - ], - "name": "serializePriceInfo", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "expirationDuration", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "keyPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxNumberOfKeys", - "type": "uint256" - }, - { - "internalType": "address", - "name": "beneficiary", - "type": "address" - } - ], - "internalType": "struct LockSerializer.LockPriceInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b50611318806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806347a277d9146100515780635d6da55b146100a9578063ccf8171a146100de578063eece4b1f146100fe575b600080fd5b61006461005f366004610eb9565b61011e565b6040516100a091908151815260208083015190820152604080830151908201526060918201516001600160a01b03169181019190915260800190565b60405180910390f35b6100bc6100b7366004610eb9565b610355565b60408051825181526020808401519082015291810151908201526060016100a0565b6100f16100ec366004610eb9565b6104f9565b6040516100a09190611077565b61011161010c366004610eb9565b610729565b6040516100a091906110d8565b610152604051806080016040528060008152602001600081526020016000815260200160006001600160a01b031681525090565b6000826001600160a01b03166311a4c03a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561018d57600080fd5b505afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c59190610fc1565b90506000836001600160a01b03166310e569736040518163ffffffff1660e01b815260040160206040518083038186803b15801561020257600080fd5b505afa158015610216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023a9190610fc1565b90506000846001600160a01b03166374b6c1066040518163ffffffff1660e01b815260040160206040518083038186803b15801561027757600080fd5b505afa15801561028b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102af9190610fc1565b90506000856001600160a01b03166338af3eed6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ec57600080fd5b505afa158015610300573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103249190610edc565b60408051608081018252958652602086019490945292840191909152506001600160a01b0316606082015292915050565b61037960405180606001604052806000815260200160008152602001600081525090565b6000826001600160a01b031663a375cb056040518163ffffffff1660e01b815260040160206040518083038186803b1580156103b457600080fd5b505afa1580156103c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ec9190610fc1565b90506000836001600160a01b03166356e0d51f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561042957600080fd5b505afa15801561043d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104619190610fc1565b90506000846001600160a01b031663183767da6040518163ffffffff1660e01b815260040160206040518083038186803b15801561049e57600080fd5b505afa1580156104b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d69190610fc1565b604080516060810182529485526020850193909352918301919091525092915050565b61051d60405180606001604052806060815260200160608152602001606081525090565b6000826001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561055857600080fd5b505afa15801561056c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105949190810190610f18565b90506000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156105d157600080fd5b505afa1580156105e5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261060d9190810190610f18565b90506000846001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064a57600080fd5b505afa15801561065e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106829190610fc1565b60405163c87b56dd60e01b8152600481018290529091506000906001600160a01b0387169063c87b56dd9060240160006040518083038186803b1580156106c857600080fd5b505afa1580156106dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107049190810190610f18565b6040805160608101825295865260208601949094529284019290925250909392505050565b6107c260405180610220016040528060008152602001600081526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016060815260200160608152602001606081526020016000815260200160006001600160a01b0316815260200160008152602001600081526020016060815260200160608152602001606081525090565b6000829050806001600160a01b0316634136aa356040518163ffffffff1660e01b815260040160206040518083038186803b15801561080057600080fd5b505afa158015610814573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108389190610ef8565b15156001146108995760405162461bcd60e51b815260206004820152602360248201527f44697361626c6564206c6f636b2063616e206e6f742062652073657269616c696044820152621e995960ea1b606482015260840160405180910390fd5b60006108a4826104f9565b905060006108b183610355565b905060006108be8461011e565b90506000846001600160a01b031663d1bbd49c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108fb57600080fd5b505afa15801561090f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109339190610fc1565b90506000856001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801561097057600080fd5b505afa158015610984573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a89190610edc565b90506000866001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109e557600080fd5b505afa1580156109f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1d9190610fc1565b90506000876001600160a01b03166393fd18446040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5a57600080fd5b505afa158015610a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a929190610fc1565b905060008267ffffffffffffffff811115610abd57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610ae6578160200160208202803683370190505b50905060008367ffffffffffffffff811115610b1257634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610b3b578160200160208202803683370190505b50905060008467ffffffffffffffff811115610b6757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610b90578160200160208202803683370190505b50905060005b85811015610e06576000610bab82600161123b565b6040516331a9108f60e11b8152600481018290529091506001600160a01b038e1690636352211e9060240160206040518083038186803b158015610bee57600080fd5b505afa158015610c02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c269190610edc565b858381518110610c4657634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508c6001600160a01b031663abdf82ce868481518110610c9557634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b8152600401610cc891906001600160a01b0391909116815260200190565b60206040518083038186803b158015610ce057600080fd5b505afa158015610cf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d189190610fc1565b838381518110610d3857634e487b7160e01b600052603260045260246000fd5b6020908102919091010152604051634d025fed60e01b8152600481018290526001600160a01b038e1690634d025fed9060240160206040518083038186803b158015610d8357600080fd5b505afa158015610d97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbb9190610edc565b848381518110610ddb57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101525080610dfe81611283565b915050610b96565b506040805161022081018252895181526020808b0151818301528a8301518284015260609a8b01516001600160a01b039081169b83019b909b528b5160808301528b81015160a08301529a82015160c08201528b5160e0820152998b01516101008b01529990990151610120890152610140880195909552929094166101608601526101808501939093526101a08401929092526101c08301919091526101e08201526102008101919091529392505050565b600060208284031215610eca578081fd5b8135610ed5816112ca565b9392505050565b600060208284031215610eed578081fd5b8151610ed5816112ca565b600060208284031215610f09578081fd5b81518015158114610ed5578182fd5b600060208284031215610f29578081fd5b815167ffffffffffffffff80821115610f40578283fd5b818401915084601f830112610f53578283fd5b815181811115610f6557610f656112b4565b604051601f8201601f19908116603f01168101908382118183101715610f8d57610f8d6112b4565b81604052828152876020848701011115610fa5578586fd5b610fb6836020830160208801611253565b979650505050505050565b600060208284031215610fd2578081fd5b5051919050565b6000815180845260208085019450808401835b838110156110115781516001600160a01b031687529582019590820190600101610fec565b509495945050505050565b6000815180845260208085019450808401835b838110156110115781518752958201959082019060010161102f565b60008151808452611063816020860160208601611253565b601f01601f19169290920160200192915050565b602081526000825160606020840152611093608084018261104b565b90506020840151601f19808584030160408601526110b1838361104b565b92506040860151915080858403016060860152506110cf828261104b565b95945050505050565b602081528151602082015260208201516040820152604082015160608201526000606083015161111360808401826001600160a01b03169052565b50608083015160a083015260a083015160c083015260c083015160e083015260e0830151610220610100818186015261115061024086018461104b565b9250808601519050601f19610120818786030181880152611171858461104b565b945080880151925050610140818786030181880152611190858461104b565b908801516101608881019190915288015190945091506101806111bd818801846001600160a01b03169052565b8701516101a0878101919091528701516101c08088019190915287015186850382016101e0808901919091529092506111f68584610fd9565b9450808801519250506102008187860301818801526112158584610fd9565b908801518782039092018488015293509050611231838261101c565b9695505050505050565b6000821982111561124e5761124e61129e565b500190565b60005b8381101561126e578181015183820152602001611256565b8381111561127d576000848401525b50505050565b60006000198214156112975761129761129e565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146112df57600080fd5b5056fea2646970667358221220bd11855a09f377c5d0d161b6f2fd77830d556efef6da5ea2047c4488a6e6fe6064736f6c63430008040033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/packages/contracts/src/contracts/utils/LockSerializer.sol b/packages/contracts/src/contracts/utils/LockSerializer.sol deleted file mode 100644 index 2ce4b23784f..00000000000 --- a/packages/contracts/src/contracts/utils/LockSerializer.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.2; - -import "hardhat/console.sol"; -import "../PublicLock/IPublicLockV8sol8.sol"; - -contract LockSerializer { - constructor() {} - - event LockCLoned(address newLockAddress); - - struct Lock { - // priceInfo - uint expirationDuration; - uint keyPrice; - uint maxNumberOfKeys; - address beneficiary; - // fees - uint256 freeTrialLength; - uint256 refundPenaltyBasisPoints; - uint256 transferFeeBasisPoints; - // metadata - string name; - string symbol; - string tokenURISample; - // protocol - uint publicLockVersion; - address tokenAddress; - // ownerhsip - uint numberOfOwners; - uint256 totalSupply; - address[] keyOwners; - address[] keyManagers; - uint[] expirationTimestamps; - // address lockCreator; - } - - // We split in multiple structs to avoid "Stack To Deep" solc - struct LockPriceInfo { - // fees - uint expirationDuration; - uint keyPrice; - uint maxNumberOfKeys; - address beneficiary; - } - - struct LockFees { - // fees - uint256 freeTrialLength; - uint256 refundPenaltyBasisPoints; - uint256 transferFeeBasisPoints; - } - - struct LockMetadata { - // metadata - string name; - string symbol; - string tokenURISample; - } - - function serializePriceInfo( - IPublicLockV8 lock - ) public view returns (LockPriceInfo memory) { - uint expirationDuration = lock.expirationDuration(); - uint keyPrice = lock.keyPrice(); - uint maxNumberOfKeys = lock.maxNumberOfKeys(); - address beneficiary = lock.beneficiary(); - return - LockPriceInfo(expirationDuration, keyPrice, maxNumberOfKeys, beneficiary); - } - - function serializeFees( - IPublicLockV8 lock - ) public view returns (LockFees memory) { - uint256 freeTrialLength = lock.freeTrialLength(); - uint256 refundPenaltyBasisPoints = lock.refundPenaltyBasisPoints(); - uint256 transferFeeBasisPoints = lock.transferFeeBasisPoints(); - return - LockFees( - freeTrialLength, - refundPenaltyBasisPoints, - transferFeeBasisPoints - ); - } - - function serializeMetadata( - IPublicLockV8 lock - ) public view returns (LockMetadata memory) { - string memory name = lock.name(); - string memory symbol = lock.symbol(); - - // get the latest TokenURI to use as sample - uint totalSupply = lock.totalSupply(); - string memory tokenURISample = lock.tokenURI(totalSupply); - - return LockMetadata(name, symbol, tokenURISample); - } - - function serialize(address lockAddress) public view returns (Lock memory) { - IPublicLockV8 lock = IPublicLockV8(lockAddress); - require(lock.isAlive() == true, "Disabled lock can not be serialized"); - - LockMetadata memory metadata = serializeMetadata(lock); - LockFees memory fees = serializeFees(lock); - LockPriceInfo memory priceInfo = serializePriceInfo(lock); - - // protocol - uint publicLockVersion = lock.publicLockVersion(); - address tokenAddress = lock.tokenAddress(); - - // ownership - uint256 totalSupply = lock.totalSupply(); - uint numberOfOwners = lock.numberOfOwners(); - - // keys - address[] memory keyOwners = new address[](totalSupply); - address[] memory keyManagers = new address[](totalSupply); - uint[] memory expirationTimestamps = new uint[](totalSupply); - - // tokenId starts at 1, so totalSupply + 1 is needed - for (uint256 i = 0; i < totalSupply; i++) { - uint256 tokenId = i + 1; - keyOwners[i] = lock.ownerOf(tokenId); - expirationTimestamps[i] = lock.keyExpirationTimestampFor(keyOwners[i]); - keyManagers[i] = lock.keyManagerOf(tokenId); - } - - Lock memory serializedLock = Lock( - // keys - priceInfo.expirationDuration, - priceInfo.keyPrice, - priceInfo.maxNumberOfKeys, - priceInfo.beneficiary, - // fees - fees.freeTrialLength, - fees.refundPenaltyBasisPoints, - fees.transferFeeBasisPoints, - // metadata - metadata.name, - metadata.symbol, - metadata.tokenURISample, - // protocol - publicLockVersion, - tokenAddress, - // ownerhsip - numberOfOwners, - totalSupply, - keyOwners, - keyManagers, - expirationTimestamps - ); - - return serializedLock; - } -} diff --git a/smart-contracts/contracts/utils/LockSerializer.sol b/smart-contracts/contracts/utils/LockSerializer.sol deleted file mode 100644 index 0151d9c10df..00000000000 --- a/smart-contracts/contracts/utils/LockSerializer.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.2; - -import "../interfaces/IPublicLock.sol"; - -contract LockSerializer { - constructor() {} - - event LockCLoned(address newLockAddress); - - struct Lock { - // priceInfo - uint expirationDuration; - uint keyPrice; - uint maxNumberOfKeys; - // fees - uint256 freeTrialLength; - uint256 refundPenaltyBasisPoints; - uint256 transferFeeBasisPoints; - // metadata - string name; - string symbol; - string tokenURISample; - // protocol - uint publicLockVersion; - address tokenAddress; - // ownerhsip - uint numberOfOwners; - uint256 totalSupply; - address[] keyOwners; - address[] keyManagers; - uint[] expirationTimestamps; - // address lockCreator; - } - - // We split in multiple structs to avoid "Stack To Deep" solc - struct LockPriceInfo { - // fees - uint expirationDuration; - uint keyPrice; - uint maxNumberOfKeys; - } - - struct LockFees { - // fees - uint256 freeTrialLength; - uint256 refundPenaltyBasisPoints; - uint256 transferFeeBasisPoints; - } - - struct LockMetadata { - // metadata - string name; - string symbol; - string tokenURISample; - } - - function serializePriceInfo( - IPublicLock lock - ) public view returns (LockPriceInfo memory) { - uint expirationDuration = lock.expirationDuration(); - uint keyPrice = lock.keyPrice(); - uint maxNumberOfKeys = lock.maxNumberOfKeys(); - return LockPriceInfo(expirationDuration, keyPrice, maxNumberOfKeys); - } - - function serializeFees( - IPublicLock lock - ) public view returns (LockFees memory) { - uint256 freeTrialLength = lock.freeTrialLength(); - uint256 refundPenaltyBasisPoints = lock.refundPenaltyBasisPoints(); - uint256 transferFeeBasisPoints = lock.transferFeeBasisPoints(); - return - LockFees( - freeTrialLength, - refundPenaltyBasisPoints, - transferFeeBasisPoints - ); - } - - function serializeMetadata( - IPublicLock lock - ) public view returns (LockMetadata memory) { - string memory name = lock.name(); - string memory symbol = lock.symbol(); - - // get the latest TokenURI to use as sample - uint totalSupply = lock.totalSupply(); - string memory tokenURISample = lock.tokenURI(totalSupply); - - return LockMetadata(name, symbol, tokenURISample); - } - - function serialize(address lockAddress) public view returns (Lock memory) { - IPublicLock lock = IPublicLock(lockAddress); - - LockMetadata memory metadata = serializeMetadata(lock); - LockFees memory fees = serializeFees(lock); - LockPriceInfo memory priceInfo = serializePriceInfo(lock); - - // protocol - uint publicLockVersion = lock.publicLockVersion(); - address tokenAddress = lock.tokenAddress(); - - // ownership - uint256 totalSupply = lock.totalSupply(); - uint numberOfOwners = lock.numberOfOwners(); - - // keys - address[] memory keyOwners = new address[](totalSupply); - address[] memory keyManagers = new address[](totalSupply); - uint[] memory expirationTimestamps = new uint[](totalSupply); - - // tokenId starts at 1, so totalSupply + 1 is needed - for (uint256 i = 0; i < totalSupply; i++) { - uint256 tokenId = i + 1; - keyOwners[i] = lock.ownerOf(tokenId); - expirationTimestamps[i] = lock.keyExpirationTimestampFor(tokenId); - keyManagers[i] = lock.keyManagerOf(tokenId); - } - - Lock memory serializedLock = Lock( - // keys - priceInfo.expirationDuration, - priceInfo.keyPrice, - priceInfo.maxNumberOfKeys, - // fees - fees.freeTrialLength, - fees.refundPenaltyBasisPoints, - fees.transferFeeBasisPoints, - // metadata - metadata.name, - metadata.symbol, - metadata.tokenURISample, - // protocol - publicLockVersion, - tokenAddress, - // ownerhsip - numberOfOwners, - totalSupply, - keyOwners, - keyManagers, - expirationTimestamps - ); - - return serializedLock; - } -} diff --git a/smart-contracts/test/Lock/purchaseWithoutUnlock.js b/smart-contracts/test/Lock/purchaseWithoutUnlock.js index 003138e9910..891b7765e0c 100644 --- a/smart-contracts/test/Lock/purchaseWithoutUnlock.js +++ b/smart-contracts/test/Lock/purchaseWithoutUnlock.js @@ -11,7 +11,7 @@ const keyPrice = ethers.parseEther('0.01') const breakUnlock = async (unlockAddress) => { // deploy a random contract to break Unlock implementation - const BrokenUnlock = await ethers.getContractFactory('LockSerializer') + const BrokenUnlock = await ethers.getContractFactory('KeyManager') await upgrades.upgradeProxy(unlockAddress, BrokenUnlock, { unsafeSkipStorageCheck: true, }) diff --git a/smart-contracts/test/LockSerializer/_compareValues.js b/smart-contracts/test/LockSerializer/_compareValues.js deleted file mode 100644 index 4add0860f74..00000000000 --- a/smart-contracts/test/LockSerializer/_compareValues.js +++ /dev/null @@ -1,37 +0,0 @@ -const assert = require('assert') -const { ethers } = require('hardhat') - -const compareValues = async (serialized, lock) => { - const arrays = [ - 'keyOwners', - 'expirationTimestamps', - 'keyManagers', - 'tokenURISample', - ] - const propNames = Object.keys(serialized) - .filter((k) => Number.isNaN(Number.parseInt(k))) // remove numbers from array index - .filter((k) => !arrays.includes(k)) // exclude arrays - const values = await Promise.all(propNames.map((k) => lock[k]())) - - // assertions - propNames.forEach((k, i) => { - if ( - ethers.BigNumber.isBigNumber(serialized[k]) && - ethers.BigNumber.isBigNumber(values[i]) - ) { - assert.equal( - serialized[k] == values[i], - true, - `different serialized value ${k}, ${serialized[k]}, ${values[i]}` - ) - } else { - assert.equal( - serialized[k], - values[i], - `different serialized value ${k}, ${serialized[k]}, ${values[i]}` - ) - } - }) -} - -module.exports = compareValues diff --git a/smart-contracts/test/LockSerializer/serialize.js b/smart-contracts/test/LockSerializer/serialize.js deleted file mode 100644 index 33ec7d0c5ca..00000000000 --- a/smart-contracts/test/LockSerializer/serialize.js +++ /dev/null @@ -1,104 +0,0 @@ -const assert = require('assert') -const { ethers } = require('hardhat') -const compareValues = require('./_compareValues') - -const { deployLock, ADDRESS_ZERO } = require('../helpers') - -describe('LockSerializer', () => { - let lock - let serializer - let lockOwner - let keyOwner - - beforeEach(async () => { - ;[lockOwner, keyOwner] = await ethers.getSigners() - - // deploy serializer - const LockSerializer = await ethers.getContractFactory('LockSerializer') - serializer = await LockSerializer.deploy() - - // get locks (truffle version) - lock = await deployLock() - }) - - describe('serialize', () => { - it('deserialize values properly', async () => { - const serialized = await serializer.serialize(await lock.getAddress()) - await compareValues(serialized, lock) - }) - - it('fetch a sample of the tokenURI properly', async () => { - const keyPrice = ethers.parseEther('0.01') - const baseTokenURI = 'https://hahaha.com/' - - // purchase a key - const tx = await lock - .connect(keyOwner) - .purchase( - [keyPrice], - [await keyOwner.getAddress()], - [ADDRESS_ZERO], - [ADDRESS_ZERO], - ['0x'], - { value: keyPrice } - ) - await tx.wait() - - const totalSupply = await lock.totalSupply() - - // default URI - const serialized = await serializer.serialize(await lock.getAddress()) - await assert.equal( - serialized.tokenURISample, - `${(await lock.getAddress()).toLowerCase()}/${totalSupply}` - ) - - // custom URI - await lock - .connect(lockOwner) - .setLockMetadata(await lock.name(), await lock.symbol(), baseTokenURI) - const serializedCustomBaseURI = await serializer.serialize( - await lock.getAddress() - ) - await assert.equal( - serializedCustomBaseURI.tokenURISample, - `${baseTokenURI}${totalSupply}` - ) - }) - - describe('key ownership', () => { - let purchasers - const keyPrice = ethers.parseEther('0.01') - - // eslint-disable-next-line func-names - beforeEach(async function () { - const [, ..._purchasers] = await ethers.getSigners() - const maxNumberOfKeys = await lock.maxNumberOfKeys() - purchasers = _purchasers.slice(0, parseInt(maxNumberOfKeys.toString())) // prevent soldout revert - - // purchase keys - await lock.connect(purchasers[0]).purchase( - [], - await Promise.all(purchasers.map((p) => p.getAddress())), - purchasers.map(() => ADDRESS_ZERO), - purchasers.map(() => ADDRESS_ZERO), - purchasers.map(() => '0x'), - { value: keyPrice * BigInt(purchasers.length) } - ) - }) - - it('contains all key owners', async () => { - const serialized = await serializer.serialize(await lock.getAddress()) - assert.deepEqual( - serialized.keyOwners, - await Promise.all(purchasers.map((p) => p.getAddress())) - ) - }) - - it('containes key expirations', async () => { - const serialized = await serializer.serialize(await lock.getAddress()) - assert.equal(serialized.expirationTimestamps.length, purchasers.length) - }) - }) - }) -}) From 0ae7eefdd82abe4ea7e97682855b392d6aaedc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:36:24 +0200 Subject: [PATCH 14/27] skip lock test for now --- governance/test/scripts/deploy/lock.js | 2 +- tests/subgraph.test.yaml | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/governance/test/scripts/deploy/lock.js b/governance/test/scripts/deploy/lock.js index 757954d1d63..ef1f7a686b7 100644 --- a/governance/test/scripts/deploy/lock.js +++ b/governance/test/scripts/deploy/lock.js @@ -43,7 +43,7 @@ const compareValues = async (serialized, lock) => { }) } -describe('Scripts/deploy:lock', () => { +describe.skip('Scripts/deploy:lock', () => { let serializer let unlockAddress let PublicLock diff --git a/tests/subgraph.test.yaml b/tests/subgraph.test.yaml index 9aa97f67d0a..607473ca117 100644 --- a/tests/subgraph.test.yaml +++ b/tests/subgraph.test.yaml @@ -24,8 +24,6 @@ dataSources: file: ./abis/PublicLock.json - name: PublicLockV11 file: ./abis/PublicLockV11.json - - name: PublicLockV7 - file: ./abis/PublicLockV7.json eventHandlers: - event: NewLock(indexed address,indexed address) handler: handleNewLock @@ -61,10 +59,6 @@ templates: file: ./abis/PublicLockV11.json - name: PublicLockV12 file: ./abis/PublicLockV12.json - - name: PublicLockV8 - file: ./abis/PublicLockV8.json - - name: PublicLockV7 - file: ./abis/PublicLockV7.json eventHandlers: - event: LockConfig(uint256,uint256,uint256) handler: handleLockConfig From ece07c16bb8268c3873e433ff425ef3efcbb723e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:38:54 +0200 Subject: [PATCH 15/27] add missing udt solc --- packages/contracts/hardhat.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/contracts/hardhat.config.js b/packages/contracts/hardhat.config.js index 899589058fc..3a1ef746c43 100644 --- a/packages/contracts/hardhat.config.js +++ b/packages/contracts/hardhat.config.js @@ -33,6 +33,7 @@ const settings = { module.exports = { solidity: { compilers: [ + { version: '0.5.17', settings }, { version: '0.7.6', settings }, { version: '0.8.0', settings }, { version: '0.8.2', settings }, From bad9ccb4971036f14835fbd29a7fb41f3e84244f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:40:49 +0200 Subject: [PATCH 16/27] fix contracts exports test --- packages/contracts/test/exports.test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/contracts/test/exports.test.js b/packages/contracts/test/exports.test.js index 158bf3154d3..e8e98546211 100644 --- a/packages/contracts/test/exports.test.js +++ b/packages/contracts/test/exports.test.js @@ -10,14 +10,14 @@ describe('main exports', () => { const contracts = require('../dist') assert.notEqual(Object.keys(contracts).length, 0) - const v0 = require('../dist/abis/Unlock/UnlockV0.json') - assert.equal(v0.contractName, 'Unlock') - assert(Object.keys(v0).includes('abi')) - assert(Object.keys(v0).includes('bytecode')) + const v10 = require('../dist/abis/Unlock/UnlockV10.json') + assert.equal(v10.contractName, 'Unlock') + assert(Object.keys(v10).includes('abi')) + assert(Object.keys(v10).includes('bytecode')) - const { UnlockV0 } = require('../dist') - assert.equal(UnlockV0.contractName, 'Unlock') - assert(Object.keys(UnlockV0).includes('abi')) - assert(Object.keys(UnlockV0).includes('bytecode')) + const { UnlockV10 } = require('../dist') + assert.equal(UnlockV10.contractName, 'Unlock') + assert(Object.keys(UnlockV10).includes('abi')) + assert(Object.keys(UnlockV10).includes('bytecode')) }) }) From 4eee722460ef26993ffa1e6cbf9c0bb894e5381b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:45:11 +0200 Subject: [PATCH 17/27] remove v9 imports in contracts --- smart-contracts/contracts/hooks/ERC1155BalanceOfHook.sol | 4 ++-- smart-contracts/contracts/hooks/ERC20BalanceOfHook.sol | 4 ++-- smart-contracts/contracts/hooks/ERC721BalanceOfHook.sol | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/smart-contracts/contracts/hooks/ERC1155BalanceOfHook.sol b/smart-contracts/contracts/hooks/ERC1155BalanceOfHook.sol index c7e4085d9e1..95312272a81 100644 --- a/smart-contracts/contracts/hooks/ERC1155BalanceOfHook.sol +++ b/smart-contracts/contracts/hooks/ERC1155BalanceOfHook.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; -import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV9.sol"; +import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV14.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; contract ERC1155BalanceOfHook { @@ -20,7 +20,7 @@ contract ERC1155BalanceOfHook { require(_nftAddress != address(0), "ERC1155 address can not be zero"); // make sure lock manager - IPublicLockV9 lock = IPublicLockV9(_lockAddress); + IPublicLockV14 lock = IPublicLockV14(_lockAddress); require( lock.isLockManager(msg.sender), "Caller does not have the LockManager role" diff --git a/smart-contracts/contracts/hooks/ERC20BalanceOfHook.sol b/smart-contracts/contracts/hooks/ERC20BalanceOfHook.sol index 40ffe488955..059fdfcf2a9 100644 --- a/smart-contracts/contracts/hooks/ERC20BalanceOfHook.sol +++ b/smart-contracts/contracts/hooks/ERC20BalanceOfHook.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; -import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV9.sol"; +import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV14.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract ERC20BalanceOfHook { @@ -18,7 +18,7 @@ contract ERC20BalanceOfHook { require(_minAmount != 0, "minAmount can not be zero"); // make sure lock manager - IPublicLockV9 lock = IPublicLockV9(_lockAddress); + IPublicLockV14 lock = IPublicLockV14(_lockAddress); require( lock.isLockManager(msg.sender), "Caller does not have the LockManager role" diff --git a/smart-contracts/contracts/hooks/ERC721BalanceOfHook.sol b/smart-contracts/contracts/hooks/ERC721BalanceOfHook.sol index 89f1d67a89d..37b4b11eded 100644 --- a/smart-contracts/contracts/hooks/ERC721BalanceOfHook.sol +++ b/smart-contracts/contracts/hooks/ERC721BalanceOfHook.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; -import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV9.sol"; +import "@unlock-protocol/contracts/dist/PublicLock/IPublicLockV14.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract ERC721BalanceOfHook { @@ -12,7 +12,7 @@ contract ERC721BalanceOfHook { require(_nftAddress != address(0), "ERC721 address can not be zero"); // make sure lock manager - IPublicLockV9 lock = IPublicLockV9(_lockAddress); + IPublicLockV14 lock = IPublicLockV14(_lockAddress); require( lock.isLockManager(msg.sender), "Caller does not have the LockManager role" From c79fed14f00af2d6d2dd61d15125a3748b775991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 14:48:41 +0200 Subject: [PATCH 18/27] subgraph remove v7 from helpers --- subgraph/src/helpers.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/subgraph/src/helpers.ts b/subgraph/src/helpers.ts index 63852e348c2..84f8215d7fd 100644 --- a/subgraph/src/helpers.ts +++ b/subgraph/src/helpers.ts @@ -1,6 +1,5 @@ import { Address, BigInt } from '@graphprotocol/graph-ts' import { PublicLockV11 } from '../generated/templates/PublicLock/PublicLockV11' -import { PublicLockV7 } from '../generated/templates/PublicLock/PublicLockV7' import { UnlockDailyData, UnlockStats, Key } from '../generated/schema' // keccak 256 of 'LOCK_MANAGER' @@ -37,12 +36,6 @@ export function getKeyExpirationTimestampFor( if (!response.reverted) { return response.value } - } else { - const lockContract = PublicLockV7.bind(lockAddress) - const response = lockContract.try_keyExpirationTimestampFor(ownerAddress) - if (!response.reverted) { - return response.value - } } return BigInt.fromI32(0) } @@ -81,7 +74,7 @@ export function getKeyManagerOf( tokenId: BigInt, owner: Address ): Address { - const lockContract = PublicLockV7.bind(lockAddress) + const lockContract = PublicLockV11.bind(lockAddress) const response = lockContract.try_keyManagerOf(tokenId) if (!response.reverted) { return response.value From 7c4a7f7163dae570ea0afaeda9af259a6af19756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 15:27:59 +0200 Subject: [PATCH 19/27] unlockjs: remove unlock config > v10 --- .../src/__tests__/helpers/configureUnlock.js | 148 +----------------- 1 file changed, 4 insertions(+), 144 deletions(-) diff --git a/packages/unlock-js/src/__tests__/helpers/configureUnlock.js b/packages/unlock-js/src/__tests__/helpers/configureUnlock.js index 7ba55b3edac..ee1692408ce 100644 --- a/packages/unlock-js/src/__tests__/helpers/configureUnlock.js +++ b/packages/unlock-js/src/__tests__/helpers/configureUnlock.js @@ -31,20 +31,10 @@ export default async ( function getConfigure(version) { switch (version) { - case 'v4': - return configureUnlockV4 - case 'v6': - return configureUnlockV6 - case 'v7': - return configureUnlockV7 - case 'v8': - return configureUnlockV8 - case 'v9': - return configureUnlockV9 case 'v10': - return configureUnlockV9 + return configureUnlockV10 case 'v11': - return configureUnlockV9 + return configureUnlockV10 case 'v12': return configureUnlockV12 default: @@ -53,143 +43,13 @@ function getConfigure(version) { } /** - * Configures unlock version v4 + * Configures unlock version v10 * @param {PropTypes.lock} publicLockTemplateAddress * @param {PropTypes.string} globalTokenSymbol * @param {PropTypes.string} globalBaseTokenURI * @param {function} callback invoked with the transaction hash */ -async function configureUnlockV4( - unlockContract, - { publicLockTemplateAddress, globalTokenSymbol, globalBaseTokenURI }, - transactionOptions = {}, - callback -) { - const { ethers } = hre - const transaction = await unlockContract.configUnlock( - publicLockTemplateAddress, - globalTokenSymbol, - globalBaseTokenURI, - transactionOptions - ) - - if (callback) { - callback(null, transaction.hash) - } - - return ethers.provider.waitForTransaction(transaction.hash) -} - -/** - * Configures unlock version v6 - * @param {PropTypes.lock} publicLockTemplateAddress - * @param {PropTypes.string} globalTokenSymbol - * @param {PropTypes.string} globalBaseTokenURI - * @param {function} callback invoked with the transaction hash - */ -async function configureUnlockV6( - unlockContract, - { publicLockTemplateAddress, globalTokenSymbol, globalBaseTokenURI }, - transactionOptions = {}, - callback -) { - const { ethers } = hre - const transaction = await unlockContract.configUnlock( - publicLockTemplateAddress, - globalTokenSymbol, - globalBaseTokenURI - ) - - if (callback) { - callback(null, transaction.hash) - } - - return ethers.provider.waitForTransaction(transaction.hash) -} - -/** - * Configures unlock version v7 - * @param {PropTypes.lock} publicLockTemplateAddress - * @param {PropTypes.string} globalTokenSymbol - * @param {PropTypes.string} globalBaseTokenURI - * @param {function} callback invoked with the transaction hash - */ -async function configureUnlockV7( - unlockContract, - { publicLockTemplateAddress, globalTokenSymbol, globalBaseTokenURI }, - transactionOptions = {}, - callback -) { - const { ethers } = hre - const configTransaction = await unlockContract.configUnlock( - globalTokenSymbol, - globalBaseTokenURI - ) - if (callback) { - callback(null, configTransaction.hash) - } - ethers.provider.waitForTransaction(configTransaction.hash) - - const deployTemplateTransaction = await unlockContract.setLockTemplate( - publicLockTemplateAddress - ) - - if (callback) { - callback(null, deployTemplateTransaction.hash) - } - return ethers.provider.waitForTransaction(deployTemplateTransaction.hash) -} -/** - * Configures unlock version v8 - * @param {PropTypes.lock} publicLockTemplateAddress - * @param {PropTypes.string} globalTokenSymbol - * @param {PropTypes.string} globalBaseTokenURI - * @param {function} callback invoked with the transaction hash - */ -async function configureUnlockV8( - unlockContract, - { - publicLockTemplateAddress, - globalTokenSymbol, - globalBaseTokenURI, - unlockDiscountToken, - wrappedEth, - estimatedGasForPurchase, - }, - transactionOptions = {}, - callback -) { - const { ethers } = hre - const configTransaction = await unlockContract.configUnlock( - unlockDiscountToken, - wrappedEth, - estimatedGasForPurchase, - globalTokenSymbol, - globalBaseTokenURI - ) - if (callback) { - callback(null, configTransaction.hash) - } - ethers.provider.waitForTransaction(configTransaction.hash) - - const deployTemplateTransaction = await unlockContract.setLockTemplate( - publicLockTemplateAddress - ) - - if (callback) { - callback(null, deployTemplateTransaction.hash) - } - return ethers.provider.waitForTransaction(deployTemplateTransaction.hash) -} - -/** - * Configures unlock version v9 - * @param {PropTypes.lock} publicLockTemplateAddress - * @param {PropTypes.string} globalTokenSymbol - * @param {PropTypes.string} globalBaseTokenURI - * @param {function} callback invoked with the transaction hash - */ -async function configureUnlockV9( +async function configureUnlockV10( unlockContract, { publicLockTemplateAddress, From 25cc6b171bcdcf7986a751356b00877a0560baf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 15:30:12 +0200 Subject: [PATCH 20/27] remove lock v9 from smart contracts --- smart-contracts/test/Lock/upgrades/v10.js | 262 ---------------------- smart-contracts/test/helpers/versions.js | 4 +- 2 files changed, 2 insertions(+), 264 deletions(-) delete mode 100644 smart-contracts/test/Lock/upgrades/v10.js diff --git a/smart-contracts/test/Lock/upgrades/v10.js b/smart-contracts/test/Lock/upgrades/v10.js deleted file mode 100644 index b0206885934..00000000000 --- a/smart-contracts/test/Lock/upgrades/v10.js +++ /dev/null @@ -1,262 +0,0 @@ -const assert = require('assert') -const { ethers, upgrades } = require('hardhat') -const { reverts } = require('../../helpers/errors') -const path = require('path') -const { - copyAndBuildContractsAtVersion, - cleanupContractVersions, - ADDRESS_ZERO, - getEvent, - getEvents, -} = require('@unlock-protocol/hardhat-helpers') - -const versionNumber = 9 -const keyPrice = ethers.parseEther('0.01') - -// pass proper root folder to helpers -const dirname = path.join(__dirname, '..') - -describe('PublicLock upgrade v9 > v10', () => { - let lock - let PublicLockLatest - let PublicLockPast - - after(async () => await cleanupContractVersions(dirname)) - - before(async function copyAndBuildContract() { - this.timeout(200000) - const [pathPublicLockPast, pathPublicLockLatest] = - await copyAndBuildContractsAtVersion(dirname, [ - { - contractName: 'PublicLock', - version: versionNumber, - }, - { - contractName: 'PublicLock', - version: versionNumber + 1, - }, - ]) - - PublicLockPast = await ethers.getContractFactory(pathPublicLockPast) - PublicLockLatest = await ethers.getContractFactory(pathPublicLockLatest) - - // deploy latest version - }) - - beforeEach(async () => { - const [, lockOwner] = await ethers.getSigners() - // deploy a simple lock - const args = [ - await lockOwner.getAddress(), - 60 * 60 * 24 * 30, // 30 days - ADDRESS_ZERO, - keyPrice, - 130, - 'A neat upgradeable lock!', - ] - - lock = await upgrades.deployProxy(PublicLockPast, args) - }) - - describe('perform upgrade', async () => { - let buyers - let tokenIds - let expirationTimestamps - let totalSupplyBefore - - beforeEach(async () => { - // buy some keys - const signers = await ethers.getSigners() - buyers = signers.slice(1, 11) - - // purchase many keys (in the correct order to make sure we can check them later) - for (let i = 0; i < buyers.length; i++) { - const keyOwner = buyers[i] - await lock - .connect(keyOwner) - .purchase( - 0, - await keyOwner.getAddress(), - ADDRESS_ZERO, - ADDRESS_ZERO, - '0x', - { - value: keyPrice, - } - ) - } - tokenIds = await Promise.all( - buyers.map(async (b) => lock.getTokenIdFor(await b.getAddress())) - ) - expirationTimestamps = await Promise.all( - buyers.map(async (b) => - lock.keyExpirationTimestampFor(await b.getAddress()) - ) - ) - - // make sure record is proper before upgrade - assert.equal(await lock.publicLockVersion(), 9) - assert.equal( - await lock.ownerOf(tokenIds[0]), - await buyers[0].getAddress() - ) - assert.equal(await lock.balanceOf(await buyers[0].getAddress()), 1) - - totalSupplyBefore = await lock.totalSupply() - - // deploy new implementation - lock = await upgrades.upgradeProxy( - await lock.getAddress(), - PublicLockLatest, - { - unsafeSkipStorageCheck: true, // UNSECURE - but we need the flag as we are resizing the `__gap` - } - ) - - // make sure ownership is preserved - assert.equal( - await lock.ownerOf(tokenIds[0]), - await buyers[0].getAddress() - ) - - // set many keys - const [, lockOwner] = await ethers.getSigners() - await lock.connect(lockOwner).setMaxKeysPerAddress(10) - }) - - it('upgraded successfully ', async () => { - assert.equal(await lock.publicLockVersion(), 10) - }) - - describe('without migrating data', () => { - it('purchase should fail ', async () => { - await reverts( - lock.connect(buyers[0]).purchase( - [], - await Promise.all(buyers.map((k) => k.getAddress())), - buyers.map(() => ADDRESS_ZERO), - buyers.map(() => ADDRESS_ZERO), - buyers.map(() => '0x'), - { - value: keyPrice * BigInt(buyers.length), - } - ), - 'MIGRATION_REQUIRED' - ) - }) - it('grantKeys should fail ', async () => { - await reverts( - lock.connect(buyers[0]).grantKeys( - await Promise.all(buyers.map((k) => k.getAddress())), - buyers.map(() => Date.now()), - buyers.map(() => ADDRESS_ZERO) - ), - 'MIGRATION_REQUIRED' - ) - }) - it('extend should fail ', async () => { - await reverts( - lock.connect(buyers[0]).extend(0, tokenIds[0], ADDRESS_ZERO, '0x', { - value: keyPrice, - }), - 'MIGRATION_REQUIRED' - ) - }) - }) - - it('totalSupply is preserved', async () => { - assert.equal(totalSupplyBefore, await lock.totalSupply()) - }) - - it('schemaVersion is undefined before migration', async () => { - assert.equal(await lock.schemaVersion(), 0) - }) - - describe('complete data migration', () => { - let updatedRecordsCount - - beforeEach(async () => { - // migrate the keys - const encoder = ethers.AbiCoder.defaultAbiCoder() - const calldata = encoder.encode(['uint', 'uint'], [0, 100]) - const [, lockOwner] = await ethers.getSigners() - const tx = await lock.connect(lockOwner).migrate(calldata) - const receipt = await tx.wait() - const { args } = await getEvent(receipt, 'KeysMigrated') - updatedRecordsCount = args.updatedRecordsCount - }) - - it('fire the correct event w updatedRecordsCount', async () => { - assert.equal(updatedRecordsCount, totalSupplyBefore) - }) - - it('schemaVersion has been updated', async () => { - assert.equal(await lock.schemaVersion(), await lock.publicLockVersion()) - }) - - it('preserves all keys data', async () => { - const totalSupply = await lock.totalSupply() - for (let i of Array(totalSupply).fill(0)) { - const tokenId = i + 1 - assert.equal(await lock.isValidKey(tokenId), true) - assert.equal( - await lock.ownerOf(tokenId), - await buyers[i].getAddress() - ) - assert.equal(await lock.balanceOf(await buyers[i].getAddress()), 1) - assert.equal( - await lock.getHasValidKey(await buyers[i].getAddress()), - true - ) - assert.equal( - await lock.keyExpirationTimestampFor(tokenId), - expirationTimestamps[i] - ) - } - }) - - it('purchase should now work ', async () => { - const tx = await lock.connect(buyers[0]).purchase( - [], - await Promise.all(buyers.map((k) => k.getAddress())), - buyers.map(() => ADDRESS_ZERO), - buyers.map(() => ADDRESS_ZERO), - buyers.map(() => '0x'), - { - value: keyPrice * BigInt(buyers.length), - } - ) - const receipt = await tx.wait() - const { events } = await getEvents(receipt, 'Transfer') - const purchasedTokenIds = events.map(({ args }) => args.tokenId) - assert.equal(purchasedTokenIds.length, buyers.length) - }) - - it('grantKeys should now work ', async () => { - const tx = await lock.connect(buyers[0]).grantKeys( - await Promise.all(buyers.map((k) => k.getAddress())), - buyers.map(() => Date.now()), - buyers.map(() => ADDRESS_ZERO) - ) - const receipt = await tx.wait() - const { events } = await getEvents(receipt, 'Transfer') - const grantedTokenIds = events.map(({ args }) => args.tokenId) - assert.equal(grantedTokenIds.length, buyers.length) - }) - - it('extend should now work ', async () => { - const tx = await lock - .connect(buyers[0]) - .extend(0, tokenIds[0], ADDRESS_ZERO, '0x', { - value: keyPrice, - }) - await tx.wait() - assert.equal( - (await lock.keyExpirationTimestampFor(tokenIds[0])) > - expirationTimestamps[0], - true - ) - }) - }) - }) -}) diff --git a/smart-contracts/test/helpers/versions.js b/smart-contracts/test/helpers/versions.js index b8449930aa9..62c608af1d5 100644 --- a/smart-contracts/test/helpers/versions.js +++ b/smart-contracts/test/helpers/versions.js @@ -17,8 +17,8 @@ function getUnlockVersionNumbers() { Array(LATEST_UNLOCK_VERSION) .fill(0) .map((_, i) => i) - // skip the contracts before v6 - .filter((v) => v > 5) + // skip the contracts before v10 + .filter((v) => v > 10) ) } From 479629dc44a8628b5101494ab57d664504684fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Mon, 19 Aug 2024 15:52:53 +0200 Subject: [PATCH 21/27] bring back UnlockV9 --- .../contracts/src/abis/Unlock/UnlockV9.json | 633 +++++++ .../src/contracts/Unlock/IUnlockV9.sol | 166 ++ .../src/contracts/Unlock/UnlockV9.sol | 1591 +++++++++++++++++ 3 files changed, 2390 insertions(+) create mode 100644 packages/contracts/src/abis/Unlock/UnlockV9.json create mode 100644 packages/contracts/src/contracts/Unlock/IUnlockV9.sol create mode 100644 packages/contracts/src/contracts/Unlock/UnlockV9.sol diff --git a/packages/contracts/src/abis/Unlock/UnlockV9.json b/packages/contracts/src/abis/Unlock/UnlockV9.json new file mode 100644 index 00000000000..2c2593cb66e --- /dev/null +++ b/packages/contracts/src/abis/Unlock/UnlockV9.json @@ -0,0 +1,633 @@ +{ + "contractName": "Unlock", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "udt", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "weth", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "estimatedGasForPurchase", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "globalTokenSymbol", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "globalTokenURI", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "ConfigUnlock", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lockOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newLockAddress", + "type": "address" + } + ], + "name": "NewLock", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "grossNetworkProduct", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDiscountGranted", + "type": "uint256" + } + ], + "name": "ResetTrackedValue", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "publicLockAddress", + "type": "address" + } + ], + "name": "SetLockTemplate", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "chainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "estimatedGasForPurchase", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "globalBaseTokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "globalTokenSymbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "grossNetworkProduct", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "locks", + "outputs": [ + { + "internalType": "bool", + "name": "deployed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "totalSales", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "yieldedDiscountTokens", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "publicLockAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalDiscountGranted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "udt", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "uniswapOracles", + "outputs": [ + { + "internalType": "contract IUniswapOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_unlockOwner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_expirationDuration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_keyPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxNumberOfKeys", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_lockName", + "type": "string" + }, + { + "internalType": "bytes12", + "name": "_salt", + "type": "bytes12" + } + ], + "name": "createLock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "computeAvailableDiscountFor", + "outputs": [ + { + "internalType": "uint256", + "name": "discount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_referrer", + "type": "address" + } + ], + "name": "recordKeyPurchase", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_discount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "recordConsumedDiscount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "unlockVersion", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_udt", + "type": "address" + }, + { + "internalType": "address", + "name": "_weth", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_estimatedGasForPurchase", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "string", + "name": "_URI", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + } + ], + "name": "configUnlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address payable", + "name": "_publicLockAddress", + "type": "address" + } + ], + "name": "setLockTemplate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracleAddress", + "type": "address" + } + ], + "name": "setOracle", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_grossNetworkProduct", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_totalDiscountGranted", + "type": "uint256" + } + ], + "name": "resetTrackedValue", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getGlobalBaseTokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getGlobalTokenSymbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052611d43806100136000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80637ff94bb2116100f9578063a998e9fb11610097578063d6e9e80311610071578063d6e9e80314610612578063ef67fde61461061a578063f2fde38b14610640578063f832899114610666576101a9565b8063a998e9fb146105dc578063c4d66de8146105e4578063cec410521461060a576101a9565b8063939d9f1f116100d3578063939d9f1f1461057d578063963a9478146105a95780639a8a0592146105cc578063a082eb0e146105d4576101a9565b80637ff94bb2146105515780638da5cb5b146105595780638f32d59b14610561576101a9565b806342d92106116101665780636bced5a2116101405780636bced5a214610427578063715018a61461044d578063743bbc2f146104555780637d8fb6411461046f576101a9565b806342d92106146102e05780635c38eb3a146103b35780635de9a137146103e1576101a9565b80630cb175e3146101ae578063262d0a85146101f357806335a750de1461021757806336524663146102945780633fc8cef3146102b95780634220bd46146102c1575b600080fd5b6101da600480360360408110156101c457600080fd5b506001600160a01b03813516906020013561066e565b6040805192835260208301919091528051918290030190f35b6101fb610677565b604080516001600160a01b039092168252519081900360200190f35b61021f610686565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610259578181015183820152602001610241565b50505050905090810190601f1680156102865780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102b7600480360360408110156102aa57600080fd5b508035906020013561071d565b005b6101fb61077b565b6102c961078a565b6040805161ffff9092168252519081900360200190f35b6102b7600480360360c08110156102f657600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561033257600080fd5b82018360208201111561034457600080fd5b8035906020019184600183028401116401000000008311171561036657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061078f9050565b6102b7600480360360408110156103c957600080fd5b506001600160a01b03813581169160200135166109ab565b610407600480360360208110156103f757600080fd5b50356001600160a01b0316610a96565b604080519315158452602084019290925282820152519081900360600190f35b6101fb6004803603602081101561043d57600080fd5b50356001600160a01b0316610abb565b6102b7610ad6565b61045d610b67565b60408051918252519081900360200190f35b6102b7600480360360c081101561048557600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104c057600080fd5b8201836020820111156104d257600080fd5b803590602001918460018302840111640100000000831117156104f457600080fd5b91939092909160208101903564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184600183028401116401000000008311171561054657600080fd5b919350915035610b6d565b61021f610ce4565b6101fb610d45565b610569610d54565b604080519115158252519081900360200190f35b6102b76004803603604081101561059357600080fd5b50803590602001356001600160a01b0316610d7a565b6102b7600480360360408110156105bf57600080fd5b5080359060200135611484565b61045d611514565b61045d61151a565b61021f611520565b6102b7600480360360208110156105fa57600080fd5b50356001600160a01b03166115ae565b61021f611659565b61045d6116b4565b6102b76004803603602081101561063057600080fd5b50356001600160a01b03166116ba565b6102b76004803603602081101561065657600080fd5b50356001600160a01b0316611831565b6101fb611884565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b820191906000526020600020905b8154815290600101906020018083116106f557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661076e576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600990565b606b546001600160a01b03166107e4576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b54600090610814906001600160a01b03168363ffffffff61189316565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108b95781810151838201526020016108a1565b50505050905090810190601f1680156108e65780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b6109b3610d54565b6109f2576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561077757606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610ade610d54565b610b1d576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b610b75610d54565b610bb4576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055610bf5606a8686611be1565b50610c0260698484611be1565b50806070819055507fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be67888888888888888860405180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b0316815260200187815260200180602001806020018481526020018381038352888882818152602001925080828437600083820152601f01601f191690910184810383528681526020019050868680828437600083820152604051601f909101601f19169092018290039c50909a5050505050505050505050a15050505050505050565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b6033546001600160a01b031690565b6033546000906001600160a01b0316610d6b61198b565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610dcb576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561077757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0d57600080fd5b505afa158015610e21573d6000803e3d6000fd5b505050506040513d6020811015610e3757600080fd5b505190506001600160a01b03811615801590610e615750606d546001600160a01b03828116911614155b15610f1a576001600160a01b038082166000908152606c6020526040902054168015610f1457606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610ee557600080fd5b505af1158015610ef9573d6000803e3d6000fd5b505050506040513d6020811015610f0f57600080fd5b505192505b50610f1e565b8391505b606654610f31908363ffffffff61198f16565b6066553360009081526068602052604090206001018054830190556001600160a01b0383161561147e57606e546001600160a01b039081166000908152606c602052604090205416801561147c57606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b505050506040513d602081101561101057600080fd5b5051606f54909150600090829060649061103b903a026806c6b935b8bbd4000063ffffffff6119f016565b8161104257fe5b048161104a57fe5b0490506000809050600160705411156111145760665480600288028161106c57fe5b606e54604080516370a0823160e01b8152306004820152905193909204600201926110fd928b926001600160a01b0316916370a08231916024808201926020929091908290030181600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505050506040513d60208110156110ef57600080fd5b50519063ffffffff6119f016565b8161110457fe5b048161110c57fe5b049050611180565b606654600261116d88606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110c557600080fd5b8161117457fe5b048161117c57fe5b0490505b8082111561118c578091505b811561147857600060646111a784601463ffffffff6119f016565b816111ae57fe5b0490506001607054111561135d57606e54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a0823191602480830192602092919082900301818787803b15801561120857600080fd5b505af115801561121c573d6000803e3d6000fd5b505050506040513d602081101561123257600080fd5b505190508381111561135757606e546040805163a9059cbb60e01b81526001600160a01b038c8116600483015285880360248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561129557600080fd5b505af11580156112a9573d6000803e3d6000fd5b505050506040513d60208110156112bf57600080fd5b5050606e546001600160a01b031663a9059cbb6112da610d45565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561132a57600080fd5b505af115801561133e573d6000803e3d6000fd5b505050506040513d602081101561135457600080fd5b50505b50611476565b606e54604080516340c10f1960e01b81526001600160a01b038b811660048301528487036024830152915191909216916340c10f199160448083019260209291908290030181600087803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b505050506040513d60208110156113de57600080fd5b5050606e546001600160a01b03166340c10f196113f9610d45565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561144957600080fd5b505af115801561145d573d6000803e3d6000fd5b505050506040513d602081101561147357600080fd5b50505b505b5050505b505b50505050565b61148c610d54565b6114cb576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60705481565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b820191906000526020600020905b81548152906001019060200180831161158957829003601f168201915b505050505081565b600054610100900460ff16806115c757506115c7611a49565b806115d5575060005460ff16155b6116105760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff1615801561163b576000805460ff1961ff0019909116610100171660011790555b61164482611a4f565b8015610777576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b60665481565b6116c2610d54565b611701576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611839610d54565b611878576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b61188181611b40565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146119225760009350611931565b6101008301516037846000f593505b5050506001600160a01b038116611985576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b6000828201838110156119e9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826119ff57506000611985565b82820282848281611a0c57fe5b04146119e95760405162461bcd60e51b8152600401808060200182810382526021815260200180611ca06021913960400191505060405180910390fd5b303b1590565b600054610100900460ff1680611a685750611a68611a49565b80611a76575060005460ff16155b611ab15760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff16158015611adc576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610777576000805461ff00191690555050565b6001600160a01b038116611b855760405162461bcd60e51b8152600401808060200182810382526026815260200180611c7a6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c225782800160ff19823516178555611c4f565b82800160010185558215611c4f579182015b82811115611c4f578235825591602001919060010190611c34565b50611c5b929150611c5f565b5090565b61071a91905b80821115611c5b5760008155600101611c6556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820b5be3eecf05b8785daddd76ce8d2c6c2eba8012ba1537f20635313bac678c70a64736f6c63430005110032", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80637ff94bb2116100f9578063a998e9fb11610097578063d6e9e80311610071578063d6e9e80314610612578063ef67fde61461061a578063f2fde38b14610640578063f832899114610666576101a9565b8063a998e9fb146105dc578063c4d66de8146105e4578063cec410521461060a576101a9565b8063939d9f1f116100d3578063939d9f1f1461057d578063963a9478146105a95780639a8a0592146105cc578063a082eb0e146105d4576101a9565b80637ff94bb2146105515780638da5cb5b146105595780638f32d59b14610561576101a9565b806342d92106116101665780636bced5a2116101405780636bced5a214610427578063715018a61461044d578063743bbc2f146104555780637d8fb6411461046f576101a9565b806342d92106146102e05780635c38eb3a146103b35780635de9a137146103e1576101a9565b80630cb175e3146101ae578063262d0a85146101f357806335a750de1461021757806336524663146102945780633fc8cef3146102b95780634220bd46146102c1575b600080fd5b6101da600480360360408110156101c457600080fd5b506001600160a01b03813516906020013561066e565b6040805192835260208301919091528051918290030190f35b6101fb610677565b604080516001600160a01b039092168252519081900360200190f35b61021f610686565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610259578181015183820152602001610241565b50505050905090810190601f1680156102865780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102b7600480360360408110156102aa57600080fd5b508035906020013561071d565b005b6101fb61077b565b6102c961078a565b6040805161ffff9092168252519081900360200190f35b6102b7600480360360c08110156102f657600080fd5b8135916001600160a01b036020820135169160408201359160608101359181019060a08101608082013564010000000081111561033257600080fd5b82018360208201111561034457600080fd5b8035906020019184600183028401116401000000008311171561036657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031916915061078f9050565b6102b7600480360360408110156103c957600080fd5b506001600160a01b03813581169160200135166109ab565b610407600480360360208110156103f757600080fd5b50356001600160a01b0316610a96565b604080519315158452602084019290925282820152519081900360600190f35b6101fb6004803603602081101561043d57600080fd5b50356001600160a01b0316610abb565b6102b7610ad6565b61045d610b67565b60408051918252519081900360200190f35b6102b7600480360360c081101561048557600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156104c057600080fd5b8201836020820111156104d257600080fd5b803590602001918460018302840111640100000000831117156104f457600080fd5b91939092909160208101903564010000000081111561051257600080fd5b82018360208201111561052457600080fd5b8035906020019184600183028401116401000000008311171561054657600080fd5b919350915035610b6d565b61021f610ce4565b6101fb610d45565b610569610d54565b604080519115158252519081900360200190f35b6102b76004803603604081101561059357600080fd5b50803590602001356001600160a01b0316610d7a565b6102b7600480360360408110156105bf57600080fd5b5080359060200135611484565b61045d611514565b61045d61151a565b61021f611520565b6102b7600480360360208110156105fa57600080fd5b50356001600160a01b03166115ae565b61021f611659565b61045d6116b4565b6102b76004803603602081101561063057600080fd5b50356001600160a01b03166116ba565b6102b76004803603602081101561065657600080fd5b50356001600160a01b0316611831565b6101fb611884565b50600091829150565b606e546001600160a01b031681565b606a8054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b820191906000526020600020905b8154815290600101906020018083116106f557829003601f168201915b505050505090505b90565b3360009081526068602052604090205460ff1661076e576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b60678054830190555b5050565b606d546001600160a01b031681565b600990565b606b546001600160a01b03166107e4576040805162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b604482015290519081900360640190fd5b6040513360601b81526014810182905251606b54600090610814906001600160a01b03168363ffffffff61189316565b9050806001600160a01b0316636eadde43338a8a8a8a8a6040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108b95781810151838201526020016108a1565b50505050905090810190601f1680156108e65780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b15801561090a57600080fd5b505af115801561091e573d6000803e3d6000fd5b5050604080516060810182526001808252600060208084018281528486018381526001600160a01b038a1680855260689093528684209551865460ff1916901515178655905193850193909355915160029093019290925591519193503392507f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a35050505050505050565b6109b3610d54565b6109f2576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6001600160a01b038281166000908152606c6020526040902080546001600160a01b03191691831691821790551561077757606d546040805163c640752d60e01b81526001600160a01b038581166004830152928316602482015290519183169163c640752d9160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b505050505050565b60686020526000908152604090208054600182015460029092015460ff909116919083565b606c602052600090815260409020546001600160a01b031681565b610ade610d54565b610b1d576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b606f5481565b610b75610d54565b610bb4576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055610bf5606a8686611be1565b50610c0260698484611be1565b50806070819055507fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be67888888888888888860405180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b0316815260200187815260200180602001806020018481526020018381038352888882818152602001925080828437600083820152601f01601f191690910184810383528681526020019050868680828437600083820152604051601f909101601f19169092018290039c50909a5050505050505050505050a15050505050505050565b60698054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107125780601f106106e757610100808354040283529160200191610712565b6033546001600160a01b031690565b6033546000906001600160a01b0316610d6b61198b565b6001600160a01b031614905090565b3360009081526068602052604090205460ff16610dcb576040805162461bcd60e51b815260206004820152600a6024820152694f4e4c595f4c4f434b5360b01b604482015290519081900360640190fd5b811561077757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0d57600080fd5b505afa158015610e21573d6000803e3d6000fd5b505050506040513d6020811015610e3757600080fd5b505190506001600160a01b03811615801590610e615750606d546001600160a01b03828116911614155b15610f1a576001600160a01b038082166000908152606c6020526040902054168015610f1457606d546040805163c1e553e760e01b81526001600160a01b03858116600483015260248201899052928316604482015290519183169163c1e553e7916064808201926020929091908290030181600087803b158015610ee557600080fd5b505af1158015610ef9573d6000803e3d6000fd5b505050506040513d6020811015610f0f57600080fd5b505192505b50610f1e565b8391505b606654610f31908363ffffffff61198f16565b6066553360009081526068602052604090206001018054830190556001600160a01b0383161561147e57606e546001600160a01b039081166000908152606c602052604090205416801561147c57606e54606d546040805163c1e553e760e01b81526001600160a01b039384166004820152670de0b6b3a7640000602482015291831660448301525160009284169163c1e553e791606480830192602092919082900301818787803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b505050506040513d602081101561101057600080fd5b5051606f54909150600090829060649061103b903a026806c6b935b8bbd4000063ffffffff6119f016565b8161104257fe5b048161104a57fe5b0490506000809050600160705411156111145760665480600288028161106c57fe5b606e54604080516370a0823160e01b8152306004820152905193909204600201926110fd928b926001600160a01b0316916370a08231916024808201926020929091908290030181600087803b1580156110c557600080fd5b505af11580156110d9573d6000803e3d6000fd5b505050506040513d60208110156110ef57600080fd5b50519063ffffffff6119f016565b8161110457fe5b048161110c57fe5b049050611180565b606654600261116d88606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156110c557600080fd5b8161117457fe5b048161117c57fe5b0490505b8082111561118c578091505b811561147857600060646111a784601463ffffffff6119f016565b816111ae57fe5b0490506001607054111561135d57606e54604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a0823191602480830192602092919082900301818787803b15801561120857600080fd5b505af115801561121c573d6000803e3d6000fd5b505050506040513d602081101561123257600080fd5b505190508381111561135757606e546040805163a9059cbb60e01b81526001600160a01b038c8116600483015285880360248301529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561129557600080fd5b505af11580156112a9573d6000803e3d6000fd5b505050506040513d60208110156112bf57600080fd5b5050606e546001600160a01b031663a9059cbb6112da610d45565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561132a57600080fd5b505af115801561133e573d6000803e3d6000fd5b505050506040513d602081101561135457600080fd5b50505b50611476565b606e54604080516340c10f1960e01b81526001600160a01b038b811660048301528487036024830152915191909216916340c10f199160448083019260209291908290030181600087803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b505050506040513d60208110156113de57600080fd5b5050606e546001600160a01b03166340c10f196113f9610d45565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561144957600080fd5b505af115801561145d573d6000803e3d6000fd5b505050506040513d602081101561147357600080fd5b50505b505b5050505b505b50505050565b61148c610d54565b6114cb576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60668290556067819055604080518381526020810183905281517f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb929181900390910190a15050565b60705481565b60675481565b6069805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b820191906000526020600020905b81548152906001019060200180831161158957829003601f168201915b505050505081565b600054610100900460ff16806115c757506115c7611a49565b806115d5575060005460ff16155b6116105760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff1615801561163b576000805460ff1961ff0019909116610100171660011790555b61164482611a4f565b8015610777576000805461ff00191690555050565b606a805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156115a65780601f1061157b576101008083540402835291602001916115a6565b60665481565b6116c2610d54565b611701576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b60408051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c4820181905291516001600160a01b03841692636eadde4392610104808201939182900301818387803b15801561177157600080fd5b505af1158015611785573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117c457600080fd5b505af11580156117d8573d6000803e3d6000fd5b5050606b80546001600160a01b0385166001600160a01b0319909116811790915560408051918252517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219350908190036020019150a150565b611839610d54565b611878576040805162461bcd60e51b81526020600482018190526024820152600080516020611cc1833981519152604482015290519081900360640190fd5b61188181611b40565b50565b606b546001600160a01b031681565b6000604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528360601b60148201526e5af43d82803e903d91602b57fd5bf360881b602882015260378120836101008301526001600160f81b031960408301523060601b60418301526101008201516055830152806075830152605560408301209250823b600081146119225760009350611931565b6101008301516037846000f593505b5050506001600160a01b038116611985576040805162461bcd60e51b8152602060048201526013602482015272141493d61657d111541313d657d19052531151606a1b604482015290519081900360640190fd5b92915050565b3390565b6000828201838110156119e9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000826119ff57506000611985565b82820282848281611a0c57fe5b04146119e95760405162461bcd60e51b8152600401808060200182810382526021815260200180611ca06021913960400191505060405180910390fd5b303b1590565b600054610100900460ff1680611a685750611a68611a49565b80611a76575060005460ff16155b611ab15760405162461bcd60e51b815260040180806020018281038252602e815260200180611ce1602e913960400191505060405180910390fd5b600054610100900460ff16158015611adc576000805460ff1961ff0019909116610100171660011790555b603380546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015610777576000805461ff00191690555050565b6001600160a01b038116611b855760405162461bcd60e51b8152600401808060200182810382526026815260200180611c7a6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c225782800160ff19823516178555611c4f565b82800160010185558215611c4f579182015b82811115611c4f578235825591602001919060010190611c34565b50611c5b929150611c5f565b5090565b61071a91905b80821115611c5b5760008155600101611c6556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820b5be3eecf05b8785daddd76ce8d2c6c2eba8012ba1537f20635313bac678c70a64736f6c63430005110032", + "compiler": { + "name": "solc", + "version": "0.5.17+commit.d19bba13.Emscripten.clang" + }, + "schemaVersion": "3.2.4", + "updatedAt": "2021-06-08T19:38:15.028Z" +} diff --git a/packages/contracts/src/contracts/Unlock/IUnlockV9.sol b/packages/contracts/src/contracts/Unlock/IUnlockV9.sol new file mode 100644 index 00000000000..136ba888c5d --- /dev/null +++ b/packages/contracts/src/contracts/Unlock/IUnlockV9.sol @@ -0,0 +1,166 @@ +pragma solidity 0.5.17; + +/** + * @title The Unlock Interface + **/ + +interface IUnlockV9 { + // Use initialize instead of a constructor to support proxies(for upgradeability via zos). + function initialize(address _unlockOwner) external; + + /** + * @dev Create lock + * This deploys a lock for a creator. It also keeps track of the deployed lock. + * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. + * @param _salt an identifier for the Lock, which is unique for the user. + * This may be implemented as a sequence ID or with RNG. It's used with `create2` + * to know the lock's address before the transaction is mined. + */ + function createLock( + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName, + bytes12 _salt + ) external returns (address); + + /** + * This function keeps track of the added GDP, as well as grants of discount tokens + * to the referrer, if applicable. + * The number of discount tokens granted is based on the value of the referal, + * the current growth rate and the lock's discount token distribution rate + * This function is invoked by a previously deployed lock only. + */ + function recordKeyPurchase( + uint _value, + address _referrer // solhint-disable-line no-unused-vars + ) external; + + /** + * This function will keep track of consumed discounts by a given user. + * It will also grant discount tokens to the creator who is granting the discount based on the + * amount of discount and compensation rate. + * This function is invoked by a previously deployed lock only. + */ + function recordConsumedDiscount( + uint _discount, + uint _tokens // solhint-disable-line no-unused-vars + ) external; + + /** + * This function returns the discount available for a user, when purchasing a + * a key from a lock. + * This does not modify the state. It returns both the discount and the number of tokens + * consumed to grant that discount. + */ + function computeAvailableDiscountFor( + address _purchaser, // solhint-disable-line no-unused-vars + uint _keyPrice // solhint-disable-line no-unused-vars + ) external view returns (uint discount, uint tokens); + + // Function to read the globalTokenURI field. + function globalBaseTokenURI() external view returns (string memory); + + /** + * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalBaseTokenURI() external view returns (string memory); + + // Function to read the globalTokenSymbol field. + function globalTokenSymbol() external view returns (string memory); + + // Function to read the chainId field. + function chainId() external view returns (uint); + + /** + * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalTokenSymbol() external view returns (string memory); + + /** + * @notice Allows the owner to update configuration variables + */ + function configUnlock( + address _udt, + address _weth, + uint _estimatedGasForPurchase, + string calldata _symbol, + string calldata _URI, + uint _chainId + ) external; + + /** + * @notice Upgrade the PublicLock template used for future calls to `createLock`. + * @dev This will initialize the template and revokeOwnership. + */ + function setLockTemplate(address payable _publicLockAddress) external; + + // Allows the owner to change the value tracking variables as needed. + function resetTrackedValue( + uint _grossNetworkProduct, + uint _totalDiscountGranted + ) external; + + function grossNetworkProduct() external view returns (uint); + + function totalDiscountGranted() external view returns (uint); + + function locks( + address + ) + external + view + returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); + + // The address of the public lock template, used when `createLock` is called + function publicLockAddress() external view returns (address); + + // Map token address to exchange contract address if the token is supported + // Used for GDP calculations + function uniswapOracles(address) external view returns (address); + + // The WETH token address, used for value calculations + function weth() external view returns (address); + + // The UDT token address, used to mint tokens on referral + function udt() external view returns (address); + + // The approx amount of gas required to purchase a key + function estimatedGasForPurchase() external view returns (uint); + + // The version number of the current Unlock implementation on this network + function unlockVersion() external pure returns (uint16); + + /** + * @notice allows the owner to set the oracle address to use for value conversions + * setting the _oracleAddress to address(0) removes support for the token + * @dev This will also call update to ensure at least one datapoint has been recorded. + */ + function setOracle(address _tokenAddress, address _oracleAddress) external; + + /** + * @dev Returns true if the caller is the current owner. + */ + function isOwner() external view returns (bool); + + /** + * @dev Returns the address of the current owner. + */ + function owner() external view returns (address); + + /** + * @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() external; + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) external; +} diff --git a/packages/contracts/src/contracts/Unlock/UnlockV9.sol b/packages/contracts/src/contracts/Unlock/UnlockV9.sol new file mode 100644 index 00000000000..4d74aac4b79 --- /dev/null +++ b/packages/contracts/src/contracts/Unlock/UnlockV9.sol @@ -0,0 +1,1591 @@ +// Sources flattened with hardhat v2.4.1 https://hardhat.org + +// File @openzeppelin/upgrades/contracts/Initializable.sol@v2.8.0 + +pragma solidity >=0.4.24 <0.7.0; + +/** + * @title Initializable + * + * @dev Helper contract to support initializer functions. To use it, replace + * the constructor with a function that has the `initializer` modifier. + * WARNING: Unlike constructors, initializer functions must be manually + * invoked. This applies both to deploying an Initializable contract, as well + * as extending an Initializable contract via inheritance. + * WARNING: When used with inheritance, manual care must be taken to not invoke + * a parent initializer twice, or ensure that all initializers are idempotent, + * because this is not dealt with automatically as with constructors. + */ +contract Initializable { + /** + * @dev Indicates that the contract has been initialized. + */ + bool private initialized; + + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool private initializing; + + /** + * @dev Modifier to use in the initializer function of a contract. + */ + modifier initializer() { + require( + initializing || isConstructor() || !initialized, + "Contract instance has already been initialized" + ); + + bool isTopLevelCall = !initializing; + if (isTopLevelCall) { + initializing = true; + initialized = true; + } + + _; + + if (isTopLevelCall) { + initializing = false; + } + } + + /// @dev Returns true if and only if the function is running in the constructor + function isConstructor() private view returns (bool) { + // extcodesize checks the size of the code stored in an address, and + // address returns the current address. Since the code is still not + // deployed when running a constructor, any checks on its code size will + // yield zero, making it an effective way to detect if a contract is + // under construction or not. + address self = address(this); + uint256 cs; + assembly { + cs := extcodesize(self) + } + return cs == 0; + } + + // Reserved storage space to allow for layout changes in the future. + uint256[50] private ______gap; +} + +// File @openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol@v2.5.0 + +pragma solidity ^0.5.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 GSN 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. + */ +contract Context is Initializable { + // Empty internal constructor, to prevent people from mistakenly deploying + // an instance of this contract, which should be used via inheritance. + constructor() internal {} + + // solhint-disable-previous-line no-empty-blocks + + function _msgSender() internal view returns (address payable) { + return msg.sender; + } + + function _msgData() internal view returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} + +// File @openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol@v2.5.0 + +pragma solidity ^0.5.0; + +/** + * @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. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be aplied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Initializable, Context { + address private _owner; + + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + function initialize(address sender) public initializer { + _owner = sender; + emit OwnershipTransferred(address(0), _owner); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(isOwner(), "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Returns true if the caller is the current owner. + */ + function isOwner() public view returns (bool) { + return _msgSender() == _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 onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = 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 onlyOwner { + _transferOwnership(newOwner); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + */ + function _transferOwnership(address newOwner) internal { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } + + uint256[50] private ______gap; +} + +// File hardlydifficult-ethereum-contracts/contracts/proxies/Clone2Factory.sol@v0.11.1 + +pragma solidity ^0.5.0; + +// From https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol +// Updated to support Solidity 5, switch to `create2` and revert on fail +library Clone2Factory { + /** + * @notice Uses create2 to deploy a clone to a pre-determined address. + * @param target the address of the template contract, containing the logic for this contract. + * @param salt a salt used to determine the contract address before the transaction is mined, + * may be random or sequential. + * The salt to use with the create2 call can be `msg.sender+salt` in order to + * prevent an attacker from front-running another user's deployment. + * @return proxyAddress the address of the newly deployed contract. + * @dev Using `bytes12` for the salt saves 6 gas over using `uint96` (requires another shift). + * Will revert on fail. + */ + function createClone2( + address target, + bytes32 salt + ) internal returns (address proxyAddress) { + // solium-disable-next-line + assembly { + let pointer := mload(0x40) + + // Create the bytecode for deployment based on the Minimal Proxy Standard (EIP-1167) + // bytecode: 0x0 + mstore( + pointer, + 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 + ) + mstore(add(pointer, 0x14), shl(96, target)) + mstore( + add(pointer, 0x28), + 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 + ) + + // `create2` consumes all available gas if called with a salt that's already been consumed + // we check if the address is available first so that doesn't happen + // Costs ~958 gas + + // Calculate the hash + let contractCodeHash := keccak256(pointer, 0x37) + + // salt: 0x100 + mstore(add(pointer, 0x100), salt) + + // addressSeed: 0x40 + // 0xff + mstore( + add(pointer, 0x40), + 0xff00000000000000000000000000000000000000000000000000000000000000 + ) + // this + mstore(add(pointer, 0x41), shl(96, address)) + // salt + mstore(add(pointer, 0x55), mload(add(pointer, 0x100))) + // hash + mstore(add(pointer, 0x75), contractCodeHash) + + proxyAddress := keccak256(add(pointer, 0x40), 0x55) + + switch extcodesize(proxyAddress) + case 0 { + // Deploy the contract, returning the address or 0 on fail + proxyAddress := create2(0, pointer, 0x37, mload(add(pointer, 0x100))) + } + default { + proxyAddress := 0 + } + } + + // Revert if the deployment fails (possible if salt was already used) + require(proxyAddress != address(0), "PROXY_DEPLOY_FAILED"); + } +} + +// File contracts/interfaces/IPublicLock.sol + +pragma solidity 0.5.17; + +/** + * @title The PublicLock Interface + */ + +contract IPublicLock { + // See indentationissue description here: + // https://github.com/duaraghav8/Ethlint/issues/268 + // solium-disable indentation + + /// Functions + + function initialize( + address _lockCreator, + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName + ) external; + + /** + * @notice Allow the contract to accept tips in ETH sent directly to the contract. + * @dev This is okay to use even if the lock is priced in ERC-20 tokens + */ + function() external payable; + + /** + * @dev Never used directly + */ + function initialize() external; + + /** + * @notice The version number of the current implementation on this network. + * @return The current version number. + */ + function publicLockVersion() public pure returns (uint); + + /** + * @notice Gets the current balance of the account provided. + * @param _tokenAddress The token type to retrieve the balance of. + * @param _account The account to get the balance of. + * @return The number of tokens of the given type for the given address, possibly 0. + */ + function getBalance( + address _tokenAddress, + address _account + ) external view returns (uint); + + /** + * @notice Used to disable lock before migrating keys and/or destroying contract. + * @dev Throws if called by other than a lock manager. + * @dev Throws if lock contract has already been disabled. + */ + function disableLock() external; + + /** + * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. + * @dev Throws if called by other than a lock manager or beneficiary + * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually + * the same as `tokenAddress` in MixinFunds. + * @param _amount specifies the max amount to withdraw, which may be reduced when + * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. + * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` + * use cases. + */ + function withdraw(address _tokenAddress, uint _amount) external; + + /** + * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. + * @param _spender address that can spend tokens belonging to the lock + * @param _amount amount of tokens that can be spent by the spender + */ + function approveBeneficiary( + address _spender, + uint _amount + ) external returns (bool); + + /** + * A function which lets a Lock manager of the lock to change the price for future purchases. + * @dev Throws if called by other than a Lock manager + * @dev Throws if lock has been disabled + * @dev Throws if _tokenAddress is not a valid token + * @param _keyPrice The new price to set for keys + * @param _tokenAddress The address of the erc20 token to use for pricing the keys, + * or 0 to use ETH + */ + function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; + + /** + * A function which lets a Lock manager update the beneficiary account, + * which receives funds on withdrawal. + * @dev Throws if called by other than a Lock manager or beneficiary + * @dev Throws if _beneficiary is address(0) + * @param _beneficiary The new address to set as the beneficiary + */ + function updateBeneficiary(address _beneficiary) external; + + /** + * Checks if the user has a non-expired key. + * @param _user The address of the key owner + */ + function getHasValidKey(address _user) external view returns (bool); + + /** + * @notice Find the tokenId for a given user + * @return The tokenId of the NFT, else returns 0 + * @param _account The address of the key owner + */ + function getTokenIdFor(address _account) external view returns (uint); + + /** + * A function which returns a subset of the keys for this Lock as an array + * @param _page the page of key owners requested when faceted by page size + * @param _pageSize the number of Key Owners requested per page + * @dev Throws if there are no key owners yet + */ + function getOwnersByPage( + uint _page, + uint _pageSize + ) external view returns (address[] memory); + + /** + * Checks if the given address owns the given tokenId. + * @param _tokenId The tokenId of the key to check + * @param _keyOwner The potential key owners address + */ + function isKeyOwner( + uint _tokenId, + address _keyOwner + ) external view returns (bool); + + /** + * @dev Returns the key's ExpirationTimestamp field for a given owner. + * @param _keyOwner address of the user for whom we search the key + * @dev Returns 0 if the owner has never owned a key for this lock + */ + function keyExpirationTimestampFor( + address _keyOwner + ) external view returns (uint timestamp); + + /** + * Public function which returns the total number of unique owners (both expired + * and valid). This may be larger than totalSupply. + */ + function numberOfOwners() external view returns (uint); + + /** + * Allows a Lock manager to assign a descriptive name for this Lock. + * @param _lockName The new name for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockName(string calldata _lockName) external; + + /** + * Allows a Lock manager to assign a Symbol for this Lock. + * @param _lockSymbol The new Symbol for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockSymbol(string calldata _lockSymbol) external; + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string memory); + + /** + * Allows a Lock manager to update the baseTokenURI for this Lock. + * @dev Throws if called by other than a Lock manager + * @param _baseTokenURI String representing the base of the URI for this lock. + */ + function setBaseTokenURI(string calldata _baseTokenURI) external; + + /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. + * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + * 3986. The URI may point to a JSON file that conforms to the "ERC721 + * Metadata JSON Schema". + * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md + * @param _tokenId The tokenID we're inquiring about + * @return String representing the URI for the requested token + */ + function tokenURI(uint256 _tokenId) external view returns (string memory); + + /** + * Allows a Lock manager to add or remove an event hook + * @param _onKeyPurchaseHook Hook called when the `purchase` function is called + * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called + */ + function setEventHooks( + address _onKeyPurchaseHook, + address _onKeyCancelHook + ) external; + + /** + * Allows a Lock manager to give a collection of users a key with no charge. + * Each key may be assigned a different expiration date. + * @dev Throws if called by other than a Lock manager + * @param _recipients An array of receiving addresses + * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted + */ + function grantKeys( + address[] calldata _recipients, + uint[] calldata _expirationTimestamps, + address[] calldata _keyManagers + ) external; + + /** + * @dev Purchase function + * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount + * (_value is ignored when using ETH) + * @param _recipient address of the recipient of the purchased key + * @param _referrer address of the user making the referral + * @param _data arbitrary data populated by the front-end which initiated the sale + * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). + * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the + * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more + * than keyPrice is approved for spending). + */ + function purchase( + uint256 _value, + address _recipient, + address _referrer, + bytes calldata _data + ) external payable; + + /** + * @notice returns the minimum price paid for a purchase with these params. + * @dev this considers any discount from Unlock or the OnKeyPurchase hook. + */ + function purchasePriceFor( + address _recipient, + address _referrer, + bytes calldata _data + ) external view returns (uint); + + /** + * Allow a Lock manager to change the transfer fee. + * @dev Throws if called by other than a Lock manager + * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). + * Ex: 200 bps = 2% + */ + function updateTransferFee(uint _transferFeeBasisPoints) external; + + /** + * Determines how much of a fee a key owner would need to pay in order to + * transfer the key to another account. This is pro-rated so the fee goes down + * overtime. + * @dev Throws if _keyOwner does not have a valid key + * @param _keyOwner The owner of the key check the transfer fee for. + * @param _time The amount of time to calculate the fee for. + * @return The transfer fee in seconds. + */ + function getTransferFee( + address _keyOwner, + uint _time + ) external view returns (uint); + + /** + * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key + * @param _keyOwner The key owner to whom we wish to send a refund to + * @param amount The amount to refund the key-owner + * @dev Throws if called by other than a Lock manager + * @dev Throws if _keyOwner does not have a valid key + */ + function expireAndRefundFor(address _keyOwner, uint amount) external; + + /** + * @dev allows the key manager to expire a given tokenId + * and send a refund to the keyOwner based on the amount of time remaining. + * @param _tokenId The id of the key to cancel. + */ + function cancelAndRefund(uint _tokenId) external; + + /** + * @dev Cancels a key managed by a different user and sends the funds to the keyOwner. + * @param _keyManager the key managed by this user will be canceled + * @param _v _r _s getCancelAndRefundApprovalHash signed by the _keyManager + * @param _tokenId The key to cancel + */ + function cancelAndRefundFor( + address _keyManager, + uint8 _v, + bytes32 _r, + bytes32 _s, + uint _tokenId + ) external; + + /** + * @notice Sets the minimum nonce for a valid off-chain approval message from the + * senders account. + * @dev This can be used to invalidate a previously signed message. + */ + function invalidateOffchainApproval(uint _nextAvailableNonce) external; + + /** + * Allow a Lock manager to change the refund penalty. + * @dev Throws if called by other than a Lock manager + * @param _freeTrialLength The new duration of free trials for this lock + * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) + */ + function updateRefundPenalty( + uint _freeTrialLength, + uint _refundPenaltyBasisPoints + ) external; + + /** + * @dev Determines how much of a refund a key owner would receive if they issued + * @param _keyOwner The key owner to get the refund value for. + * a cancelAndRefund block.timestamp. + * Note that due to the time required to mine a tx, the actual refund amount will be lower + * than what the user reads from this call. + */ + function getCancelAndRefundValueFor( + address _keyOwner + ) external view returns (uint refund); + + function keyManagerToNonce(address) external view returns (uint256); + + /** + * @notice returns the hash to sign in order to allow another user to cancel on your behalf. + * @dev this can be computed in JS instead of read from the contract. + * @param _keyManager The key manager's address (also the message signer) + * @param _txSender The address cancelling cancel on behalf of the keyOwner + * @return approvalHash The hash to sign + */ + function getCancelAndRefundApprovalHash( + address _keyManager, + address _txSender + ) external view returns (bytes32 approvalHash); + + function addKeyGranter(address account) external; + + function addLockManager(address account) external; + + function isKeyGranter(address account) external view returns (bool); + + function isLockManager(address account) external view returns (bool); + + function onKeyPurchaseHook() external view returns (address); + + function onKeyCancelHook() external view returns (address); + + function revokeKeyGranter(address _granter) external; + + function renounceLockManager() external; + + ///=================================================================== + /// Auto-generated getter functions from public state variables + + function beneficiary() external view returns (address); + + function expirationDuration() external view returns (uint256); + + function freeTrialLength() external view returns (uint256); + + function isAlive() external view returns (bool); + + function keyPrice() external view returns (uint256); + + function maxNumberOfKeys() external view returns (uint256); + + function owners(uint256) external view returns (address); + + function refundPenaltyBasisPoints() external view returns (uint256); + + function tokenAddress() external view returns (address); + + function transferFeeBasisPoints() external view returns (uint256); + + function unlockProtocol() external view returns (address); + + function keyManagerOf(uint) external view returns (address); + + ///=================================================================== + + /** + * @notice Allows the key owner to safely share their key (parent key) by + * transferring a portion of the remaining time to a new key (child key). + * @dev Throws if key is not valid. + * @dev Throws if `_to` is the zero address + * @param _to The recipient of the shared key + * @param _tokenId the key to share + * @param _timeShared The amount of time shared + * checks if `_to` is a smart contract (code size > 0). If so, it calls + * `onERC721Received` on `_to` and throws if the return value is not + * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. + * @dev Emit Transfer event + */ + function shareKey(address _to, uint _tokenId, uint _timeShared) external; + + /** + * @notice Update transfer and cancel rights for a given key + * @param _tokenId The id of the key to assign rights for + * @param _keyManager The address to assign the rights to for the given key + */ + function setKeyManagerOf(uint _tokenId, address _keyManager) external; + + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string memory _name); + + ///=================================================================== + + /// From ERC165.sol + function supportsInterface(bytes4 interfaceId) external view returns (bool); + + ///=================================================================== + + /// From ERC-721 + /** + * @dev Returns the number of NFTs in `owner`'s account. + */ + function balanceOf(address _owner) public view returns (uint256 balance); + + /** + * @dev Returns the owner of the NFT specified by `tokenId`. + */ + function ownerOf(uint256 tokenId) public view returns (address _owner); + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * + * + * Requirements: + * - `from`, `to` cannot be zero. + * - `tokenId` must be owned by `from`. + * - If the caller is not `from`, it must be have been allowed to move this + * NFT by either `approve` or `setApprovalForAll`. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) public; + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * Requirements: + * - If the caller is not `from`, it must be approved to move this NFT by + * either `approve` or `setApprovalForAll`. + */ + function transferFrom(address from, address to, uint256 tokenId) public; + + function approve(address to, uint256 tokenId) public; + + /** + * @notice Get the approved address for a single NFT + * @dev Throws if `_tokenId` is not a valid NFT. + * @param _tokenId The NFT to find the approved address for + * @return The approved address for this NFT, or the zero address if there is none + */ + function getApproved(uint256 _tokenId) public view returns (address operator); + + function setApprovalForAll(address operator, bool _approved) public; + + function isApprovedForAll( + address _owner, + address operator + ) public view returns (bool); + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes memory data + ) public; + + function totalSupply() public view returns (uint256); + + function tokenOfOwnerByIndex( + address _owner, + uint256 index + ) public view returns (uint256 tokenId); + + function tokenByIndex(uint256 index) public view returns (uint256); + + /** + * @notice An ERC-20 style transfer. + * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). + * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user + * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. + */ + function transfer(address _to, uint _value) external returns (bool success); +} + +// File contracts/interfaces/IUnlock.sol + +pragma solidity 0.5.17; + +/** + * @title The Unlock Interface + **/ + +interface IUnlock { + // Use initialize instead of a constructor to support proxies(for upgradeability via zos). + function initialize(address _unlockOwner) external; + + /** + * @dev Create lock + * This deploys a lock for a creator. It also keeps track of the deployed lock. + * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. + * @param _salt an identifier for the Lock, which is unique for the user. + * This may be implemented as a sequence ID or with RNG. It's used with `create2` + * to know the lock's address before the transaction is mined. + */ + function createLock( + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName, + bytes12 _salt + ) external; + + /** + * This function keeps track of the added GDP, as well as grants of discount tokens + * to the referrer, if applicable. + * The number of discount tokens granted is based on the value of the referal, + * the current growth rate and the lock's discount token distribution rate + * This function is invoked by a previously deployed lock only. + */ + function recordKeyPurchase( + uint _value, + address _referrer // solhint-disable-line no-unused-vars + ) external; + + /** + * This function will keep track of consumed discounts by a given user. + * It will also grant discount tokens to the creator who is granting the discount based on the + * amount of discount and compensation rate. + * This function is invoked by a previously deployed lock only. + */ + function recordConsumedDiscount( + uint _discount, + uint _tokens // solhint-disable-line no-unused-vars + ) external; + + /** + * This function returns the discount available for a user, when purchasing a + * a key from a lock. + * This does not modify the state. It returns both the discount and the number of tokens + * consumed to grant that discount. + */ + function computeAvailableDiscountFor( + address _purchaser, // solhint-disable-line no-unused-vars + uint _keyPrice // solhint-disable-line no-unused-vars + ) external view returns (uint discount, uint tokens); + + // Function to read the globalTokenURI field. + function globalBaseTokenURI() external view returns (string memory); + + /** + * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalBaseTokenURI() external view returns (string memory); + + // Function to read the globalTokenSymbol field. + function globalTokenSymbol() external view returns (string memory); + + // Function to read the chainId field. + function chainId() external view returns (uint); + + /** + * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalTokenSymbol() external view returns (string memory); + + /** + * @notice Allows the owner to update configuration variables + */ + function configUnlock( + address _udt, + address _weth, + uint _estimatedGasForPurchase, + string calldata _symbol, + string calldata _URI, + uint _chainId + ) external; + + /** + * @notice Upgrade the PublicLock template used for future calls to `createLock`. + * @dev This will initialize the template and revokeOwnership. + */ + function setLockTemplate(address payable _publicLockAddress) external; + + // Allows the owner to change the value tracking variables as needed. + function resetTrackedValue( + uint _grossNetworkProduct, + uint _totalDiscountGranted + ) external; + + function grossNetworkProduct() external view returns (uint); + + function totalDiscountGranted() external view returns (uint); + + function locks( + address + ) + external + view + returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); + + // The address of the public lock template, used when `createLock` is called + function publicLockAddress() external view returns (address); + + // Map token address to exchange contract address if the token is supported + // Used for GDP calculations + function uniswapOracles(address) external view returns (address); + + // The WETH token address, used for value calculations + function weth() external view returns (address); + + // The UDT token address, used to mint tokens on referral + function udt() external view returns (address); + + // The approx amount of gas required to purchase a key + function estimatedGasForPurchase() external view returns (uint); + + // The version number of the current Unlock implementation on this network + function unlockVersion() external pure returns (uint16); + + /** + * @notice allows the owner to set the oracle address to use for value conversions + * setting the _oracleAddress to address(0) removes support for the token + * @dev This will also call update to ensure at least one datapoint has been recorded. + */ + function setOracle(address _tokenAddress, address _oracleAddress) external; + + /** + * @dev Returns true if the caller is the current owner. + */ + function isOwner() external view returns (bool); + + /** + * @dev Returns the address of the current owner. + */ + function owner() external view returns (address); + + /** + * @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() external; + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) external; +} + +// File @openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol@v2.5.0 + +pragma solidity ^0.5.5; + +/** + * @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 + * ==== + */ + function isContract(address account) internal view returns (bool) { + // According to EIP-1052, 0x0 is the value returned for not-yet created accounts + // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned + // for accounts without code, i.e. `keccak256('')` + bytes32 codehash; + bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + // solhint-disable-next-line no-inline-assembly + assembly { + codehash := extcodehash(account) + } + return (codehash != accountHash && codehash != 0x0); + } + + /** + * @dev Converts an `address` into `address payable`. Note that this is + * simply a type cast: the actual underlying value is not changed. + * + * _Available since v2.4.0._ + */ + function toPayable(address account) internal pure returns (address payable) { + return address(uint160(account)); + } + + /** + * @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]. + * + * _Available since v2.4.0._ + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, "Address: insufficient balance"); + + // solhint-disable-next-line avoid-call-value + (bool success, ) = recipient.call.value(amount)(""); + require( + success, + "Address: unable to send value, recipient may have reverted" + ); + } +} + +// File hardlydifficult-eth/contracts/protocols/Uniswap/IUniswapOracle.sol@v1.1.2 + +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.0; + +interface IUniswapOracle { + function PERIOD() external returns (uint); + + function factory() external returns (address); + + function update(address _tokenIn, address _tokenOut) external; + + function consult( + address _tokenIn, + uint _amountIn, + address _tokenOut + ) external view returns (uint _amountOut); + + function updateAndConsult( + address _tokenIn, + uint _amountIn, + address _tokenOut + ) external returns (uint _amountOut); +} + +// File @openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol@v2.5.0 + +pragma solidity ^0.5.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + * + * _Available since v2.4.0._ + */ + function sub( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + * + * _Available since v2.4.0._ + */ + function div( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + * + * _Available since v2.4.0._ + */ + function mod( + uint256 a, + uint256 b, + string memory errorMessage + ) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} + +// File contracts/interfaces/IMintableERC20.sol + +pragma solidity 0.5.17; + +interface IMintableERC20 { + function mint(address account, uint256 amount) external returns (bool); + + function transfer(address recipient, uint256 amount) external returns (bool); + + function totalSupply() external returns (uint); + + function balanceOf(address account) external returns (uint256); +} + +// File contracts/Unlock.sol + +pragma solidity 0.5.17; + +/** + * @title The Unlock contract + * @author Julien Genestoux (unlock-protocol.com) + * This smart contract has 3 main roles: + * 1. Distribute discounts to discount token holders + * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. + * 3. Create & deploy Public Lock contracts. + * In order to achieve these 3 elements, it keeps track of several things such as + * a. Deployed locks addresses and balances of discount tokens granted by each lock. + * b. The total network product (sum of all key sales, net of discounts) + * c. Total of discounts granted + * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim + * discounts and cannot be used/transferred for a given period) + * e. Growth rate of Network Product + * f. Growth rate of Discount tokens supply + * The smart contract has an owner who only can perform the following + * - Upgrades + * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most + * 50% of GNP growth rate) + * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and + * in the wild. + * The partial implementation includes the following features: + * a. Keeping track of deployed locks + * b. Keeping track of GNP + */ + +/// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. +/// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization +contract Unlock is IUnlock, Initializable, Ownable { + using Address for address; + using Clone2Factory for address; + using SafeMath for uint; + + /** + * The struct for a lock + * We use deployed to keep track of deployments. + * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, + * which would be the same values when the lock is not set. + */ + struct LockBalances { + bool deployed; + uint totalSales; // This is in wei + uint yieldedDiscountTokens; + } + + modifier onlyFromDeployedLock() { + require(locks[msg.sender].deployed, "ONLY_LOCKS"); + _; + } + + uint public grossNetworkProduct; + + uint public totalDiscountGranted; + + // We keep track of deployed locks to ensure that callers are all deployed locks. + mapping(address => LockBalances) public locks; + + // global base token URI + // Used by locks where the owner has not set a custom base URI. + string public globalBaseTokenURI; + + // global base token symbol + // Used by locks where the owner has not set a custom symbol + string public globalTokenSymbol; + + // The address of the public lock template, used when `createLock` is called + address public publicLockAddress; + + // Map token address to oracle contract address if the token is supported + // Used for GDP calculations + mapping(address => IUniswapOracle) public uniswapOracles; + + // The WETH token address, used for value calculations + address public weth; + + // The UDT token address, used to mint tokens on referral + address public udt; + + // The approx amount of gas required to purchase a key + uint public estimatedGasForPurchase; + + // Blockchain ID the network id on which this version of Unlock is operating + uint public chainId; + + // Events + event NewLock(address indexed lockOwner, address indexed newLockAddress); + + event ConfigUnlock( + address udt, + address weth, + uint estimatedGasForPurchase, + string globalTokenSymbol, + string globalTokenURI, + uint chainId + ); + + event SetLockTemplate(address publicLockAddress); + + event ResetTrackedValue(uint grossNetworkProduct, uint totalDiscountGranted); + + // Use initialize instead of a constructor to support proxies (for upgradeability via zos). + function initialize(address _unlockOwner) public initializer { + // We must manually initialize Ownable.sol + Ownable.initialize(_unlockOwner); + } + + /** + * @dev Create lock + * This deploys a lock for a creator. It also keeps track of the deployed lock. + * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. + * @param _salt an identifier for the Lock, which is unique for the user. + * This may be implemented as a sequence ID or with RNG. It's used with `create2` + * to know the lock's address before the transaction is mined. + */ + function createLock( + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string memory _lockName, + bytes12 _salt + ) public { + require(publicLockAddress != address(0), "MISSING_LOCK_TEMPLATE"); + + // create lock + bytes32 salt; + // solium-disable-next-line + assembly { + let pointer := mload(0x40) + // The salt is the msg.sender + mstore(pointer, shl(96, caller)) + // followed by the _salt provided + mstore(add(pointer, 0x14), _salt) + salt := mload(pointer) + } + address payable newLock = address( + uint160(publicLockAddress.createClone2(salt)) + ); + IPublicLock(newLock).initialize( + msg.sender, + _expirationDuration, + _tokenAddress, + _keyPrice, + _maxNumberOfKeys, + _lockName + ); + + // Assign the new Lock + locks[newLock] = LockBalances({ + deployed: true, + totalSales: 0, + yieldedDiscountTokens: 0 + }); + + // trigger event + emit NewLock(msg.sender, newLock); + } + + /** + * This function returns the discount available for a user, when purchasing a + * a key from a lock. + * This does not modify the state. It returns both the discount and the number of tokens + * consumed to grant that discount. + * TODO: actually implement this. + */ + function computeAvailableDiscountFor( + address /* _purchaser */, + uint /* _keyPrice */ + ) public view returns (uint discount, uint tokens) { + // TODO: implement me + return (0, 0); + } + + /** + * This function keeps track of the added GDP, as well as grants of discount tokens + * to the referrer, if applicable. + * The number of discount tokens granted is based on the value of the referal, + * the current growth rate and the lock's discount token distribution rate + * This function is invoked by a previously deployed lock only. + * TODO: actually implement + */ + function recordKeyPurchase( + uint _value, + address _referrer + ) public onlyFromDeployedLock { + if (_value > 0) { + uint valueInETH; + address tokenAddress = IPublicLock(msg.sender).tokenAddress(); + if (tokenAddress != address(0) && tokenAddress != weth) { + // If priced in an ERC-20 token, find the supported uniswap oracle + IUniswapOracle oracle = uniswapOracles[tokenAddress]; + if (address(oracle) != address(0)) { + valueInETH = oracle.updateAndConsult(tokenAddress, _value, weth); + } + } else { + // If priced in ETH (or value is 0), no conversion is required + valueInETH = _value; + } + + grossNetworkProduct = grossNetworkProduct.add(valueInETH); + // If GNP does not overflow, the lock totalSales should be safe + locks[msg.sender].totalSales += valueInETH; + + // Mint UDT + if (_referrer != address(0)) { + IUniswapOracle udtOracle = uniswapOracles[udt]; + if (address(udtOracle) != address(0)) { + // Get the value of 1 UDT (w/ 18 decimals) in ETH + uint udtPrice = udtOracle.updateAndConsult(udt, 10 ** 18, weth); + + // tokensToDistribute is either == to the gas cost times 1.25 to cover the 20% dev cut + uint tokensToDistribute = (estimatedGasForPurchase * tx.gasprice).mul( + 125 * 10 ** 18 + ) / + 100 / + udtPrice; + + // or tokensToDistribute is capped by network GDP growth + uint maxTokens = 0; + if (chainId > 1) { + // non mainnet: we distribute tokens using asymptotic curve between 0 and 0.5 + // maxTokens = IMintableERC20(udt).balanceOf(address(this)).mul((valueInETH / grossNetworkProduct) / (2 + 2 * valueInETH / grossNetworkProduct)); + maxTokens = + IMintableERC20(udt).balanceOf(address(this)).mul(valueInETH) / + (2 + (2 * valueInETH) / grossNetworkProduct) / + grossNetworkProduct; + } else { + // Mainnet: we mint new token using log curve + maxTokens = + IMintableERC20(udt).totalSupply().mul(valueInETH) / + 2 / + grossNetworkProduct; + } + + // cap to GDP growth! + if (tokensToDistribute > maxTokens) { + tokensToDistribute = maxTokens; + } + + if (tokensToDistribute > 0) { + // 80% goes to the referrer, 20% to the Unlock dev - round in favor of the referrer + uint devReward = tokensToDistribute.mul(20) / 100; + if (chainId > 1) { + uint balance = IMintableERC20(udt).balanceOf(address(this)); + if (balance > tokensToDistribute) { + // Only distribute if there are enough tokens + IMintableERC20(udt).transfer( + _referrer, + tokensToDistribute - devReward + ); + IMintableERC20(udt).transfer(owner(), devReward); + } + } else { + // No distribnution + IMintableERC20(udt).mint( + _referrer, + tokensToDistribute - devReward + ); + IMintableERC20(udt).mint(owner(), devReward); + } + } + } + } + } + } + + /** + * This function will keep track of consumed discounts by a given user. + * It will also grant discount tokens to the creator who is granting the discount based on the + * amount of discount and compensation rate. + * This function is invoked by a previously deployed lock only. + */ + function recordConsumedDiscount( + uint _discount, + uint /* _tokens */ + ) public onlyFromDeployedLock { + // TODO: implement me + totalDiscountGranted += _discount; + return; + } + + // The version number of the current Unlock implementation on this network + function unlockVersion() external pure returns (uint16) { + return 9; + } + + /** + * @notice Allows the owner to update configuration variables + */ + function configUnlock( + address _udt, + address _weth, + uint _estimatedGasForPurchase, + string calldata _symbol, + string calldata _URI, + uint _chainId + ) external onlyOwner { + udt = _udt; + weth = _weth; + estimatedGasForPurchase = _estimatedGasForPurchase; + + globalTokenSymbol = _symbol; + globalBaseTokenURI = _URI; + + chainId = _chainId; + + emit ConfigUnlock( + _udt, + _weth, + _estimatedGasForPurchase, + _symbol, + _URI, + _chainId + ); + } + + /** + * @notice Upgrade the PublicLock template used for future calls to `createLock`. + * @dev This will initialize the template and revokeOwnership. + */ + function setLockTemplate( + address payable _publicLockAddress + ) external onlyOwner { + // First claim the template so that no-one else could + // this will revert if the template was already initialized. + IPublicLock(_publicLockAddress).initialize( + address(this), + 0, + address(0), + 0, + 0, + "" + ); + IPublicLock(_publicLockAddress).renounceLockManager(); + + publicLockAddress = _publicLockAddress; + + emit SetLockTemplate(_publicLockAddress); + } + + /** + * @notice allows the owner to set the oracle address to use for value conversions + * setting the _oracleAddress to address(0) removes support for the token + * @dev This will also call update to ensure at least one datapoint has been recorded. + */ + function setOracle( + address _tokenAddress, + address _oracleAddress + ) external onlyOwner { + uniswapOracles[_tokenAddress] = IUniswapOracle(_oracleAddress); + if (_oracleAddress != address(0)) { + IUniswapOracle(_oracleAddress).update(_tokenAddress, weth); + } + } + + // Allows the owner to change the value tracking variables as needed. + function resetTrackedValue( + uint _grossNetworkProduct, + uint _totalDiscountGranted + ) external onlyOwner { + grossNetworkProduct = _grossNetworkProduct; + totalDiscountGranted = _totalDiscountGranted; + + emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); + } + + /** + * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalBaseTokenURI() external view returns (string memory) { + return globalBaseTokenURI; + } + + /** + * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalTokenSymbol() external view returns (string memory) { + return globalTokenSymbol; + } +} From 97530bfba0429b5ac78a0f2ae7adb9440da93b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 13:42:24 +0200 Subject: [PATCH 22/27] bring back publicLock v9 --- governance/scripts/lock/outdated.js | 15 +- .../src/abis/PublicLock/PublicLockV9.json | 1788 ++++++++ .../contracts/PublicLock/IPublicLockV9.sol | 462 ++ .../src/contracts/PublicLock/PublicLockV9.sol | 3702 +++++++++++++++++ 4 files changed, 5960 insertions(+), 7 deletions(-) create mode 100644 packages/contracts/src/abis/PublicLock/PublicLockV9.json create mode 100644 packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol create mode 100644 packages/contracts/src/contracts/PublicLock/PublicLockV9.sol diff --git a/governance/scripts/lock/outdated.js b/governance/scripts/lock/outdated.js index 55f68f7e357..7c819d7b6c9 100644 --- a/governance/scripts/lock/outdated.js +++ b/governance/scripts/lock/outdated.js @@ -105,10 +105,10 @@ async function getAllLocks({ chainId, timeLimit }) { .map((lock) => getLockBalance({ chainId, lock })) ) ) - .filter( - ({ balanceNative, balanceToken }) => - balanceNative !== 0n || balanceToken !== 0n - ) + // .filter( + // ({ balanceNative, balanceToken }) => + // balanceNative !== 0n || balanceToken !== 0n + // ) .sort(({ version: a }, { version: b }) => b - a) return { @@ -121,7 +121,7 @@ async function getAllLocks({ chainId, timeLimit }) { } function logLocks({ chainId, activeLocks, earliest, earlyLocks, versions }) { - const { name } = networks[chainId] + const { name, explorer } = networks[chainId] console.log( `## ${name} (${chainId}): @@ -134,14 +134,15 @@ function logLocks({ chainId, activeLocks, earliest, earlyLocks, versions }) { ${ earlyLocks.length ? ` -## earliest locks with money left (total: ${earlyLocks.length}) +### Locks v8 and v9 (total: ${earlyLocks.length}) | address | version | balance | lastKeyMinted | | --- | --- | --- | --- | ${earlyLocks + .sort((a, b) => b.lastKeyMintedAt - a.lastKeyMintedAt) .map( ({ address, balanceFormatted, lastKeyMintedAt, version }) => - `| ${address} | v${version} | ${balanceFormatted} | ${new Date(lastKeyMintedAt * 1000).toLocaleDateString('en-US')} |` + `| [${address}](${explorer.urls.address(address)}) | v${version} | ${balanceFormatted} | ${new Date(lastKeyMintedAt * 1000).toLocaleDateString('en-US')} |` ) .join('\n')}` : '' diff --git a/packages/contracts/src/abis/PublicLock/PublicLockV9.json b/packages/contracts/src/abis/PublicLock/PublicLockV9.json new file mode 100644 index 00000000000..fa07035f2be --- /dev/null +++ b/packages/contracts/src/abis/PublicLock/PublicLockV9.json @@ -0,0 +1,1788 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PublicLock", + "sourceName": "src/contracts/PublicLock/PublicLockV9.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sendTo", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "refund", + "type": "uint256" + } + ], + "name": "CancelKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Disable", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "_timeAdded", + "type": "bool" + } + ], + "name": "ExpirationChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ExpireKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "refundedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "GasRefunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "KeyGranterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "KeyGranterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "KeyManagerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "LockManagerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "LockManagerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "name": "NewLockSymbol", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldKeyPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "keyPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "PricingChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "freeTrialLength", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "refundPenaltyBasisPoints", + "type": "uint256" + } + ], + "name": "RefundPenaltyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newExpiration", + "type": "uint256" + } + ], + "name": "RenewKeyPurchase", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "transferFeeBasisPoints", + "type": "uint256" + } + ], + "name": "TransferFeeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lockAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "unlockAddress", + "type": "address" + } + ], + "name": "UnlockCallFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEY_GRANTER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LOCK_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "addKeyGranter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "addLockManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "approveBeneficiary", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "cancelAndRefund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "expirationDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_keyOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "expireAndRefundFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "freeTrialLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasRefundValue", + "outputs": [ + { + "internalType": "uint256", + "name": "_refundValue", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + } + ], + "name": "getCancelAndRefundValueFor", + "outputs": [ + { + "internalType": "uint256", + "name": "refund", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + } + ], + "name": "getHasValidKey", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "getTokenIdFor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_time", + "type": "uint256" + } + ], + "name": "getTransferFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_recipients", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_expirationTimestamps", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "_keyManagers", + "type": "address[]" + } + ], + "name": "grantKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_lockCreator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_expirationDuration", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_keyPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxNumberOfKeys", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_lockName", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAlive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isKeyGranter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isLockManager", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + } + ], + "name": "keyExpirationTimestampFor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "keyManagerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keyPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumberOfKeys", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numberOfOwners", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onKeyCancelHook", + "outputs": [ + { + "internalType": "contract ILockKeyCancelHook", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onKeyPurchaseHook", + "outputs": [ + { + "internalType": "contract ILockKeyPurchaseHook", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onTokenURIHook", + "outputs": [ + { + "internalType": "contract ILockTokenURIHook", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onValidKeyHook", + "outputs": [ + { + "internalType": "contract ILockValidKeyHook", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "publicLockVersion", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "_referrer", + "type": "address" + }, + { + "internalType": "address", + "name": "_keyManager", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "purchase", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "_referrer", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "purchasePriceFor", + "outputs": [ + { + "internalType": "uint256", + "name": "minKeyPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "refundPenaltyBasisPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceLockManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_granter", + "type": "address" + } + ], + "name": "revokeKeyGranter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "bool", + "name": "_approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_baseTokenURI", + "type": "string" + } + ], + "name": "setBaseTokenURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_onKeyPurchaseHook", + "type": "address" + }, + { + "internalType": "address", + "name": "_onKeyCancelHook", + "type": "address" + }, + { + "internalType": "address", + "name": "_onValidKeyHook", + "type": "address" + }, + { + "internalType": "address", + "name": "_onTokenURIHook", + "type": "address" + } + ], + "name": "setEventHooks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newExpirationDuration", + "type": "uint256" + } + ], + "name": "setExpirationDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_refundValue", + "type": "uint256" + } + ], + "name": "setGasRefundValue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_keyManager", + "type": "address" + } + ], + "name": "setKeyManagerOf", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxNumberOfKeys", + "type": "uint256" + } + ], + "name": "setMaxNumberOfKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_timeShared", + "type": "uint256" + } + ], + "name": "shareKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "tokenByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keyOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "tokenOfOwnerByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transferFeeBasisPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockProtocol", + "outputs": [ + { + "internalType": "contract IUnlock", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_beneficiary", + "type": "address" + } + ], + "name": "updateBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_keyPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + } + ], + "name": "updateKeyPricing", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_lockName", + "type": "string" + } + ], + "name": "updateLockName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_lockSymbol", + "type": "string" + } + ], + "name": "updateLockSymbol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_freeTrialLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_refundPenaltyBasisPoints", + "type": "uint256" + } + ], + "name": "updateRefundPenalty", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_transferFeeBasisPoints", + "type": "uint256" + } + ], + "name": "updateTransferFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080604052600061201e5534801561001657600080fd5b50615a8280620000276000396000f3fe60806040526004361061044b5760003560e01c806370a0823111610234578063aae4b8f71161012e578063d1bbd49c116100b6578063f0ba60401161007a578063f0ba604014610d4f578063f12c6b6e14610d64578063f3fef3a314610d84578063f5766b3914610da4578063fc42b58f14610dc457600080fd5b8063d1bbd49c14610cb3578063d250348514610ccf578063d32bfb6c14610cef578063d547741f14610d0f578063e985e9c514610d2f57600080fd5b8063b88d4fde116100fd578063b88d4fde14610c1e578063bf4a927014610c3e578063c1c98d0314610c5e578063c87b56dd14610c73578063cb0703c614610c9357600080fd5b8063aae4b8f714610b84578063abdf82ce14610ba4578063b11d7ec114610bde578063b585a6d514610bfe57600080fd5b806393fd1844116101bc578063a217fddf11610180578063a217fddf14610af8578063a22cb46514610b0d578063a2e4cd2e14610b2d578063a375cb0514610b4d578063a9059cbb14610b6457600080fd5b806393fd184414610a5457806395d89b4114610a6b578063970aaeb714610a8057806397aa390a14610ab75780639d76ea5814610ad757600080fd5b806381a3c9431161020357806381a3c943146109bf5780638577a6d5146109df5780638be4b870146109ff5780638ca2fbad14610a1257806391d1485414610a3457600080fd5b806370a082311461094757806374b6c10614610967578063782a4ade1461097e5780637ec2a7241461099e57600080fd5b80632f745c591161034557806352b0f638116102cd5780636207a8da116102915780636207a8da146108b1578063626485a3146108c75780636352211e146108e75780636d8ea5b4146109075780636eadde431461092757600080fd5b806352b0f6381461081a57806352d6a8e41461083a578063550ef3a81461085a578063564aa99d1461087a57806356e0d51f1461089a57600080fd5b806339f469861161031457806339f46986146107685780634136aa351461078857806342842e0e146107a35780634d025fed146107c35780634f6ccce7146107fa57600080fd5b80632f745c59146106e757806330176e131461070757806336568abe1461072757806338af3eed1461074757600080fd5b806318160ddd116103d3578063248a9ca311610397578063248a9ca31461063557806326e9ca07146106655780632af9162a146106865780632d33dd5b146106a65780632f2ff15d146106c757600080fd5b806318160ddd146105a5578063183767da146105bb578063217751bc146105d257806323100509146105f357806323b872dd1461061557600080fd5b8063097ba3331161041a578063097ba333146105085780630aaffd2a146105365780630f15023b1461055657806310e569731461057757806311a4c03a1461058e57600080fd5b806301ffc9a71461045757806306fdde031461048c578063081812fc146104ae578063095ea7b3146104e657600080fd5b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046152e6565b610de4565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610df5565b6040516104839190615672565b3480156104ba57600080fd5b506104ce6104c93660046152aa565b610e84565b6040516001600160a01b039091168152602001610483565b3480156104f257600080fd5b506105066105013660046151b3565b610f00565b005b34801561051457600080fd5b5061052861052336600461503e565b611035565b604051908152602001610483565b34801561054257600080fd5b50610506610551366004614ee1565b611081565b34801561056257600080fd5b50610c83546104ce906001600160a01b031681565b34801561058357600080fd5b50610528610c855481565b34801561059a57600080fd5b50610528610c845481565b3480156105b157600080fd5b50610c8754610528565b3480156105c757600080fd5b506105286124075481565b3480156105de57600080fd5b50610c8a546104ce906001600160a01b031681565b3480156105ff57600080fd5b506105286000805160206159ed83398151915281565b34801561062157600080fd5b506105066106303660046150a0565b611105565b34801561064157600080fd5b506105286106503660046152aa565b60009081526097602052604090206001015490565b34801561067157600080fd5b50610c8b546104ce906001600160a01b031681565b34801561069257600080fd5b506105066106a1366004614ee1565b611434565b3480156106b257600080fd5b50610c89546104ce906001600160a01b031681565b3480156106d357600080fd5b506105066106e23660046152c2565b6114b7565b3480156106f357600080fd5b506105286107023660046151b3565b6114e2565b34801561071357600080fd5b5061050661072236600461531e565b61156a565b34801561073357600080fd5b506105066107423660046152c2565b6115ab565b34801561075357600080fd5b50610c88546104ce906001600160a01b031681565b34801561077457600080fd5b5061050661078336600461544e565b611629565b34801561079457600080fd5b5061089a546104779060ff1681565b3480156107af57600080fd5b506105066107be3660046150a0565b6116a3565b3480156107cf57600080fd5b506104ce6107de3660046152aa565b611078602052600090815260409020546001600160a01b031681565b34801561080657600080fd5b506105286108153660046152aa565b6116be565b34801561082657600080fd5b50610477610835366004614ee1565b611705565b34801561084657600080fd5b50610528610855366004614ee1565b61171f565b34801561086657600080fd5b5061050661087536600461531e565b61172a565b34801561088657600080fd5b50610506610895366004614ee1565b61176b565b3480156108a657600080fd5b506105286127f05481565b3480156108bd57600080fd5b5061201e54610528565b3480156108d357600080fd5b506105066108e23660046152aa565b6117ee565b3480156108f357600080fd5b506104ce6109023660046152aa565b611828565b34801561091357600080fd5b50610477610922366004614ee1565b611844565b34801561093357600080fd5b50610506610942366004614f28565b61191d565b34801561095357600080fd5b50610528610962366004614ee1565b611a3c565b34801561097357600080fd5b50610528610c865481565b34801561098a57600080fd5b5061050661099936600461531e565b611a84565b3480156109aa57600080fd5b50610c8c546104ce906001600160a01b031681565b3480156109cb57600080fd5b506105066109da3660046151f9565b611b03565b3480156109eb57600080fd5b506105066109fa3660046152aa565b611d71565b610506610a0d3660046153de565b611dde565b348015610a1e57600080fd5b50610528600080516020615a2d83398151915281565b348015610a4057600080fd5b50610477610a4f3660046152c2565b61245e565b348015610a6057600080fd5b506105286110775481565b348015610a7757600080fd5b506104a1612489565b348015610a8c57600080fd5b50610528610a9b366004614ee1565b6001600160a01b03166000908152611075602052604090205490565b348015610ac357600080fd5b50610506610ad2366004614efd565b6125c2565b348015610ae357600080fd5b506104b1546104ce906001600160a01b031681565b348015610b0457600080fd5b50610528600081565b348015610b1957600080fd5b50610506610b28366004615186565b612626565b348015610b3957600080fd5b50610506610b483660046152c2565b6126fe565b348015610b5957600080fd5b506105286127f15481565b348015610b7057600080fd5b50610477610b7f3660046151b3565b612896565b348015610b9057600080fd5b50610477610b9f366004614ee1565b612905565b348015610bb057600080fd5b50610528610bbf366004614ee1565b6001600160a01b03166000908152611075602052604090206001015490565b348015610bea57600080fd5b50610506610bf93660046152c2565b61291f565b348015610c0a57600080fd5b50610477610c193660046151b3565b6129e3565b348015610c2a57600080fd5b50610506610c393660046150e0565b612aa7565b348015610c4a57600080fd5b50610506610c593660046152aa565b612b10565b348015610c6a57600080fd5b50610506612bb4565b348015610c7f57600080fd5b506104a1610c8e3660046152aa565b612c41565b348015610c9f57600080fd5b50610506610cae366004614fe3565b612ef8565b348015610cbf57600080fd5b5060405160098152602001610483565b348015610cdb57600080fd5b50610506610cea366004614ee1565b61312b565b348015610cfb57600080fd5b50610506610d0a3660046152aa565b6131ae565b348015610d1b57600080fd5b50610506610d2a3660046152c2565b613232565b348015610d3b57600080fd5b50610477610d4a366004614fab565b613258565b348015610d5b57600080fd5b506105066132f1565b348015610d7057600080fd5b50610506610d7f3660046151c5565b613336565b348015610d9057600080fd5b50610506610d9f3660046151b3565b61368b565b348015610db057600080fd5b50610506610dbf3660046152aa565b613818565b348015610dd057600080fd5b50610528610ddf3660046151b3565b613852565b6000610def826138cb565b92915050565b6114638054610e0390615937565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2f90615937565b8015610e7c5780601f10610e5157610100808354040283529160200191610e7c565b820191906000526020600020905b815481529060010190602001808311610e5f57829003601f168201915b505050505081565b6000818152611076602052604081205482906001600160a01b0316610ede5760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b60448201526064015b60405180910390fd5b600083815261107960205260409020546001600160a01b031691505b50919050565b61089a5460ff16610f235760405162461bcd60e51b8152600401610ed590615796565b80610f2e81336138d6565b80610f3e5750610f3e813361394e565b80610f67575060008181526110766020526040902054610f67906001600160a01b031633613258565b610f835760405162461bcd60e51b8152600401610ed5906156d5565b336001600160a01b0384161415610fcb5760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b60008281526110796020908152604080832080546001600160a01b0319166001600160a01b03888116918217909255611076909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611078858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b95945050505050565b61108a33612905565b806110a05750610c88546001600160a01b031633145b6110bc5760405162461bcd60e51b8152600401610ed59061570c565b6001600160a01b0381166110e25760405162461bcd60e51b8152600401610ed590615685565b610c8880546001600160a01b0319166001600160a01b0392909216919091179055565b61089a5460ff166111285760405162461bcd60e51b8152600401610ed590615796565b8261113281611844565b61114e5760405162461bcd60e51b8152600401610ed5906156ae565b8161115981336138d6565b806111695750611169813361394e565b80611192575060008181526110766020526040902054611192906001600160a01b031633613258565b6111ae5760405162461bcd60e51b8152600401610ed5906156d5565b846001600160a01b03166111c184611828565b6001600160a01b0316146112175760405162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e4552000000006044820152606401610ed5565b61271061240754106112645760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661128a5760405162461bcd60e51b8152600401610ed590615685565b836001600160a01b0316856001600160a01b031614156112df5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b60006112ec866000613852565b6001600160a01b03808816600090815261107560205260408082209289168252812060018101549394509192906113269088908690613a1f565b8154611342578682556113398888613b1f565b61134287613b9d565b4281116113705760018084015490830155868255611361876000613bdc565b61136b8888613b1f565b6113f8565b600019610c845414156113d75760405162461bcd60e51b815260206004820152602960248201527f526563697069656e7420616c7265616479206f776e732061206e6f6e2d6578706044820152686972696e67206b657960b81b6064820152608401610ed5565b428184600101546113e89190615861565b6113f291906158dd565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615a0d83398151915291a4505050505050505050565b61144c600080516020615a2d8339815191523361245e565b6114685760405162461bcd60e51b8152600401610ed590615741565b6114806000805160206159ed83398151915282613232565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6000828152609760205260409020600101546114d38133613c69565b6114dd8383613ccd565b505050565b60006114ed83611a3c565b8210801561150357506001600160a01b03831615155b6115485760405162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b6044820152606401610ed5565b6001600160a01b038316600090815261107560205260409020545b9392505050565b611582600080516020615a2d8339815191523361245e565b61159e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114658383614dc9565b6001600160a01b038116331461161b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610ed5565b6116258282613d53565b5050565b611641600080516020615a2d8339815191523361245e565b61165d5760405162461bcd60e51b8152600401610ed590615741565b60408051838152602081018390527fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c910160405180910390a16127f1919091556127f055565b6114dd83838360405180602001604052806000815250612aa7565b6000610c875482106117015760405162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b6044820152606401610ed5565b5090565b6000610def6000805160206159ed8339815191528361245e565b6000610def82613dba565b611742600080516020615a2d8339815191523361245e565b61175e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114638383614dc9565b611783600080516020615a2d8339815191523361245e565b61179f5760405162461bcd60e51b8152600401610ed590615741565b6117b76000805160206159ed833981519152826114b7565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b611806600080516020615a2d8339815191523361245e565b6118225760405162461bcd60e51b8152600401610ed590615741565b610c8455565b600090815261107660205260409020546001600160a01b031690565b6001600160a01b0380821660009081526110756020526040902060010154610c8b544290911191161561191857610c8b546001600160a01b0383811660008181526110756020526040908190206001015490516370b6638f60e11b815230600482015260248101929092526044820152831515606482015291169063e16cc71e9060840160206040518083038186803b1580156118e057600080fd5b505afa1580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def919061528e565b919050565b600054610100900460ff166119385760005460ff161561193c565b303b155b61199f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ed5565b600054610100900460ff161580156119c1576000805461ffff19166101011790555b6119ca86613eda565b6119dd61089a805460ff19166001179055565b6119e988888787613fb1565b6119f38383614053565b6119fb614079565b611a076103e86127f055565b611a108861408b565b611a206380ac58cd60e01b614113565b8015611a32576000805461ff00191690555b5050505050505050565b60006001600160a01b038216611a645760405162461bcd60e51b8152600401610ed590615685565b611a6d82611844565b611a78576000611a7b565b60015b60ff1692915050565b611a9c600080516020615a2d8339815191523361245e565b611ab85760405162461bcd60e51b8152600401610ed590615741565b611ac56114648383614dc9565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb978282604051611af792919061565e565b60405180910390a15050565b611b0c33611705565b80611b1b5750611b1b33612905565b611b995760405162461bcd60e51b815260206004820152604360248201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560448201527f20746865204b65794772616e746572206f72204c6f636b4d616e6167657220726064820152626f6c6560e81b608482015260a401610ed5565b60005b85811015611d68576000878783818110611bc657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bdb9190614ee1565b90506000868684818110611bff57634e487b7160e01b600052603260045260246000fd5b9050602002013590506000858585818110611c2a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c3f9190614ee1565b90506001600160a01b038316611c675760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b03831660009081526110756020526040902060018101548311611cc65760405162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b6044820152606401610ed5565b805480611ce357611cd682614192565b508054611ce38582613b1f565b611ced8184613bdc565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615a0d833981519152908290a450505050508080611d609061596c565b915050611b9c565b50505050505050565b611d89600080516020615a2d8339815191523361245e565b611da55760405162461bcd60e51b8152600401610ed590615741565b6040518181527f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49060200160405180910390a161240755565b61089a5460ff16611e015760405162461bcd60e51b8152600401610ed590615796565b610c8754610c865411611e465760405162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b6044820152606401610ed5565b6001600160a01b038516611e6c5760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b0385166000908152611075602052604081208054909181611f0857611e9783614192565b82549150611ea58883613b1f565b600019610c84541415611ebb5750600019611ecc565b610c8454611ec99042615861565b90505b60018301819055611edd8287613bdc565b60405182906001600160a01b038a1690600090600080516020615a0d833981519152908290a4612062565b4283600101541115611fe65760001983600101541415611f865760405162461bcd60e51b815260206004820152603360248201527f412076616c6964206e6f6e2d6578706972696e67206b65792063616e206e6f746044820152722062652070757263686173656420747769636560681b6064820152608401610ed5565b610c84548360010154611f999190615861565b600184018190556040518181529091506001600160a01b038916907f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9060200160405180910390a2612062565b600019610c84541415611ffc575060001961200d565b610c845461200a9042615861565b90505b6001830181905561201e8287613bdc565b876001600160a01b03167f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d8260405161205991815260200190565b60405180910390a25b60006120a5898988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b610c835460405163939d9f1f60e01b8152600481018390526001600160a01b038b8116602483015292935091169063939d9f1f90604401600060405180830381600087803b1580156120f657600080fd5b505af1925050508015612107575060015b61214f57610c83546040516001600160a01b03909116815230907f6b18946261693dfd6c760d986b28ad2238b5b0267f8e5b6bc40a2f998e2f20ac9060200160405180910390a25b6104b1546000906001600160a01b0316156121f957506104b1546040516323b872dd60e01b8152336004820152306024820152604481018c90528b916001600160a01b03169081906323b872dd90606401602060405180830381600087803b1580156121ba57600080fd5b505af11580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061528e565b50506121fc565b50345b818110156122415760405162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b6044820152606401610ed5565b610c89546001600160a01b0316156122c357610c8954604051639849965760e01b81526001600160a01b03909116906398499657906122909033908e908e908d908d908a908a906004016155ac565b600060405180830381600087803b1580156122aa57600080fd5b505af11580156122be573d6000803e3d6000fd5b505050505b61201e5415612451576104b1546001600160a01b031615612377576104b15461201e546040516323b872dd60e01b815230600482015233602482015260448101919091526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561233857600080fd5b505af115801561234c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612370919061528e565b5050612404565b61201e5460405160009133918381818185875af1925050503d80600081146123bb576040519150601f19603f3d011682016040523d82523d6000602084013e6123c0565b606091505b50509050806124025760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610ed5565b505b61201e546104b154604080519283526001600160a01b03909116602083015233917f522a883b471164223f18b50f326da8671372b64b4792eac0e63d447e714c3e3b910160405180910390a25b5050505050505050505050565b60009182526097602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060611464805461249990615937565b1515905061253157610c8360009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f057600080fd5b505afa158015612504573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261252c919081019061535d565b905090565b611464805461253f90615937565b80601f016020809104026020016040519081016040528092919081815260200182805461256b90615937565b80156125b85780601f1061258d576101008083540402835291602001916125b8565b820191906000526020600020905b81548152906001019060200180831161259b57829003601f168201915b5050505050905090565b6125da600080516020615a2d8339815191523361245e565b6125f65760405162461bcd60e51b8152600401610ed590615741565b8161260081611844565b61261c5760405162461bcd60e51b8152600401610ed5906156ae565b6114dd83836141b6565b61089a5460ff166126495760405162461bcd60e51b8152600401610ed590615796565b6001600160a01b0382163314156126915760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b33600081815261107a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612716600080516020615a2d8339815191523361245e565b6127325760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff166127555760405162461bcd60e51b8152600401610ed590615796565b610c85546104b1546001600160a01b0390811690831615806127e757506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ad57600080fd5b505afa1580156127c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e591906153c6565b115b6128235760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b610c858490556104b180546001600160a01b0319166001600160a01b0385811691821790925560408051858152602081018890529284169083015260608201527f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d49060800160405180910390a150505050565b600080610c8454836128a891906158be565b336000908152611075602052604081206001810154929350916128cc9042906158dd565b9050808310156128ea576128e586836000015485613336565b6128f9565b6128f933878460000154611105565b50600195945050505050565b6000610def600080516020615a2d8339815191528361245e565b6000828152611076602052604090205482906001600160a01b03166129745760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b6044820152606401610ed5565b61297e83336138d6565b8061298d575061298d33612905565b6129d95760405162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f555044415445006044820152606401610ed5565b6114dd8383613bdc565b60006129ee33612905565b80612a045750610c88546001600160a01b031633145b612a205760405162461bcd60e51b8152600401610ed59061570c565b6104b15460405163095ea7b360e01b81526001600160a01b038581166004830152602482018590529091169063095ea7b390604401602060405180830381600087803b158015612a6f57600080fd5b505af1158015612a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611563919061528e565b612ab2848484611105565b612abe848484846142b1565b612b0a5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b50505050565b612b28600080516020615a2d8339815191523361245e565b612b445760405162461bcd60e51b8152600401610ed590615741565b610c87548111612bae5760405162461bcd60e51b815260206004820152602f60248201527f6d61784e756d6265724f664b65797320697320736d616c6c6572207468616e2060448201526e6578697374696e6720737570706c7960881b6064820152608401610ed5565b610c8655565b612bcc600080516020615a2d8339815191523361245e565b612be85760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff16612c0b5760405162461bcd60e51b8152600401610ed590615796565b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a161089a805460ff19169055565b606080806000612c5030614370565b905060608515612c6a57612c63866145cb565b9250612c7d565b6040518060200160405280600081525092505b610c8c546001600160a01b031615612d6b576000612c9a87611828565b90506000612cc1826001600160a01b03166000908152611075602052604090206001015490565b610c8c5460405163988b93ad60e01b81523060048201523360248201526001600160a01b038581166044830152606482018c90526084820184905292935091169063988b93ad9060a40160006040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d5f919081019061535d565b98975050505050505050565b6114658054612d7990615937565b15159050612e2f57610c8360009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b158015612dd057600080fd5b505afa158015612de4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e0c919081019061535d565b9350604051806040016040528060018152602001602f60f81b8152509050612ee2565b6114658054612e3d90615937565b80601f0160208091040260200160405190810160405280929190818152602001828054612e6990615937565b8015612eb65780601f10612e8b57610100808354040283529160200191612eb6565b820191906000526020600020905b815481529060010190602001808311612e9957829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b612eee84838386614713565b9695505050505050565b612f10600080516020615a2d8339815191523361245e565b612f2c5760405162461bcd60e51b8152600401610ed590615741565b6001600160a01b0384161580612f4b57506001600160a01b0384163b15155b612f975760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b00000000000000006044820152606401610ed5565b6001600160a01b0383161580612fb657506001600160a01b0383163b15155b6130025760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b0000000000006044820152606401610ed5565b6001600160a01b038216158061302157506001600160a01b0382163b15155b61306d5760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f56414c49445f4b45595f484f4f4b000000000000006044820152606401610ed5565b6001600160a01b038116158061308c57506001600160a01b0381163b15155b6130d85760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f544f4b454e5f5552495f484f4f4b000000000000006044820152606401610ed5565b610c8980546001600160a01b039586166001600160a01b031991821617909155610c8a805494861694821694909417909355610c8c8054918516918416919091179055610c8b8054919093169116179055565b613143600080516020615a2d8339815191523361245e565b61315f5760405162461bcd60e51b8152600401610ed590615741565b613177600080516020615a2d833981519152826114b7565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b806131b981336138d6565b806131c957506131c9813361394e565b806131f25750600081815261107660205260409020546131f2906001600160a01b031633613258565b61320e5760405162461bcd60e51b8152600401610ed5906156d5565b600061321983611828565b9050600061322682613dba565b9050612b0a82826141b6565b60008281526097602052604090206001015461324e8133613c69565b6114dd8383613d53565b6001600160a01b03808316600090815261107560209081526040808320548084526110789092528220549192909116806132be575050506001600160a01b03808316600090815261107a602090815260408083209385168352929052205460ff16610def565b6001600160a01b03908116600090815261107a602090815260408083209387168352929052205460ff169150610def9050565b613309600080516020615a2d833981519152336115ab565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b61089a5460ff166133595760405162461bcd60e51b8152600401610ed590615796565b8161336481336138d6565b806133745750613374813361394e565b8061339d57506000818152611076602052604090205461339d906001600160a01b031633613258565b6133b95760405162461bcd60e51b8152600401610ed5906156d5565b61271061240754106134065760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661342c5760405162461bcd60e51b8152600401610ed590615685565b600083815261107660205260409020546001600160a01b031661344e81611844565b61346a5760405162461bcd60e51b8152600401610ed5906156ae565b846001600160a01b0316816001600160a01b031614156134bf5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b6001600160a01b038082166000908152611075602052604080822092881682528120805460018401549192909181906134f99042906158dd565b90506000613507878a613852565b90506000613515828b615861565b9050828110156135335789935061352e8b826000613a1f565b61357e565b61353d8884613852565b915061354982846158dd565b4260018901556040519094508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b846135c55761358c86614192565b8554945061359a8c86613b1f565b60405185906001600160a01b038e1690600090600080516020615a0d833981519152908290a46135db565b428660010154116135db576135db856000613bdc565b6135e785856001613a1f565b848c6001600160a01b0316896001600160a01b0316600080516020615a0d83398151915260405160405180910390a4613631888d87604051806020016040528060008152506142b1565b61367d5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b505050505050505050505050565b61369433612905565b806136aa5750610c88546001600160a01b031633145b6136c65760405162461bcd60e51b8152600401610ed59061570c565b60006001600160a01b0383166136dd575047613757565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b15801561371c57600080fd5b505afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375491906153c6565b90505b600082158061376557508183115b156137b457600082116137ad5760405162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b6044820152606401610ed5565b50806137b7565b50815b610c88546040518281526001600160a01b039182169186169033907f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9060200160405180910390a4610c8854612b0a9085906001600160a01b031683614745565b613830600080516020615a2d8339815191523361245e565b61384c5760405162461bcd60e51b8152600401610ed590615741565b61201e55565b600061385d83611844565b61386957506000610def565b6001600160a01b0383166000908152611075602052604081209080846138a05742836001015461389991906158dd565b91506138a4565b8491505b61271061240754836138b691906158be565b6138c0919061589e565b9350610def92505050565b6000610def82614781565b600082815261107860205260408120546001600160a01b03838116911614806139395750600083815261107860205260409020546001600160a01b03161580156139395750816001600160a01b031661392e84611828565b6001600160a01b0316145b1561394657506001610def565b506000610def565b60009182526110796020526040909120546001600160a01b0391821691161490565b610c89546000906001600160a01b031615613a1357610c895460405163221c1fd160e01b81526001600160a01b039091169063221c1fd1906139bc9033908890889088906004016155f7565b60206040518083038186803b1580156139d457600080fd5b505afa1580156139e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0c91906153c6565b9050611563565b50610c85549392505050565b6000613a2a84611828565b90506001600160a01b038116613a755760405162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b6044820152606401610ed5565b6001600160a01b03811660009081526110756020526040812060018101549091613a9e84611844565b90508415613aca578015613ac057613ab68683615861565b6001840155613ada565b613ab68642615861565b613ad486836158dd565b60018401555b60408051878152861515602082015288917fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3910160405180910390a250505050505050565b6001600160a01b0382166000908152611075602090815260409182902082518084019093528054835260010154908201819052613b6d576110778054906000613b678361596c565b91905055505b5060009081526110766020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600081815261107960205260409020546001600160a01b031615613bd95760008181526110796020526040902080546001600160a01b03191690555b50565b600082815261107860205260409020546001600160a01b038281169116146116255760008281526110786020526040902080546001600160a01b0319166001600160a01b038316179055613c2f82613b9d565b6040516001600160a01b0382169083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a35050565b613c73828261245e565b61162557613c8b816001600160a01b0316601461478c565b613c9683602061478c565b604051602001613ca7929190615537565b60408051601f198184030181529082905262461bcd60e51b8252610ed591600401615672565b613cd7828261245e565b6116255760008281526097602090815260408083206001600160a01b03851684529091529020805460ff19166001179055613d0f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b613d5d828261245e565b156116255760008281526097602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600081613dc681611844565b613de25760405162461bcd60e51b8152600401610ed5906156ae565b6001600160a01b038316600090815261107560205260409020610c84546000191415613e1457610c8554925050610efa565b6000428260010154613e2691906158dd565b9050610c84546127f15482613e3b9190615861565b10613e4b57610c85549350613e6b565b610c845481610c8554613e5e91906158be565b613e68919061589e565b93505b6127f1541580613e8a5750610c84546127f154613e889083615861565b105b15613ed25760006127106127f054610c8554613ea691906158be565b613eb0919061589e565b905080851115613ecb57613ec481866158dd565b9450613ed0565b600094505b505b505050919050565b6104b180546001600160a01b0319166001600160a01b0383169081179091551580613f7557506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f3b57600080fd5b505afa158015613f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7391906153c6565b115b613bd95760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b63bbf81e008311156140055760405162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f594541525300000000000000006044820152606401610ed5565b610c838054336001600160a01b031991821617909155610c8880549091166001600160a01b038616179055821561403c5782614040565b6000195b610c8455610c8591909155610c86555050565b61405b61496d565b6140686114638383614dc9565b50611625635b5e139f60e01b614113565b61408963780e9d6360e01b614113565b565b6140a3600080516020615a2d833981519152806149a4565b6140c96000805160206159ed833981519152600080516020615a2d8339815191526149a4565b6140d281612905565b6140ee576140ee600080516020615a2d833981519152826149ef565b6140f781611705565b613bd957613bd96000805160206159ed833981519152826149ef565b6001600160e01b0319808216141561416d5760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e74657266616365206964000000006044820152606401610ed5565b6001600160e01b0319166000908152606560205260409020805460ff19166001179055565b8054613bd957610c8780549060006141a98361596c565b9091555050610c87549055565b6001600160a01b0382166000818152611075602052604090819020805491519092339290917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce5289061420a9087815260200190565b60405180910390a44260018201558115614236576104b154614236906001600160a01b03168484614745565b610c8a546001600160a01b0316156114dd57610c8a5460405163b499b6c560e01b81523360048201526001600160a01b038581166024830152604482018590529091169063b499b6c590606401600060405180830381600087803b15801561429d57600080fd5b505af1158015611d68573d6000803e3d6000fd5b60006001600160a01b0384163b6142ca57506001614368565b604051630a85bd0160e11b81526000906001600160a01b0386169063150b7a02906142ff9033908a908990899060040161562b565b602060405180830381600087803b15801561431957600080fd5b505af115801561432d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143519190615302565b6001600160e01b031916630a85bd0160e11b149150505b949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b816000815181106143e957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061442657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060005b60148110156145c2578260048561445884600c615861565b6020811061447657634e487b7160e01b600052603260045260246000fd5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106144aa57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826144c58360026158be565b6144d0906002615861565b815181106144ee57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350828461451283600c615861565b6020811061453057634e487b7160e01b600052603260045260246000fd5b825191901a600f1690811061455557634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826145708360026158be565b61457b906003615861565b8151811061459957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350806145ba8161596c565b915050614440565b50949350505050565b606081806145f25750506040805180820190915260018152600360fc1b6020820152919050565b8260005b811561461c57806146068161596c565b91506146159050600a8361589e565b91506145f6565b6000816001600160401b0381111561464457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561466e576020820181803683370190505b509050815b8415614709576146846001826158dd565b90506000614693600a8761589e565b61469e90600a6158be565b6146a890876158dd565b6146b3906030615879565b905060008160f81b9050808484815181106146de57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614700600a8861589e565b96505050614673565b5095945050505050565b60608484848460405160200161472c94939291906154e0565b6040516020818303038152906040529050949350505050565b80156114dd576001600160a01b03831661476c576114dd6001600160a01b038316826149f9565b82612b0a6001600160a01b0382168484614b12565b6000610def82614b64565b6060600061479b8360026158be565b6147a6906002615861565b6001600160401b038111156147cb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147f5576020820181803683370190505b509050600360fc1b8160008151811061481e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061485b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061487f8460026158be565b61488a906001615861565b90505b600181111561491e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106148cc57634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106148f057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361491781615920565b905061488d565b5083156115635760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ed5565b600054610100900460ff166149945760405162461bcd60e51b8152600401610ed5906157bf565b61499c614b89565b614089614b89565b600082815260976020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6116258282613ccd565b80471015614a495760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ed5565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614a96576040519150601f19603f3d011682016040523d82523d6000602084013e614a9b565b606091505b50509050806114dd5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ed5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114dd908490614bb0565b60006001600160e01b03198216637965db0b60e01b1480610def5750610def82614c82565b600054610100900460ff166140895760405162461bcd60e51b8152600401610ed5906157bf565b6000614c05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614cbe9092919063ffffffff16565b8051909150156114dd5780806020019051810190614c23919061528e565b6114dd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ed5565b60006301ffc9a760e01b6001600160e01b031983161480610def5750506001600160e01b03191660009081526065602052604090205460ff1690565b6060614368848460008585843b614d175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ed5565b600080866001600160a01b03168587604051614d3391906154c4565b60006040518083038185875af1925050503d8060008114614d70576040519150601f19603f3d011682016040523d82523d6000602084013e614d75565b606091505b5091509150614d85828286614d90565b979650505050505050565b60608315614d9f575081611563565b825115614daf5782518084602001fd5b8160405162461bcd60e51b8152600401610ed59190615672565b828054614dd590615937565b90600052602060002090601f016020900481019282614df75760008555614e3d565b82601f10614e105782800160ff19823516178555614e3d565b82800160010185558215614e3d579182015b82811115614e3d578235825591602001919060010190614e22565b506117019291505b808211156117015760008155600101614e45565b60008083601f840112614e6a578182fd5b5081356001600160401b03811115614e80578182fd5b6020830191508360208260051b8501011115614e9b57600080fd5b9250929050565b60008083601f840112614eb3578182fd5b5081356001600160401b03811115614ec9578182fd5b602083019150836020828501011115614e9b57600080fd5b600060208284031215614ef2578081fd5b8135611563816159b3565b60008060408385031215614f0f578081fd5b8235614f1a816159b3565b946020939093013593505050565b600080600080600080600060c0888a031215614f42578283fd5b8735614f4d816159b3565b9650602088013595506040880135614f64816159b3565b9450606088013593506080880135925060a08801356001600160401b03811115614f8c578283fd5b614f988a828b01614ea2565b989b979a50959850939692959293505050565b60008060408385031215614fbd578182fd5b8235614fc8816159b3565b91506020830135614fd8816159b3565b809150509250929050565b60008060008060808587031215614ff8578384fd5b8435615003816159b3565b93506020850135615013816159b3565b92506040850135615023816159b3565b91506060850135615033816159b3565b939692955090935050565b60008060008060608587031215615053578384fd5b843561505e816159b3565b9350602085013561506e816159b3565b925060408501356001600160401b03811115615088578283fd5b61509487828801614ea2565b95989497509550505050565b6000806000606084860312156150b4578081fd5b83356150bf816159b3565b925060208401356150cf816159b3565b929592945050506040919091013590565b600080600080608085870312156150f5578182fd5b8435615100816159b3565b93506020850135615110816159b3565b92506040850135915060608501356001600160401b03811115615131578182fd5b8501601f81018713615141578182fd5b803561515461514f8261583a565b61580a565b818152886020838501011115615168578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615198578182fd5b82356151a3816159b3565b91506020830135614fd8816159c8565b60008060408385031215614f0f578182fd5b6000806000606084860312156151d9578081fd5b83356151e4816159b3565b95602085013595506040909401359392505050565b60008060008060008060608789031215615211578384fd5b86356001600160401b0380821115615227578586fd5b6152338a838b01614e59565b9098509650602089013591508082111561524b578586fd5b6152578a838b01614e59565b9096509450604089013591508082111561526f578384fd5b5061527c89828a01614e59565b979a9699509497509295939492505050565b60006020828403121561529f578081fd5b8151611563816159c8565b6000602082840312156152bb578081fd5b5035919050565b600080604083850312156152d4578182fd5b823591506020830135614fd8816159b3565b6000602082840312156152f7578081fd5b8135611563816159d6565b600060208284031215615313578081fd5b8151611563816159d6565b60008060208385031215615330578182fd5b82356001600160401b03811115615345578283fd5b61535185828601614ea2565b90969095509350505050565b60006020828403121561536e578081fd5b81516001600160401b03811115615383578182fd5b8201601f81018413615393578182fd5b80516153a161514f8261583a565b8181528560208385010111156153b5578384fd5b6110788260208301602086016158f4565b6000602082840312156153d7578081fd5b5051919050565b60008060008060008060a087890312156153f6578384fd5b863595506020870135615408816159b3565b94506040870135615418816159b3565b93506060870135615428816159b3565b925060808701356001600160401b03811115615442578283fd5b61527c89828a01614ea2565b60008060408385031215615460578182fd5b50508035926020909101359150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526154b08160208601602086016158f4565b601f01601f19169290920160200192915050565b600082516154d68184602087016158f4565b9190910192915050565b600085516154f2818460208a016158f4565b855190830190615506818360208a016158f4565b85519101906155198183602089016158f4565b845191019061552c8183602088016158f4565b019695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161556f8160178501602088016158f4565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516155a08160288401602088016158f4565b01602801949350505050565b6001600160a01b03888116825287811660208301528616604082015260c0606082018190526000906155e1908301868861546f565b60808301949094525060a0015295945050505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090612eee90830184615498565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612eee90830184615498565b60208152600061436860208301848661546f565b6020815260006115636020830184615498565b6020808252600f908201526e494e56414c49445f4144445245535360881b604082015260600190565b6020808252600d908201526c12d15657d393d517d590531251609a1b604082015260600190565b6020808252601c908201527f4f4e4c595f4b45595f4d414e414745525f4f525f415050524f56454400000000604082015260600190565b6020808252818101527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604082015260600190565b60208082526035908201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560408201527420746865204c6f636b4d616e6167657220726f6c6560581b606082015260800190565b6020808252600f908201526e1313d0d2d7d11154149150d0551151608a1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156158325761583261599d565b604052919050565b60006001600160401b038211156158535761585361599d565b50601f01601f191660200190565b6000821982111561587457615874615987565b500190565b600060ff821660ff84168060ff0382111561589657615896615987565b019392505050565b6000826158b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156158d8576158d8615987565b500290565b6000828210156158ef576158ef615987565b500390565b60005b8381101561590f5781810151838201526020016158f7565b83811115612b0a5750506000910152565b60008161592f5761592f615987565b506000190190565b600181811c9082168061594b57607f821691505b60208210811415610efa57634e487b7160e01b600052602260045260246000fd5b600060001982141561598057615980615987565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613bd957600080fd5b8015158114613bd957600080fd5b6001600160e01b031981168114613bd957600080fdfeb309c40027c81d382c3b58d8de24207a34b27e1db369b1434e4a11311f154b5eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efb89cdd26cddd51301940bf2715f765b626b8a5a9e2681ac62dc83cc2db2530c0a2646970667358221220a966aec0ea72cc36f07dd0afa1e277f5eb266146078b7651e59c22655e0639ae64736f6c63430008040033", + "deployedBytecode": "0x60806040526004361061044b5760003560e01c806370a0823111610234578063aae4b8f71161012e578063d1bbd49c116100b6578063f0ba60401161007a578063f0ba604014610d4f578063f12c6b6e14610d64578063f3fef3a314610d84578063f5766b3914610da4578063fc42b58f14610dc457600080fd5b8063d1bbd49c14610cb3578063d250348514610ccf578063d32bfb6c14610cef578063d547741f14610d0f578063e985e9c514610d2f57600080fd5b8063b88d4fde116100fd578063b88d4fde14610c1e578063bf4a927014610c3e578063c1c98d0314610c5e578063c87b56dd14610c73578063cb0703c614610c9357600080fd5b8063aae4b8f714610b84578063abdf82ce14610ba4578063b11d7ec114610bde578063b585a6d514610bfe57600080fd5b806393fd1844116101bc578063a217fddf11610180578063a217fddf14610af8578063a22cb46514610b0d578063a2e4cd2e14610b2d578063a375cb0514610b4d578063a9059cbb14610b6457600080fd5b806393fd184414610a5457806395d89b4114610a6b578063970aaeb714610a8057806397aa390a14610ab75780639d76ea5814610ad757600080fd5b806381a3c9431161020357806381a3c943146109bf5780638577a6d5146109df5780638be4b870146109ff5780638ca2fbad14610a1257806391d1485414610a3457600080fd5b806370a082311461094757806374b6c10614610967578063782a4ade1461097e5780637ec2a7241461099e57600080fd5b80632f745c591161034557806352b0f638116102cd5780636207a8da116102915780636207a8da146108b1578063626485a3146108c75780636352211e146108e75780636d8ea5b4146109075780636eadde431461092757600080fd5b806352b0f6381461081a57806352d6a8e41461083a578063550ef3a81461085a578063564aa99d1461087a57806356e0d51f1461089a57600080fd5b806339f469861161031457806339f46986146107685780634136aa351461078857806342842e0e146107a35780634d025fed146107c35780634f6ccce7146107fa57600080fd5b80632f745c59146106e757806330176e131461070757806336568abe1461072757806338af3eed1461074757600080fd5b806318160ddd116103d3578063248a9ca311610397578063248a9ca31461063557806326e9ca07146106655780632af9162a146106865780632d33dd5b146106a65780632f2ff15d146106c757600080fd5b806318160ddd146105a5578063183767da146105bb578063217751bc146105d257806323100509146105f357806323b872dd1461061557600080fd5b8063097ba3331161041a578063097ba333146105085780630aaffd2a146105365780630f15023b1461055657806310e569731461057757806311a4c03a1461058e57600080fd5b806301ffc9a71461045757806306fdde031461048c578063081812fc146104ae578063095ea7b3146104e657600080fd5b3661045257005b600080fd5b34801561046357600080fd5b506104776104723660046152e6565b610de4565b60405190151581526020015b60405180910390f35b34801561049857600080fd5b506104a1610df5565b6040516104839190615672565b3480156104ba57600080fd5b506104ce6104c93660046152aa565b610e84565b6040516001600160a01b039091168152602001610483565b3480156104f257600080fd5b506105066105013660046151b3565b610f00565b005b34801561051457600080fd5b5061052861052336600461503e565b611035565b604051908152602001610483565b34801561054257600080fd5b50610506610551366004614ee1565b611081565b34801561056257600080fd5b50610c83546104ce906001600160a01b031681565b34801561058357600080fd5b50610528610c855481565b34801561059a57600080fd5b50610528610c845481565b3480156105b157600080fd5b50610c8754610528565b3480156105c757600080fd5b506105286124075481565b3480156105de57600080fd5b50610c8a546104ce906001600160a01b031681565b3480156105ff57600080fd5b506105286000805160206159ed83398151915281565b34801561062157600080fd5b506105066106303660046150a0565b611105565b34801561064157600080fd5b506105286106503660046152aa565b60009081526097602052604090206001015490565b34801561067157600080fd5b50610c8b546104ce906001600160a01b031681565b34801561069257600080fd5b506105066106a1366004614ee1565b611434565b3480156106b257600080fd5b50610c89546104ce906001600160a01b031681565b3480156106d357600080fd5b506105066106e23660046152c2565b6114b7565b3480156106f357600080fd5b506105286107023660046151b3565b6114e2565b34801561071357600080fd5b5061050661072236600461531e565b61156a565b34801561073357600080fd5b506105066107423660046152c2565b6115ab565b34801561075357600080fd5b50610c88546104ce906001600160a01b031681565b34801561077457600080fd5b5061050661078336600461544e565b611629565b34801561079457600080fd5b5061089a546104779060ff1681565b3480156107af57600080fd5b506105066107be3660046150a0565b6116a3565b3480156107cf57600080fd5b506104ce6107de3660046152aa565b611078602052600090815260409020546001600160a01b031681565b34801561080657600080fd5b506105286108153660046152aa565b6116be565b34801561082657600080fd5b50610477610835366004614ee1565b611705565b34801561084657600080fd5b50610528610855366004614ee1565b61171f565b34801561086657600080fd5b5061050661087536600461531e565b61172a565b34801561088657600080fd5b50610506610895366004614ee1565b61176b565b3480156108a657600080fd5b506105286127f05481565b3480156108bd57600080fd5b5061201e54610528565b3480156108d357600080fd5b506105066108e23660046152aa565b6117ee565b3480156108f357600080fd5b506104ce6109023660046152aa565b611828565b34801561091357600080fd5b50610477610922366004614ee1565b611844565b34801561093357600080fd5b50610506610942366004614f28565b61191d565b34801561095357600080fd5b50610528610962366004614ee1565b611a3c565b34801561097357600080fd5b50610528610c865481565b34801561098a57600080fd5b5061050661099936600461531e565b611a84565b3480156109aa57600080fd5b50610c8c546104ce906001600160a01b031681565b3480156109cb57600080fd5b506105066109da3660046151f9565b611b03565b3480156109eb57600080fd5b506105066109fa3660046152aa565b611d71565b610506610a0d3660046153de565b611dde565b348015610a1e57600080fd5b50610528600080516020615a2d83398151915281565b348015610a4057600080fd5b50610477610a4f3660046152c2565b61245e565b348015610a6057600080fd5b506105286110775481565b348015610a7757600080fd5b506104a1612489565b348015610a8c57600080fd5b50610528610a9b366004614ee1565b6001600160a01b03166000908152611075602052604090205490565b348015610ac357600080fd5b50610506610ad2366004614efd565b6125c2565b348015610ae357600080fd5b506104b1546104ce906001600160a01b031681565b348015610b0457600080fd5b50610528600081565b348015610b1957600080fd5b50610506610b28366004615186565b612626565b348015610b3957600080fd5b50610506610b483660046152c2565b6126fe565b348015610b5957600080fd5b506105286127f15481565b348015610b7057600080fd5b50610477610b7f3660046151b3565b612896565b348015610b9057600080fd5b50610477610b9f366004614ee1565b612905565b348015610bb057600080fd5b50610528610bbf366004614ee1565b6001600160a01b03166000908152611075602052604090206001015490565b348015610bea57600080fd5b50610506610bf93660046152c2565b61291f565b348015610c0a57600080fd5b50610477610c193660046151b3565b6129e3565b348015610c2a57600080fd5b50610506610c393660046150e0565b612aa7565b348015610c4a57600080fd5b50610506610c593660046152aa565b612b10565b348015610c6a57600080fd5b50610506612bb4565b348015610c7f57600080fd5b506104a1610c8e3660046152aa565b612c41565b348015610c9f57600080fd5b50610506610cae366004614fe3565b612ef8565b348015610cbf57600080fd5b5060405160098152602001610483565b348015610cdb57600080fd5b50610506610cea366004614ee1565b61312b565b348015610cfb57600080fd5b50610506610d0a3660046152aa565b6131ae565b348015610d1b57600080fd5b50610506610d2a3660046152c2565b613232565b348015610d3b57600080fd5b50610477610d4a366004614fab565b613258565b348015610d5b57600080fd5b506105066132f1565b348015610d7057600080fd5b50610506610d7f3660046151c5565b613336565b348015610d9057600080fd5b50610506610d9f3660046151b3565b61368b565b348015610db057600080fd5b50610506610dbf3660046152aa565b613818565b348015610dd057600080fd5b50610528610ddf3660046151b3565b613852565b6000610def826138cb565b92915050565b6114638054610e0390615937565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2f90615937565b8015610e7c5780601f10610e5157610100808354040283529160200191610e7c565b820191906000526020600020905b815481529060010190602001808311610e5f57829003601f168201915b505050505081565b6000818152611076602052604081205482906001600160a01b0316610ede5760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b60448201526064015b60405180910390fd5b600083815261107960205260409020546001600160a01b031691505b50919050565b61089a5460ff16610f235760405162461bcd60e51b8152600401610ed590615796565b80610f2e81336138d6565b80610f3e5750610f3e813361394e565b80610f67575060008181526110766020526040902054610f67906001600160a01b031633613258565b610f835760405162461bcd60e51b8152600401610ed5906156d5565b336001600160a01b0384161415610fcb5760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b60008281526110796020908152604080832080546001600160a01b0319166001600160a01b03888116918217909255611076909352818420549151869492909116917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611078858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b95945050505050565b61108a33612905565b806110a05750610c88546001600160a01b031633145b6110bc5760405162461bcd60e51b8152600401610ed59061570c565b6001600160a01b0381166110e25760405162461bcd60e51b8152600401610ed590615685565b610c8880546001600160a01b0319166001600160a01b0392909216919091179055565b61089a5460ff166111285760405162461bcd60e51b8152600401610ed590615796565b8261113281611844565b61114e5760405162461bcd60e51b8152600401610ed5906156ae565b8161115981336138d6565b806111695750611169813361394e565b80611192575060008181526110766020526040902054611192906001600160a01b031633613258565b6111ae5760405162461bcd60e51b8152600401610ed5906156d5565b846001600160a01b03166111c184611828565b6001600160a01b0316146112175760405162461bcd60e51b815260206004820152601c60248201527f5452414e534645525f46524f4d3a204e4f545f4b45595f4f574e4552000000006044820152606401610ed5565b61271061240754106112645760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661128a5760405162461bcd60e51b8152600401610ed590615685565b836001600160a01b0316856001600160a01b031614156112df5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b60006112ec866000613852565b6001600160a01b03808816600090815261107560205260408082209289168252812060018101549394509192906113269088908690613a1f565b8154611342578682556113398888613b1f565b61134287613b9d565b4281116113705760018084015490830155868255611361876000613bdc565b61136b8888613b1f565b6113f8565b600019610c845414156113d75760405162461bcd60e51b815260206004820152602960248201527f526563697069656e7420616c7265616479206f776e732061206e6f6e2d6578706044820152686972696e67206b657960b81b6064820152608401610ed5565b428184600101546113e89190615861565b6113f291906158dd565b60018301555b426001840155600080845560405188916001600160a01b03808c1692908d1691600080516020615a0d83398151915291a4505050505050505050565b61144c600080516020615a2d8339815191523361245e565b6114685760405162461bcd60e51b8152600401610ed590615741565b6114806000805160206159ed83398151915282613232565b6040516001600160a01b038216907f766f6199fea59554b9ff688e413302b9200f85d74811c053c12d945ac6d8dd7a90600090a250565b6000828152609760205260409020600101546114d38133613c69565b6114dd8383613ccd565b505050565b60006114ed83611a3c565b8210801561150357506001600160a01b03831615155b6115485760405162461bcd60e51b815260206004820152601660248201527527a7262cafa7a722afa5a2acafa822a92fa7aba722a960511b6044820152606401610ed5565b6001600160a01b038316600090815261107560205260409020545b9392505050565b611582600080516020615a2d8339815191523361245e565b61159e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114658383614dc9565b6001600160a01b038116331461161b5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610ed5565b6116258282613d53565b5050565b611641600080516020615a2d8339815191523361245e565b61165d5760405162461bcd60e51b8152600401610ed590615741565b60408051838152602081018390527fd6867bc538320e67d7bdc35860c27c08486eb490b4fd9b820fff18fb28381d3c910160405180910390a16127f1919091556127f055565b6114dd83838360405180602001604052806000815250612aa7565b6000610c875482106117015760405162461bcd60e51b815260206004820152600c60248201526b4f55545f4f465f52414e474560a01b6044820152606401610ed5565b5090565b6000610def6000805160206159ed8339815191528361245e565b6000610def82613dba565b611742600080516020615a2d8339815191523361245e565b61175e5760405162461bcd60e51b8152600401610ed590615741565b6114dd6114638383614dc9565b611783600080516020615a2d8339815191523361245e565b61179f5760405162461bcd60e51b8152600401610ed590615741565b6117b76000805160206159ed833981519152826114b7565b6040516001600160a01b038216907f684f8a71407db0c334454ebe9c9b288549317893a20b10dc779ec5c118dcd12190600090a250565b611806600080516020615a2d8339815191523361245e565b6118225760405162461bcd60e51b8152600401610ed590615741565b610c8455565b600090815261107660205260409020546001600160a01b031690565b6001600160a01b0380821660009081526110756020526040902060010154610c8b544290911191161561191857610c8b546001600160a01b0383811660008181526110756020526040908190206001015490516370b6638f60e11b815230600482015260248101929092526044820152831515606482015291169063e16cc71e9060840160206040518083038186803b1580156118e057600080fd5b505afa1580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def919061528e565b919050565b600054610100900460ff166119385760005460ff161561193c565b303b155b61199f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ed5565b600054610100900460ff161580156119c1576000805461ffff19166101011790555b6119ca86613eda565b6119dd61089a805460ff19166001179055565b6119e988888787613fb1565b6119f38383614053565b6119fb614079565b611a076103e86127f055565b611a108861408b565b611a206380ac58cd60e01b614113565b8015611a32576000805461ff00191690555b5050505050505050565b60006001600160a01b038216611a645760405162461bcd60e51b8152600401610ed590615685565b611a6d82611844565b611a78576000611a7b565b60015b60ff1692915050565b611a9c600080516020615a2d8339815191523361245e565b611ab85760405162461bcd60e51b8152600401610ed590615741565b611ac56114648383614dc9565b507f8868e22e84ebf32da89b2ebcb0ac642816304ea3863b257f240df9098719cb978282604051611af792919061565e565b60405180910390a15050565b611b0c33611705565b80611b1b5750611b1b33612905565b611b995760405162461bcd60e51b815260206004820152604360248201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560448201527f20746865204b65794772616e746572206f72204c6f636b4d616e6167657220726064820152626f6c6560e81b608482015260a401610ed5565b60005b85811015611d68576000878783818110611bc657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611bdb9190614ee1565b90506000868684818110611bff57634e487b7160e01b600052603260045260246000fd5b9050602002013590506000858585818110611c2a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c3f9190614ee1565b90506001600160a01b038316611c675760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b03831660009081526110756020526040902060018101548311611cc65760405162461bcd60e51b815260206004820152601060248201526f414c52454144595f4f574e535f4b455960801b6044820152606401610ed5565b805480611ce357611cd682614192565b508054611ce38582613b1f565b611ced8184613bdc565b6040516001600160a01b0384169082907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a36001820184905560405181906001600160a01b03871690600090600080516020615a0d833981519152908290a450505050508080611d609061596c565b915050611b9c565b50505050505050565b611d89600080516020615a2d8339815191523361245e565b611da55760405162461bcd60e51b8152600401610ed590615741565b6040518181527f0496ed1e61eb69727f9659a8e859288db4758ffb1f744d1c1424634f90a257f49060200160405180910390a161240755565b61089a5460ff16611e015760405162461bcd60e51b8152600401610ed590615796565b610c8754610c865411611e465760405162461bcd60e51b815260206004820152600d60248201526c1313d0d2d7d4d3d31117d3d555609a1b6044820152606401610ed5565b6001600160a01b038516611e6c5760405162461bcd60e51b8152600401610ed590615685565b6001600160a01b0385166000908152611075602052604081208054909181611f0857611e9783614192565b82549150611ea58883613b1f565b600019610c84541415611ebb5750600019611ecc565b610c8454611ec99042615861565b90505b60018301819055611edd8287613bdc565b60405182906001600160a01b038a1690600090600080516020615a0d833981519152908290a4612062565b4283600101541115611fe65760001983600101541415611f865760405162461bcd60e51b815260206004820152603360248201527f412076616c6964206e6f6e2d6578706972696e67206b65792063616e206e6f746044820152722062652070757263686173656420747769636560681b6064820152608401610ed5565b610c84548360010154611f999190615861565b600184018190556040518181529091506001600160a01b038916907f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d9060200160405180910390a2612062565b600019610c84541415611ffc575060001961200d565b610c845461200a9042615861565b90505b6001830181905561201e8287613bdc565b876001600160a01b03167f872bd7c99ad5e7b6ed7f0a890f348839cb8e225c9deaa3909afedae54c93d17d8260405161205991815260200190565b60405180910390a25b60006120a5898988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061397092505050565b610c835460405163939d9f1f60e01b8152600481018390526001600160a01b038b8116602483015292935091169063939d9f1f90604401600060405180830381600087803b1580156120f657600080fd5b505af1925050508015612107575060015b61214f57610c83546040516001600160a01b03909116815230907f6b18946261693dfd6c760d986b28ad2238b5b0267f8e5b6bc40a2f998e2f20ac9060200160405180910390a25b6104b1546000906001600160a01b0316156121f957506104b1546040516323b872dd60e01b8152336004820152306024820152604481018c90528b916001600160a01b03169081906323b872dd90606401602060405180830381600087803b1580156121ba57600080fd5b505af11580156121ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f2919061528e565b50506121fc565b50345b818110156122415760405162461bcd60e51b8152602060048201526012602482015271494e53554646494349454e545f56414c554560701b6044820152606401610ed5565b610c89546001600160a01b0316156122c357610c8954604051639849965760e01b81526001600160a01b03909116906398499657906122909033908e908e908d908d908a908a906004016155ac565b600060405180830381600087803b1580156122aa57600080fd5b505af11580156122be573d6000803e3d6000fd5b505050505b61201e5415612451576104b1546001600160a01b031615612377576104b15461201e546040516323b872dd60e01b815230600482015233602482015260448101919091526001600160a01b039091169081906323b872dd90606401602060405180830381600087803b15801561233857600080fd5b505af115801561234c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612370919061528e565b5050612404565b61201e5460405160009133918381818185875af1925050503d80600081146123bb576040519150601f19603f3d011682016040523d82523d6000602084013e6123c0565b606091505b50509050806124025760405162461bcd60e51b815260206004820152600e60248201526d2932b33ab732103330b4b632b21760911b6044820152606401610ed5565b505b61201e546104b154604080519283526001600160a01b03909116602083015233917f522a883b471164223f18b50f326da8671372b64b4792eac0e63d447e714c3e3b910160405180910390a25b5050505050505050505050565b60009182526097602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060611464805461249990615937565b1515905061253157610c8360009054906101000a90046001600160a01b03166001600160a01b031663cec410526040518163ffffffff1660e01b815260040160006040518083038186803b1580156124f057600080fd5b505afa158015612504573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261252c919081019061535d565b905090565b611464805461253f90615937565b80601f016020809104026020016040519081016040528092919081815260200182805461256b90615937565b80156125b85780601f1061258d576101008083540402835291602001916125b8565b820191906000526020600020905b81548152906001019060200180831161259b57829003601f168201915b5050505050905090565b6125da600080516020615a2d8339815191523361245e565b6125f65760405162461bcd60e51b8152600401610ed590615741565b8161260081611844565b61261c5760405162461bcd60e51b8152600401610ed5906156ae565b6114dd83836141b6565b61089a5460ff166126495760405162461bcd60e51b8152600401610ed590615796565b6001600160a01b0382163314156126915760405162461bcd60e51b815260206004820152600c60248201526b20a8282927ab22afa9a2a62360a11b6044820152606401610ed5565b33600081815261107a602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612716600080516020615a2d8339815191523361245e565b6127325760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff166127555760405162461bcd60e51b8152600401610ed590615796565b610c85546104b1546001600160a01b0390811690831615806127e757506000836001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127ad57600080fd5b505afa1580156127c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127e591906153c6565b115b6128235760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b610c858490556104b180546001600160a01b0319166001600160a01b0385811691821790925560408051858152602081018890529284169083015260608201527f3615065ccf48367ac483ac86701248e2e5ff55bdd9be845007d34a3b68d719d49060800160405180910390a150505050565b600080610c8454836128a891906158be565b336000908152611075602052604081206001810154929350916128cc9042906158dd565b9050808310156128ea576128e586836000015485613336565b6128f9565b6128f933878460000154611105565b50600195945050505050565b6000610def600080516020615a2d8339815191528361245e565b6000828152611076602052604090205482906001600160a01b03166129745760405162461bcd60e51b815260206004820152600b60248201526a4e4f5f535543485f4b455960a81b6044820152606401610ed5565b61297e83336138d6565b8061298d575061298d33612905565b6129d95760405162461bcd60e51b815260206004820152601f60248201527f554e415554484f52495a45445f4b45595f4d414e414745525f555044415445006044820152606401610ed5565b6114dd8383613bdc565b60006129ee33612905565b80612a045750610c88546001600160a01b031633145b612a205760405162461bcd60e51b8152600401610ed59061570c565b6104b15460405163095ea7b360e01b81526001600160a01b038581166004830152602482018590529091169063095ea7b390604401602060405180830381600087803b158015612a6f57600080fd5b505af1158015612a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611563919061528e565b612ab2848484611105565b612abe848484846142b1565b612b0a5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b50505050565b612b28600080516020615a2d8339815191523361245e565b612b445760405162461bcd60e51b8152600401610ed590615741565b610c87548111612bae5760405162461bcd60e51b815260206004820152602f60248201527f6d61784e756d6265724f664b65797320697320736d616c6c6572207468616e2060448201526e6578697374696e6720737570706c7960881b6064820152608401610ed5565b610c8655565b612bcc600080516020615a2d8339815191523361245e565b612be85760405162461bcd60e51b8152600401610ed590615741565b61089a5460ff16612c0b5760405162461bcd60e51b8152600401610ed590615796565b6040517f25a311358326fb18c62efc24bc28d3126acee8d2a67fd8b2145b757dc8bd1bc190600090a161089a805460ff19169055565b606080806000612c5030614370565b905060608515612c6a57612c63866145cb565b9250612c7d565b6040518060200160405280600081525092505b610c8c546001600160a01b031615612d6b576000612c9a87611828565b90506000612cc1826001600160a01b03166000908152611075602052604090206001015490565b610c8c5460405163988b93ad60e01b81523060048201523360248201526001600160a01b038581166044830152606482018c90526084820184905292935091169063988b93ad9060a40160006040518083038186803b158015612d2357600080fd5b505afa158015612d37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d5f919081019061535d565b98975050505050505050565b6114658054612d7990615937565b15159050612e2f57610c8360009054906101000a90046001600160a01b03166001600160a01b031663a998e9fb6040518163ffffffff1660e01b815260040160006040518083038186803b158015612dd057600080fd5b505afa158015612de4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e0c919081019061535d565b9350604051806040016040528060018152602001602f60f81b8152509050612ee2565b6114658054612e3d90615937565b80601f0160208091040260200160405190810160405280929190818152602001828054612e6990615937565b8015612eb65780601f10612e8b57610100808354040283529160200191612eb6565b820191906000526020600020905b815481529060010190602001808311612e9957829003601f168201915b505050505093506040518060200160405280600081525090506040518060200160405280600081525091505b612eee84838386614713565b9695505050505050565b612f10600080516020615a2d8339815191523361245e565b612f2c5760405162461bcd60e51b8152600401610ed590615741565b6001600160a01b0384161580612f4b57506001600160a01b0384163b15155b612f975760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f4f4e5f4b45595f534f4c445f484f4f4b00000000000000006044820152606401610ed5565b6001600160a01b0383161580612fb657506001600160a01b0383163b15155b6130025760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f4f4e5f4b45595f43414e43454c5f484f4f4b0000000000006044820152606401610ed5565b6001600160a01b038216158061302157506001600160a01b0382163b15155b61306d5760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f56414c49445f4b45595f484f4f4b000000000000006044820152606401610ed5565b6001600160a01b038116158061308c57506001600160a01b0381163b15155b6130d85760405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4f4e5f544f4b454e5f5552495f484f4f4b000000000000006044820152606401610ed5565b610c8980546001600160a01b039586166001600160a01b031991821617909155610c8a805494861694821694909417909355610c8c8054918516918416919091179055610c8b8054919093169116179055565b613143600080516020615a2d8339815191523361245e565b61315f5760405162461bcd60e51b8152600401610ed590615741565b613177600080516020615a2d833981519152826114b7565b6040516001600160a01b038216907f91d5c045d5bd98bf59a379b259ebca05b93bf79af1845fdf87e3172385d4c7f790600090a250565b806131b981336138d6565b806131c957506131c9813361394e565b806131f25750600081815261107660205260409020546131f2906001600160a01b031633613258565b61320e5760405162461bcd60e51b8152600401610ed5906156d5565b600061321983611828565b9050600061322682613dba565b9050612b0a82826141b6565b60008281526097602052604090206001015461324e8133613c69565b6114dd8383613d53565b6001600160a01b03808316600090815261107560209081526040808320548084526110789092528220549192909116806132be575050506001600160a01b03808316600090815261107a602090815260408083209385168352929052205460ff16610def565b6001600160a01b03908116600090815261107a602090815260408083209387168352929052205460ff169150610def9050565b613309600080516020615a2d833981519152336115ab565b60405133907f42885193b8178d25fca25a38e6fcc93918501e91be06d85e0c8afb3bad95238090600090a2565b61089a5460ff166133595760405162461bcd60e51b8152600401610ed590615796565b8161336481336138d6565b806133745750613374813361394e565b8061339d57506000818152611076602052604090205461339d906001600160a01b031633613258565b6133b95760405162461bcd60e51b8152600401610ed5906156d5565b61271061240754106134065760405162461bcd60e51b815260206004820152601660248201527512d15657d514905394d1915494d7d11254d05093115160521b6044820152606401610ed5565b6001600160a01b03841661342c5760405162461bcd60e51b8152600401610ed590615685565b600083815261107660205260409020546001600160a01b031661344e81611844565b61346a5760405162461bcd60e51b8152600401610ed5906156ae565b846001600160a01b0316816001600160a01b031614156134bf5760405162461bcd60e51b815260206004820152601060248201526f2a2920a729a322a92faa27afa9a2a62360811b6044820152606401610ed5565b6001600160a01b038082166000908152611075602052604080822092881682528120805460018401549192909181906134f99042906158dd565b90506000613507878a613852565b90506000613515828b615861565b9050828110156135335789935061352e8b826000613a1f565b61357e565b61353d8884613852565b915061354982846158dd565b4260018901556040519094508b907f59f2fe866dd27a1c2d34115520888c3150365cbc931aab97fa88c4b9ab40b79590600090a25b846135c55761358c86614192565b8554945061359a8c86613b1f565b60405185906001600160a01b038e1690600090600080516020615a0d833981519152908290a46135db565b428660010154116135db576135db856000613bdc565b6135e785856001613a1f565b848c6001600160a01b0316896001600160a01b0316600080516020615a0d83398151915260405160405180910390a4613631888d87604051806020016040528060008152506142b1565b61367d5760405162461bcd60e51b815260206004820152601d60248201527f4e4f4e5f434f4d504c49414e545f4552433732315f52454345495645520000006044820152606401610ed5565b505050505050505050505050565b61369433612905565b806136aa5750610c88546001600160a01b031633145b6136c65760405162461bcd60e51b8152600401610ed59061570c565b60006001600160a01b0383166136dd575047613757565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b15801561371c57600080fd5b505afa158015613730573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375491906153c6565b90505b600082158061376557508183115b156137b457600082116137ad5760405162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f46554e445360801b6044820152606401610ed5565b50806137b7565b50815b610c88546040518281526001600160a01b039182169186169033907f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e9060200160405180910390a4610c8854612b0a9085906001600160a01b031683614745565b613830600080516020615a2d8339815191523361245e565b61384c5760405162461bcd60e51b8152600401610ed590615741565b61201e55565b600061385d83611844565b61386957506000610def565b6001600160a01b0383166000908152611075602052604081209080846138a05742836001015461389991906158dd565b91506138a4565b8491505b61271061240754836138b691906158be565b6138c0919061589e565b9350610def92505050565b6000610def82614781565b600082815261107860205260408120546001600160a01b03838116911614806139395750600083815261107860205260409020546001600160a01b03161580156139395750816001600160a01b031661392e84611828565b6001600160a01b0316145b1561394657506001610def565b506000610def565b60009182526110796020526040909120546001600160a01b0391821691161490565b610c89546000906001600160a01b031615613a1357610c895460405163221c1fd160e01b81526001600160a01b039091169063221c1fd1906139bc9033908890889088906004016155f7565b60206040518083038186803b1580156139d457600080fd5b505afa1580156139e8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0c91906153c6565b9050611563565b50610c85549392505050565b6000613a2a84611828565b90506001600160a01b038116613a755760405162461bcd60e51b815260206004820152601060248201526f4e4f4e5f4558495354454e545f4b455960801b6044820152606401610ed5565b6001600160a01b03811660009081526110756020526040812060018101549091613a9e84611844565b90508415613aca578015613ac057613ab68683615861565b6001840155613ada565b613ab68642615861565b613ad486836158dd565b60018401555b60408051878152861515602082015288917fe9408df99703ae33a9d01185bcad328ea8683fb1f920da9c30959c192f21b5b3910160405180910390a250505050505050565b6001600160a01b0382166000908152611075602090815260409182902082518084019093528054835260010154908201819052613b6d576110778054906000613b678361596c565b91905055505b5060009081526110766020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b600081815261107960205260409020546001600160a01b031615613bd95760008181526110796020526040902080546001600160a01b03191690555b50565b600082815261107860205260409020546001600160a01b038281169116146116255760008281526110786020526040902080546001600160a01b0319166001600160a01b038316179055613c2f82613b9d565b6040516001600160a01b0382169083907f9d2895c45a420624de863a2f437b022d879f457bf7a829044055a10c5a6fd5e390600090a35050565b613c73828261245e565b61162557613c8b816001600160a01b0316601461478c565b613c9683602061478c565b604051602001613ca7929190615537565b60408051601f198184030181529082905262461bcd60e51b8252610ed591600401615672565b613cd7828261245e565b6116255760008281526097602090815260408083206001600160a01b03851684529091529020805460ff19166001179055613d0f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b613d5d828261245e565b156116255760008281526097602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600081613dc681611844565b613de25760405162461bcd60e51b8152600401610ed5906156ae565b6001600160a01b038316600090815261107560205260409020610c84546000191415613e1457610c8554925050610efa565b6000428260010154613e2691906158dd565b9050610c84546127f15482613e3b9190615861565b10613e4b57610c85549350613e6b565b610c845481610c8554613e5e91906158be565b613e68919061589e565b93505b6127f1541580613e8a5750610c84546127f154613e889083615861565b105b15613ed25760006127106127f054610c8554613ea691906158be565b613eb0919061589e565b905080851115613ecb57613ec481866158dd565b9450613ed0565b600094505b505b505050919050565b6104b180546001600160a01b0319166001600160a01b0383169081179091551580613f7557506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f3b57600080fd5b505afa158015613f4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f7391906153c6565b115b613bd95760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606401610ed5565b63bbf81e008311156140055760405162461bcd60e51b815260206004820152601860248201527f4d41585f45585049524154494f4e5f3130305f594541525300000000000000006044820152606401610ed5565b610c838054336001600160a01b031991821617909155610c8880549091166001600160a01b038616179055821561403c5782614040565b6000195b610c8455610c8591909155610c86555050565b61405b61496d565b6140686114638383614dc9565b50611625635b5e139f60e01b614113565b61408963780e9d6360e01b614113565b565b6140a3600080516020615a2d833981519152806149a4565b6140c96000805160206159ed833981519152600080516020615a2d8339815191526149a4565b6140d281612905565b6140ee576140ee600080516020615a2d833981519152826149ef565b6140f781611705565b613bd957613bd96000805160206159ed833981519152826149ef565b6001600160e01b0319808216141561416d5760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e74657266616365206964000000006044820152606401610ed5565b6001600160e01b0319166000908152606560205260409020805460ff19166001179055565b8054613bd957610c8780549060006141a98361596c565b9091555050610c87549055565b6001600160a01b0382166000818152611075602052604090819020805491519092339290917f0a7068a9989857441c039a14a42b67ed71dd1fcfe5a9b17cc87b252e47bce5289061420a9087815260200190565b60405180910390a44260018201558115614236576104b154614236906001600160a01b03168484614745565b610c8a546001600160a01b0316156114dd57610c8a5460405163b499b6c560e01b81523360048201526001600160a01b038581166024830152604482018590529091169063b499b6c590606401600060405180830381600087803b15801561429d57600080fd5b505af1158015611d68573d6000803e3d6000fd5b60006001600160a01b0384163b6142ca57506001614368565b604051630a85bd0160e11b81526000906001600160a01b0386169063150b7a02906142ff9033908a908990899060040161562b565b602060405180830381600087803b15801561431957600080fd5b505af115801561432d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143519190615302565b6001600160e01b031916630a85bd0160e11b149150505b949350505050565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b816000815181106143e957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061442657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060005b60148110156145c2578260048561445884600c615861565b6020811061447657634e487b7160e01b600052603260045260246000fd5b1a60f81b6001600160f81b031916901c60f81c60ff16815181106144aa57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826144c58360026158be565b6144d0906002615861565b815181106144ee57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350828461451283600c615861565b6020811061453057634e487b7160e01b600052603260045260246000fd5b825191901a600f1690811061455557634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916826145708360026158be565b61457b906003615861565b8151811061459957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350806145ba8161596c565b915050614440565b50949350505050565b606081806145f25750506040805180820190915260018152600360fc1b6020820152919050565b8260005b811561461c57806146068161596c565b91506146159050600a8361589e565b91506145f6565b6000816001600160401b0381111561464457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561466e576020820181803683370190505b509050815b8415614709576146846001826158dd565b90506000614693600a8761589e565b61469e90600a6158be565b6146a890876158dd565b6146b3906030615879565b905060008160f81b9050808484815181106146de57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614700600a8861589e565b96505050614673565b5095945050505050565b60608484848460405160200161472c94939291906154e0565b6040516020818303038152906040529050949350505050565b80156114dd576001600160a01b03831661476c576114dd6001600160a01b038316826149f9565b82612b0a6001600160a01b0382168484614b12565b6000610def82614b64565b6060600061479b8360026158be565b6147a6906002615861565b6001600160401b038111156147cb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156147f5576020820181803683370190505b509050600360fc1b8160008151811061481e57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061485b57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600061487f8460026158be565b61488a906001615861565b90505b600181111561491e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106148cc57634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106148f057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361491781615920565b905061488d565b5083156115635760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610ed5565b600054610100900460ff166149945760405162461bcd60e51b8152600401610ed5906157bf565b61499c614b89565b614089614b89565b600082815260976020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6116258282613ccd565b80471015614a495760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610ed5565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614a96576040519150601f19603f3d011682016040523d82523d6000602084013e614a9b565b606091505b50509050806114dd5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610ed5565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114dd908490614bb0565b60006001600160e01b03198216637965db0b60e01b1480610def5750610def82614c82565b600054610100900460ff166140895760405162461bcd60e51b8152600401610ed5906157bf565b6000614c05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614cbe9092919063ffffffff16565b8051909150156114dd5780806020019051810190614c23919061528e565b6114dd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610ed5565b60006301ffc9a760e01b6001600160e01b031983161480610def5750506001600160e01b03191660009081526065602052604090205460ff1690565b6060614368848460008585843b614d175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ed5565b600080866001600160a01b03168587604051614d3391906154c4565b60006040518083038185875af1925050503d8060008114614d70576040519150601f19603f3d011682016040523d82523d6000602084013e614d75565b606091505b5091509150614d85828286614d90565b979650505050505050565b60608315614d9f575081611563565b825115614daf5782518084602001fd5b8160405162461bcd60e51b8152600401610ed59190615672565b828054614dd590615937565b90600052602060002090601f016020900481019282614df75760008555614e3d565b82601f10614e105782800160ff19823516178555614e3d565b82800160010185558215614e3d579182015b82811115614e3d578235825591602001919060010190614e22565b506117019291505b808211156117015760008155600101614e45565b60008083601f840112614e6a578182fd5b5081356001600160401b03811115614e80578182fd5b6020830191508360208260051b8501011115614e9b57600080fd5b9250929050565b60008083601f840112614eb3578182fd5b5081356001600160401b03811115614ec9578182fd5b602083019150836020828501011115614e9b57600080fd5b600060208284031215614ef2578081fd5b8135611563816159b3565b60008060408385031215614f0f578081fd5b8235614f1a816159b3565b946020939093013593505050565b600080600080600080600060c0888a031215614f42578283fd5b8735614f4d816159b3565b9650602088013595506040880135614f64816159b3565b9450606088013593506080880135925060a08801356001600160401b03811115614f8c578283fd5b614f988a828b01614ea2565b989b979a50959850939692959293505050565b60008060408385031215614fbd578182fd5b8235614fc8816159b3565b91506020830135614fd8816159b3565b809150509250929050565b60008060008060808587031215614ff8578384fd5b8435615003816159b3565b93506020850135615013816159b3565b92506040850135615023816159b3565b91506060850135615033816159b3565b939692955090935050565b60008060008060608587031215615053578384fd5b843561505e816159b3565b9350602085013561506e816159b3565b925060408501356001600160401b03811115615088578283fd5b61509487828801614ea2565b95989497509550505050565b6000806000606084860312156150b4578081fd5b83356150bf816159b3565b925060208401356150cf816159b3565b929592945050506040919091013590565b600080600080608085870312156150f5578182fd5b8435615100816159b3565b93506020850135615110816159b3565b92506040850135915060608501356001600160401b03811115615131578182fd5b8501601f81018713615141578182fd5b803561515461514f8261583a565b61580a565b818152886020838501011115615168578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615198578182fd5b82356151a3816159b3565b91506020830135614fd8816159c8565b60008060408385031215614f0f578182fd5b6000806000606084860312156151d9578081fd5b83356151e4816159b3565b95602085013595506040909401359392505050565b60008060008060008060608789031215615211578384fd5b86356001600160401b0380821115615227578586fd5b6152338a838b01614e59565b9098509650602089013591508082111561524b578586fd5b6152578a838b01614e59565b9096509450604089013591508082111561526f578384fd5b5061527c89828a01614e59565b979a9699509497509295939492505050565b60006020828403121561529f578081fd5b8151611563816159c8565b6000602082840312156152bb578081fd5b5035919050565b600080604083850312156152d4578182fd5b823591506020830135614fd8816159b3565b6000602082840312156152f7578081fd5b8135611563816159d6565b600060208284031215615313578081fd5b8151611563816159d6565b60008060208385031215615330578182fd5b82356001600160401b03811115615345578283fd5b61535185828601614ea2565b90969095509350505050565b60006020828403121561536e578081fd5b81516001600160401b03811115615383578182fd5b8201601f81018413615393578182fd5b80516153a161514f8261583a565b8181528560208385010111156153b5578384fd5b6110788260208301602086016158f4565b6000602082840312156153d7578081fd5b5051919050565b60008060008060008060a087890312156153f6578384fd5b863595506020870135615408816159b3565b94506040870135615418816159b3565b93506060870135615428816159b3565b925060808701356001600160401b03811115615442578283fd5b61527c89828a01614ea2565b60008060408385031215615460578182fd5b50508035926020909101359150565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526154b08160208601602086016158f4565b601f01601f19169290920160200192915050565b600082516154d68184602087016158f4565b9190910192915050565b600085516154f2818460208a016158f4565b855190830190615506818360208a016158f4565b85519101906155198183602089016158f4565b845191019061552c8183602088016158f4565b019695505050505050565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161556f8160178501602088016158f4565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516155a08160288401602088016158f4565b01602801949350505050565b6001600160a01b03888116825287811660208301528616604082015260c0606082018190526000906155e1908301868861546f565b60808301949094525060a0015295945050505050565b6001600160a01b038581168252848116602083015283166040820152608060608201819052600090612eee90830184615498565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612eee90830184615498565b60208152600061436860208301848661546f565b6020815260006115636020830184615498565b6020808252600f908201526e494e56414c49445f4144445245535360881b604082015260600190565b6020808252600d908201526c12d15657d393d517d590531251609a1b604082015260600190565b6020808252601c908201527f4f4e4c595f4b45595f4d414e414745525f4f525f415050524f56454400000000604082015260600190565b6020808252818101527f4f4e4c595f4c4f434b5f4d414e414745525f4f525f42454e4546494349415259604082015260600190565b60208082526035908201527f4d6978696e526f6c65733a2063616c6c657220646f6573206e6f74206861766560408201527420746865204c6f636b4d616e6167657220726f6c6560581b606082015260800190565b6020808252600f908201526e1313d0d2d7d11154149150d0551151608a1b604082015260600190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156158325761583261599d565b604052919050565b60006001600160401b038211156158535761585361599d565b50601f01601f191660200190565b6000821982111561587457615874615987565b500190565b600060ff821660ff84168060ff0382111561589657615896615987565b019392505050565b6000826158b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156158d8576158d8615987565b500290565b6000828210156158ef576158ef615987565b500390565b60005b8381101561590f5781810151838201526020016158f7565b83811115612b0a5750506000910152565b60008161592f5761592f615987565b506000190190565b600181811c9082168061594b57607f821691505b60208210811415610efa57634e487b7160e01b600052602260045260246000fd5b600060001982141561598057615980615987565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114613bd957600080fd5b8015158114613bd957600080fd5b6001600160e01b031981168114613bd957600080fdfeb309c40027c81d382c3b58d8de24207a34b27e1db369b1434e4a11311f154b5eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efb89cdd26cddd51301940bf2715f765b626b8a5a9e2681ac62dc83cc2db2530c0a2646970667358221220a966aec0ea72cc36f07dd0afa1e277f5eb266146078b7651e59c22655e0639ae64736f6c63430008040033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol b/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol new file mode 100644 index 00000000000..53127b197dd --- /dev/null +++ b/packages/contracts/src/contracts/PublicLock/IPublicLockV9.sol @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.17 <0.9.0; + +/** + * @title The PublicLock Interface + */ + +interface IPublicLockV9 { + // See indentationissue description here: + // https://github.com/duaraghav8/Ethlint/issues/268 + // solium-disable indentation + + /// Functions + function initialize( + address _lockCreator, + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName + ) external; + + // roles + function DEFAULT_ADMIN_ROLE() external pure returns (bytes32 role); + + function KEY_GRANTER_ROLE() external pure returns (bytes32 role); + + function LOCK_MANAGER_ROLE() external pure returns (bytes32 role); + + /** + * @notice The version number of the current implementation on this network. + * @return The current version number. + */ + function publicLockVersion() external pure returns (uint16); + + /** + * @notice Used to disable lock before migrating keys and/or destroying contract. + * @dev Throws if called by other than a lock manager. + * @dev Throws if lock contract has already been disabled. + */ + function disableLock() external; + + /** + * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. + * @dev Throws if called by other than a lock manager or beneficiary + * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually + * the same as `tokenAddress` in MixinFunds. + * @param _amount specifies the max amount to withdraw, which may be reduced when + * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. + * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` + * use cases. + */ + function withdraw(address _tokenAddress, uint _amount) external; + + /** + * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. + * @param _spender address that can spend tokens belonging to the lock + * @param _amount amount of tokens that can be spent by the spender + */ + function approveBeneficiary( + address _spender, + uint _amount + ) external returns (bool); + + /** + * A function which lets a Lock manager of the lock to change the price for future purchases. + * @dev Throws if called by other than a Lock manager + * @dev Throws if lock has been disabled + * @dev Throws if _tokenAddress is not a valid token + * @param _keyPrice The new price to set for keys + * @param _tokenAddress The address of the erc20 token to use for pricing the keys, + * or 0 to use ETH + */ + function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; + + /** + * A function to change the default duration of each key in the lock + * @notice keys previously bought are unaffected by this change (i.e. + * existing keys timestamps are not recalculated/updated) + * @param _newExpirationDuration the new amount of time for each key purchased + * or zero (0) for a non-expiring key + */ + function setExpirationDuration(uint _newExpirationDuration) external; + + /** + * A function which lets a Lock manager update the beneficiary account, + * which receives funds on withdrawal. + * @dev Throws if called by other than a Lock manager or beneficiary + * @dev Throws if _beneficiary is address(0) + * @param _beneficiary The new address to set as the beneficiary + */ + function updateBeneficiary(address _beneficiary) external; + + /** + * Checks if the user has a non-expired key. + * @param _user The address of the key owner + */ + function getHasValidKey(address _user) external view returns (bool); + + /** + * @notice Find the tokenId for a given user + * @return The tokenId of the NFT, else returns 0 + * @param _account The address of the key owner + */ + function getTokenIdFor(address _account) external view returns (uint); + + /** + * @dev Returns the key's ExpirationTimestamp field for a given owner. + * @param _keyOwner address of the user for whom we search the key + * @dev Returns 0 if the owner has never owned a key for this lock + */ + function keyExpirationTimestampFor( + address _keyOwner + ) external view returns (uint timestamp); + + /** + * Public function which returns the total number of unique owners (both expired + * and valid). This may be larger than totalSupply. + */ + function numberOfOwners() external view returns (uint); + + /** + * Allows a Lock manager to assign a descriptive name for this Lock. + * @param _lockName The new name for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockName(string calldata _lockName) external; + + /** + * Allows a Lock manager to assign a Symbol for this Lock. + * @param _lockSymbol The new Symbol for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockSymbol(string calldata _lockSymbol) external; + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string memory); + + /** + * Allows a Lock manager to update the baseTokenURI for this Lock. + * @dev Throws if called by other than a Lock manager + * @param _baseTokenURI String representing the base of the URI for this lock. + */ + function setBaseTokenURI(string calldata _baseTokenURI) external; + + /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. + * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + * 3986. The URI may point to a JSON file that conforms to the "ERC721 + * Metadata JSON Schema". + * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md + * @param _tokenId The tokenID we're inquiring about + * @return String representing the URI for the requested token + */ + function tokenURI(uint256 _tokenId) external view returns (string memory); + + /** + * Allows a Lock manager to add or remove an event hook + * @param _onKeyPurchaseHook Hook called when the `purchase` function is called + * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called + * @param _onValidKeyHook Hook called to determine if the contract should overide the status for a given address + * @param _onTokenURIHook Hook called to generate a data URI used for NFT metadata + */ + function setEventHooks( + address _onKeyPurchaseHook, + address _onKeyCancelHook, + address _onValidKeyHook, + address _onTokenURIHook + ) external; + + /** + * Allows a Lock manager to give a collection of users a key with no charge. + * Each key may be assigned a different expiration date. + * @dev Throws if called by other than a Lock manager + * @param _recipients An array of receiving addresses + * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted + */ + function grantKeys( + address[] calldata _recipients, + uint[] calldata _expirationTimestamps, + address[] calldata _keyManagers + ) external; + + /** + * @dev Purchase function + * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount + * (_value is ignored when using ETH) + * @param _recipient address of the recipient of the purchased key + * @param _referrer address of the user making the referral + * @param _keyManager optional address to grant managing rights to a specific address on creation + * @param _data arbitrary data populated by the front-end which initiated the sale + * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). + * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the + * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more + * than keyPrice is approved for spending). + */ + function purchase( + uint256 _value, + address _recipient, + address _referrer, + address _keyManager, + bytes calldata _data + ) external payable; + + /** + * @param _gasRefundValue price in wei or token in smallest price unit + * @dev Set the value to be refunded to the sender on purchase + */ + function setGasRefundValue(uint256 _gasRefundValue) external; + + /** + * _gasRefundValue price in wei or token in smallest price unit + * @dev Returns the value/rpice to be refunded to the sender on purchase + */ + function gasRefundValue() external view returns (uint256 _gasRefundValue); + + /** + * @notice returns the minimum price paid for a purchase with these params. + * @dev this considers any discount from Unlock or the OnKeyPurchase hook. + */ + function purchasePriceFor( + address _recipient, + address _referrer, + bytes calldata _data + ) external view returns (uint); + + /** + * Allow a Lock manager to change the transfer fee. + * @dev Throws if called by other than a Lock manager + * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). + * Ex: 200 bps = 2% + */ + function updateTransferFee(uint _transferFeeBasisPoints) external; + + /** + * Determines how much of a fee a key owner would need to pay in order to + * transfer the key to another account. This is pro-rated so the fee goes down + * overtime. + * @dev Throws if _keyOwner does not have a valid key + * @param _keyOwner The owner of the key check the transfer fee for. + * @param _time The amount of time to calculate the fee for. + * @return The transfer fee in seconds. + */ + function getTransferFee( + address _keyOwner, + uint _time + ) external view returns (uint); + + /** + * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key + * @param _keyOwner The key owner to whom we wish to send a refund to + * @param amount The amount to refund the key-owner + * @dev Throws if called by other than a Lock manager + * @dev Throws if _keyOwner does not have a valid key + */ + function expireAndRefundFor(address _keyOwner, uint amount) external; + + /** + * @dev allows the key manager to expire a given tokenId + * and send a refund to the keyOwner based on the amount of time remaining. + * @param _tokenId The id of the key to cancel. + */ + function cancelAndRefund(uint _tokenId) external; + + /** + * Allow a Lock manager to change the refund penalty. + * @dev Throws if called by other than a Lock manager + * @param _freeTrialLength The new duration of free trials for this lock + * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) + */ + function updateRefundPenalty( + uint _freeTrialLength, + uint _refundPenaltyBasisPoints + ) external; + + /** + * @dev Determines how much of a refund a key owner would receive if they issued + * @param _keyOwner The key owner to get the refund value for. + * a cancelAndRefund block.timestamp. + * Note that due to the time required to mine a tx, the actual refund amount will be lower + * than what the user reads from this call. + */ + function getCancelAndRefundValueFor( + address _keyOwner + ) external view returns (uint refund); + + function addKeyGranter(address account) external; + + function addLockManager(address account) external; + + function isKeyGranter(address account) external view returns (bool); + + function isLockManager(address account) external view returns (bool); + + function onKeyPurchaseHook() external view returns (address); + + function onKeyCancelHook() external view returns (address); + + function onValidKeyHook() external view returns (bool); + + function onTokenURIHook() external view returns (string memory); + + function revokeKeyGranter(address _granter) external; + + function renounceLockManager() external; + + /** + * @dev Change the maximum number of keys the lock can edit + * @param _maxNumberOfKeys uint the maximum number of keys + */ + function setMaxNumberOfKeys(uint _maxNumberOfKeys) external; + + ///=================================================================== + /// Auto-generated getter functions from public state variables + + function beneficiary() external view returns (address); + + function expirationDuration() external view returns (uint256); + + function freeTrialLength() external view returns (uint256); + + function isAlive() external view returns (bool); + + function keyPrice() external view returns (uint256); + + function maxNumberOfKeys() external view returns (uint256); + + function refundPenaltyBasisPoints() external view returns (uint256); + + function tokenAddress() external view returns (address); + + function transferFeeBasisPoints() external view returns (uint256); + + function unlockProtocol() external view returns (address); + + function keyManagerOf(uint) external view returns (address); + + ///=================================================================== + + /** + * @notice Allows the key owner to safely share their key (parent key) by + * transferring a portion of the remaining time to a new key (child key). + * @dev Throws if key is not valid. + * @dev Throws if `_to` is the zero address + * @param _to The recipient of the shared key + * @param _tokenId the key to share + * @param _timeShared The amount of time shared + * checks if `_to` is a smart contract (code size > 0). If so, it calls + * `onERC721Received` on `_to` and throws if the return value is not + * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. + * @dev Emit Transfer event + */ + function shareKey(address _to, uint _tokenId, uint _timeShared) external; + + /** + * @notice Update transfer and cancel rights for a given key + * @param _tokenId The id of the key to assign rights for + * @param _keyManager The address to assign the rights to for the given key + */ + function setKeyManagerOf(uint _tokenId, address _keyManager) external; + + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string memory _name); + + ///=================================================================== + + /// From ERC165.sol + function supportsInterface(bytes4 interfaceId) external view returns (bool); + + ///=================================================================== + + /// From ERC-721 + /** + * @dev Returns the number of NFTs in `owner`'s account. + */ + function balanceOf(address _owner) external view returns (uint256 balance); + + /** + * @dev Returns the owner of the NFT specified by `tokenId`. + */ + function ownerOf(uint256 tokenId) external view returns (address _owner); + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * Requirements: + * - `from`, `to` cannot be zero. + * - `tokenId` must be owned by `from`. + * - If the caller is not `from`, it must be have been allowed to move this + * NFT by either `approve` or `setApprovalForAll`. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * Requirements: + * - If the caller is not `from`, it must be approved to move this NFT by + * either `approve` or `setApprovalForAll`. + */ + function transferFrom(address from, address to, uint256 tokenId) external; + + function approve(address to, uint256 tokenId) external; + + /** + * @notice Get the approved address for a single NFT + * @dev Throws if `_tokenId` is not a valid NFT. + * @param _tokenId The NFT to find the approved address for + * @return operator The approved address for this NFT, or the zero address if there is none + */ + function getApproved( + uint256 _tokenId + ) external view returns (address operator); + + function setApprovalForAll(address operator, bool _approved) external; + + function isApprovedForAll( + address _owner, + address operator + ) external view returns (bool); + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; + + function totalSupply() external view returns (uint256); + + function tokenOfOwnerByIndex( + address _owner, + uint256 index + ) external view returns (uint256 tokenId); + + function tokenByIndex(uint256 index) external view returns (uint256); + + /** + * Innherited from Open Zeppelin AccessControl.sol + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + function grantRole(bytes32 role, address account) external; + + function revokeRole(bytes32 role, address account) external; + + function renounceRole(bytes32 role, address account) external; + + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @notice An ERC-20 style transfer. + * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). + * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user + * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. + */ + function transfer(address _to, uint _value) external returns (bool success); +} diff --git a/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol b/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol new file mode 100644 index 00000000000..638322f5f0d --- /dev/null +++ b/packages/contracts/src/contracts/PublicLock/PublicLockV9.sol @@ -0,0 +1,3702 @@ +// Sources flattened with hardhat v2.8.0 https://hardhat.org +// SPDX-License-Identifier: MIT + +// File contracts/interfaces/IPublicLock.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @title The PublicLock Interface + */ + +interface IPublicLock { + // See indentationissue description here: + // https://github.com/duaraghav8/Ethlint/issues/268 + // solium-disable indentation + + /// Functions + function initialize( + address _lockCreator, + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName + ) external; + + // roles + function DEFAULT_ADMIN_ROLE() external pure returns (bytes32 role); + + function KEY_GRANTER_ROLE() external pure returns (bytes32 role); + + function LOCK_MANAGER_ROLE() external pure returns (bytes32 role); + + /** + * @notice The version number of the current implementation on this network. + * @return The current version number. + */ + function publicLockVersion() external pure returns (uint16); + + /** + * @notice Used to disable lock before migrating keys and/or destroying contract. + * @dev Throws if called by other than a lock manager. + * @dev Throws if lock contract has already been disabled. + */ + function disableLock() external; + + /** + * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. + * @dev Throws if called by other than a lock manager or beneficiary + * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually + * the same as `tokenAddress` in MixinFunds. + * @param _amount specifies the max amount to withdraw, which may be reduced when + * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. + * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` + * use cases. + */ + function withdraw(address _tokenAddress, uint _amount) external; + + /** + * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. + * @param _spender address that can spend tokens belonging to the lock + * @param _amount amount of tokens that can be spent by the spender + */ + function approveBeneficiary( + address _spender, + uint _amount + ) external returns (bool); + + /** + * A function which lets a Lock manager of the lock to change the price for future purchases. + * @dev Throws if called by other than a Lock manager + * @dev Throws if lock has been disabled + * @dev Throws if _tokenAddress is not a valid token + * @param _keyPrice The new price to set for keys + * @param _tokenAddress The address of the erc20 token to use for pricing the keys, + * or 0 to use ETH + */ + function updateKeyPricing(uint _keyPrice, address _tokenAddress) external; + + /** + * A function to change the default duration of each key in the lock + * @notice keys previously bought are unaffected by this change (i.e. + * existing keys timestamps are not recalculated/updated) + * @param _newExpirationDuration the new amount of time for each key purchased + * or zero (0) for a non-expiring key + */ + function setExpirationDuration(uint _newExpirationDuration) external; + + /** + * A function which lets a Lock manager update the beneficiary account, + * which receives funds on withdrawal. + * @dev Throws if called by other than a Lock manager or beneficiary + * @dev Throws if _beneficiary is address(0) + * @param _beneficiary The new address to set as the beneficiary + */ + function updateBeneficiary(address _beneficiary) external; + + /** + * Checks if the user has a non-expired key. + * @param _user The address of the key owner + */ + function getHasValidKey(address _user) external view returns (bool); + + /** + * @notice Find the tokenId for a given user + * @return The tokenId of the NFT, else returns 0 + * @param _account The address of the key owner + */ + function getTokenIdFor(address _account) external view returns (uint); + + /** + * @dev Returns the key's ExpirationTimestamp field for a given owner. + * @param _keyOwner address of the user for whom we search the key + * @dev Returns 0 if the owner has never owned a key for this lock + */ + function keyExpirationTimestampFor( + address _keyOwner + ) external view returns (uint timestamp); + + /** + * Public function which returns the total number of unique owners (both expired + * and valid). This may be larger than totalSupply. + */ + function numberOfOwners() external view returns (uint); + + /** + * Allows a Lock manager to assign a descriptive name for this Lock. + * @param _lockName The new name for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockName(string calldata _lockName) external; + + /** + * Allows a Lock manager to assign a Symbol for this Lock. + * @param _lockSymbol The new Symbol for the lock + * @dev Throws if called by other than a Lock manager + */ + function updateLockSymbol(string calldata _lockSymbol) external; + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string memory); + + /** + * Allows a Lock manager to update the baseTokenURI for this Lock. + * @dev Throws if called by other than a Lock manager + * @param _baseTokenURI String representing the base of the URI for this lock. + */ + function setBaseTokenURI(string calldata _baseTokenURI) external; + + /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. + * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + * 3986. The URI may point to a JSON file that conforms to the "ERC721 + * Metadata JSON Schema". + * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md + * @param _tokenId The tokenID we're inquiring about + * @return String representing the URI for the requested token + */ + function tokenURI(uint256 _tokenId) external view returns (string memory); + + /** + * Allows a Lock manager to add or remove an event hook + * @param _onKeyPurchaseHook Hook called when the `purchase` function is called + * @param _onKeyCancelHook Hook called when the internal `_cancelAndRefund` function is called + */ + function setEventHooks( + address _onKeyPurchaseHook, + address _onKeyCancelHook, + address _onValidKeyHook, + address _onTokenURIHook + ) external; + + /** + * Allows a Lock manager to give a collection of users a key with no charge. + * Each key may be assigned a different expiration date. + * @dev Throws if called by other than a Lock manager + * @param _recipients An array of receiving addresses + * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted + */ + function grantKeys( + address[] calldata _recipients, + uint[] calldata _expirationTimestamps, + address[] calldata _keyManagers + ) external; + + /** + * @dev Purchase function + * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount + * (_value is ignored when using ETH) + * @param _recipient address of the recipient of the purchased key + * @param _referrer address of the user making the referral + * @param _keyManager optional address to grant managing rights to a specific address on creation + * @param _data arbitrary data populated by the front-end which initiated the sale + * @dev Throws if lock is disabled. Throws if lock is sold-out. Throws if _recipient == address(0). + * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if a Lock manager increases the + * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more + * than keyPrice is approved for spending). + */ + function purchase( + uint256 _value, + address _recipient, + address _referrer, + address _keyManager, + bytes calldata _data + ) external payable; + + /** + * @param _gasRefundValue price in wei or token in smallest price unit + * @dev Set the value to be refunded to the sender on purchase + */ + function setGasRefundValue(uint256 _gasRefundValue) external; + + /** + * _gasRefundValue price in wei or token in smallest price unit + * @dev Returns the value/rpice to be refunded to the sender on purchase + */ + function gasRefundValue() external view returns (uint256 _gasRefundValue); + + /** + * @notice returns the minimum price paid for a purchase with these params. + * @dev this considers any discount from Unlock or the OnKeyPurchase hook. + */ + function purchasePriceFor( + address _recipient, + address _referrer, + bytes calldata _data + ) external view returns (uint); + + /** + * Allow a Lock manager to change the transfer fee. + * @dev Throws if called by other than a Lock manager + * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). + * Ex: 200 bps = 2% + */ + function updateTransferFee(uint _transferFeeBasisPoints) external; + + /** + * Determines how much of a fee a key owner would need to pay in order to + * transfer the key to another account. This is pro-rated so the fee goes down + * overtime. + * @dev Throws if _keyOwner does not have a valid key + * @param _keyOwner The owner of the key check the transfer fee for. + * @param _time The amount of time to calculate the fee for. + * @return The transfer fee in seconds. + */ + function getTransferFee( + address _keyOwner, + uint _time + ) external view returns (uint); + + /** + * @dev Invoked by a Lock manager to expire the user's key and perform a refund and cancellation of the key + * @param _keyOwner The key owner to whom we wish to send a refund to + * @param amount The amount to refund the key-owner + * @dev Throws if called by other than a Lock manager + * @dev Throws if _keyOwner does not have a valid key + */ + function expireAndRefundFor(address _keyOwner, uint amount) external; + + /** + * @dev allows the key manager to expire a given tokenId + * and send a refund to the keyOwner based on the amount of time remaining. + * @param _tokenId The id of the key to cancel. + */ + function cancelAndRefund(uint _tokenId) external; + + /** + * Allow a Lock manager to change the refund penalty. + * @dev Throws if called by other than a Lock manager + * @param _freeTrialLength The new duration of free trials for this lock + * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) + */ + function updateRefundPenalty( + uint _freeTrialLength, + uint _refundPenaltyBasisPoints + ) external; + + /** + * @dev Determines how much of a refund a key owner would receive if they issued + * @param _keyOwner The key owner to get the refund value for. + * a cancelAndRefund block.timestamp. + * Note that due to the time required to mine a tx, the actual refund amount will be lower + * than what the user reads from this call. + */ + function getCancelAndRefundValueFor( + address _keyOwner + ) external view returns (uint refund); + + function addKeyGranter(address account) external; + + function addLockManager(address account) external; + + function isKeyGranter(address account) external view returns (bool); + + function isLockManager(address account) external view returns (bool); + + function onKeyPurchaseHook() external view returns (address); + + function onKeyCancelHook() external view returns (address); + + function onValidKeyHook() external view returns (bool); + + function onTokenURIHook() external view returns (string memory); + + function revokeKeyGranter(address _granter) external; + + function renounceLockManager() external; + + /** + * @dev Change the maximum number of keys the lock can edit + * @param _maxNumberOfKeys uint the maximum number of keys + */ + function setMaxNumberOfKeys(uint _maxNumberOfKeys) external; + + ///=================================================================== + /// Auto-generated getter functions from public state variables + + function beneficiary() external view returns (address); + + function expirationDuration() external view returns (uint256); + + function freeTrialLength() external view returns (uint256); + + function isAlive() external view returns (bool); + + function keyPrice() external view returns (uint256); + + function maxNumberOfKeys() external view returns (uint256); + + function refundPenaltyBasisPoints() external view returns (uint256); + + function tokenAddress() external view returns (address); + + function transferFeeBasisPoints() external view returns (uint256); + + function unlockProtocol() external view returns (address); + + function keyManagerOf(uint) external view returns (address); + + ///=================================================================== + + /** + * @notice Allows the key owner to safely share their key (parent key) by + * transferring a portion of the remaining time to a new key (child key). + * @dev Throws if key is not valid. + * @dev Throws if `_to` is the zero address + * @param _to The recipient of the shared key + * @param _tokenId the key to share + * @param _timeShared The amount of time shared + * checks if `_to` is a smart contract (code size > 0). If so, it calls + * `onERC721Received` on `_to` and throws if the return value is not + * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. + * @dev Emit Transfer event + */ + function shareKey(address _to, uint _tokenId, uint _timeShared) external; + + /** + * @notice Update transfer and cancel rights for a given key + * @param _tokenId The id of the key to assign rights for + * @param _keyManager The address to assign the rights to for the given key + */ + function setKeyManagerOf(uint _tokenId, address _keyManager) external; + + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string memory _name); + + ///=================================================================== + + /// From ERC165.sol + function supportsInterface(bytes4 interfaceId) external view returns (bool); + + ///=================================================================== + + /// From ERC-721 + /** + * @dev Returns the number of NFTs in `owner`'s account. + */ + function balanceOf(address _owner) external view returns (uint256 balance); + + /** + * @dev Returns the owner of the NFT specified by `tokenId`. + */ + function ownerOf(uint256 tokenId) external view returns (address _owner); + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * Requirements: + * - `from`, `to` cannot be zero. + * - `tokenId` must be owned by `from`. + * - If the caller is not `from`, it must be have been allowed to move this + * NFT by either `approve` or `setApprovalForAll`. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to + * another (`to`). + * + * Requirements: + * - If the caller is not `from`, it must be approved to move this NFT by + * either `approve` or `setApprovalForAll`. + */ + function transferFrom(address from, address to, uint256 tokenId) external; + + function approve(address to, uint256 tokenId) external; + + /** + * @notice Get the approved address for a single NFT + * @dev Throws if `_tokenId` is not a valid NFT. + * @param _tokenId The NFT to find the approved address for + * @return operator The approved address for this NFT, or the zero address if there is none + */ + function getApproved( + uint256 _tokenId + ) external view returns (address operator); + + function setApprovalForAll(address operator, bool _approved) external; + + function isApprovedForAll( + address _owner, + address operator + ) external view returns (bool); + + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; + + function totalSupply() external view returns (uint256); + + function tokenOfOwnerByIndex( + address _owner, + uint256 index + ) external view returns (uint256 tokenId); + + function tokenByIndex(uint256 index) external view returns (uint256); + + /** + * Innherited from Open Zeppelin AccessControl.sol + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + function grantRole(bytes32 role, address account) external; + + function revokeRole(bytes32 role, address account) external; + + function renounceRole(bytes32 role, address account) external; + + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @notice An ERC-20 style transfer. + * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). + * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user + * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. + */ + function transfer(address _to, uint _value) external returns (bool success); +} + +// File @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (utils/Address.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Collection of functions related to the address type + */ +library AddressUpgradeable { + /** + * @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 + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize, which returns 0 for contracts in + // construction, since the code is only stored at the end of the + // constructor execution. + + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, "Address: insufficient balance"); + + (bool success, ) = recipient.call{value: amount}(""); + require( + success, + "Address: unable to send value, recipient may have reverted" + ); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall( + address target, + bytes memory data + ) internal returns (bytes memory) { + return functionCall(target, data, "Address: low-level call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return + functionCallWithValue( + target, + data, + value, + "Address: low-level call with value failed" + ); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require( + address(this).balance >= value, + "Address: insufficient balance for call" + ); + require(isContract(target), "Address: call to non-contract"); + + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResult(success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data + ) internal view returns (bytes memory) { + return + functionStaticCall(target, data, "Address: low-level static call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + require(isContract(target), "Address: static call to non-contract"); + + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResult(success, returndata, errorMessage); + } + + /** + * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the + * revert reason using the provided one. + * + * _Available since v4.3._ + */ + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } + } +} + +// File @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) + +pragma solidity ^0.8.0; + +/** + * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed + * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an + * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer + * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. + * + * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as + * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. + * + * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure + * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. + * + * [CAUTION] + * ==== + * Avoid leaving a contract uninitialized. + * + * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation + * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the + * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: + * + * [.hljs-theme-light.nopadding] + * ``` + * /// @custom:oz-upgrades-unsafe-allow constructor + * constructor() initializer {} + * ``` + * ==== + */ +abstract contract Initializable { + /** + * @dev Indicates that the contract has been initialized. + */ + bool private _initialized; + + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool private _initializing; + + /** + * @dev Modifier to protect an initializer function from being invoked twice. + */ + modifier initializer() { + // If the contract is initializing we ignore whether _initialized is set in order to support multiple + // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the + // contract may have been reentered. + require( + _initializing ? _isConstructor() : !_initialized, + "Initializable: contract is already initialized" + ); + + bool isTopLevelCall = !_initializing; + if (isTopLevelCall) { + _initializing = true; + _initialized = true; + } + + _; + + if (isTopLevelCall) { + _initializing = false; + } + } + + /** + * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the + * {initializer} modifier, directly or indirectly. + */ + modifier onlyInitializing() { + require(_initializing, "Initializable: contract is not initializing"); + _; + } + + function _isConstructor() private view returns (bool) { + return !AddressUpgradeable.isContract(address(this)); + } +} + +// File @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol@v4.4.2 +// 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 IERC165Upgradeable { + /** + * @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); +} + +// File @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) + +pragma solidity ^0.8.0; + +/** + * @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 ERC165Upgradeable is Initializable, IERC165Upgradeable { + function __ERC165_init() internal onlyInitializing { + __ERC165_init_unchained(); + } + + function __ERC165_init_unchained() internal onlyInitializing {} + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { + return interfaceId == type(IERC165Upgradeable).interfaceId; + } + + uint256[50] private __gap; +} + +// File @openzeppelin/contracts-upgradeable/utils/introspection/ERC165StorageUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Storage based implementation of the {IERC165} interface. + * + * Contracts may inherit from this and call {_registerInterface} to declare + * their support of an interface. + */ +abstract contract ERC165StorageUpgradeable is Initializable, ERC165Upgradeable { + function __ERC165Storage_init() internal onlyInitializing { + __ERC165_init_unchained(); + __ERC165Storage_init_unchained(); + } + + function __ERC165Storage_init_unchained() internal onlyInitializing {} + + /** + * @dev Mapping of interface ids to whether or not it's supported. + */ + mapping(bytes4 => bool) private _supportedInterfaces; + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { + return + super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId]; + } + + /** + * @dev Registers the contract as an implementer of the interface defined by + * `interfaceId`. Support of the actual ERC165 interface is automatic and + * registering its interface id is not required. + * + * See {IERC165-supportsInterface}. + * + * Requirements: + * + * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). + */ + function _registerInterface(bytes4 interfaceId) internal virtual { + require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); + _supportedInterfaces[interfaceId] = true; + } + + uint256[49] private __gap; +} + +// File @openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20Upgradeable { + /** + * @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 `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, 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 `sender` to `recipient` 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 sender, + address recipient, + uint256 amount + ) external returns (bool); + + /** + * @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); +} + +// File @openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @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 SafeERC20Upgradeable { + using AddressUpgradeable for address; + + function safeTransfer( + IERC20Upgradeable token, + address to, + uint256 value + ) internal { + _callOptionalReturn( + token, + abi.encodeWithSelector(token.transfer.selector, to, value) + ); + } + + function safeTransferFrom( + IERC20Upgradeable 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( + IERC20Upgradeable 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( + IERC20Upgradeable 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( + IERC20Upgradeable 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) + ); + } + } + + /** + * @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( + IERC20Upgradeable 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" + ); + } + } +} + +// File contracts/mixins/MixinFunds.sol +pragma solidity ^0.8.0; + +/** + * @title An implementation of the money related functions. + * @author HardlyDifficult (unlock-protocol.com) + */ +contract MixinFunds { + using AddressUpgradeable for address payable; + using SafeERC20Upgradeable for IERC20Upgradeable; + + /** + * The token-type that this Lock is priced in. If 0, then use ETH, else this is + * a ERC20 token address. + */ + address public tokenAddress; + + function _initializeMixinFunds(address _tokenAddress) internal { + tokenAddress = _tokenAddress; + require( + _tokenAddress == address(0) || + IERC20Upgradeable(_tokenAddress).totalSupply() > 0, + "INVALID_TOKEN" + ); + } + + /** + * Transfers funds from the contract to the account provided. + * + * Security: be wary of re-entrancy when calling this function. + */ + function _transfer( + address _tokenAddress, + address payable _to, + uint _amount + ) internal { + if (_amount > 0) { + if (_tokenAddress == address(0)) { + // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/ + _to.sendValue(_amount); + } else { + IERC20Upgradeable token = IERC20Upgradeable(_tokenAddress); + token.safeTransfer(_to, _amount); + } + } + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File @openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) + +pragma solidity ^0.8.0; + +/** + * @dev External interface of AccessControl declared to support ERC165 detection. + */ +interface IAccessControlUpgradeable { + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged( + bytes32 indexed role, + bytes32 indexed previousAdminRole, + bytes32 indexed newAdminRole + ); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {AccessControl-_setupRole}. + */ + event RoleGranted( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked( + bytes32 indexed role, + address indexed account, + address indexed sender + ); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) external; +} + +// File @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol@v4.4.2 +// 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 ContextUpgradeable is Initializable { + function __Context_init() internal onlyInitializing { + __Context_init_unchained(); + } + + function __Context_init_unchained() internal onlyInitializing {} + + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } + + uint256[50] private __gap; +} + +// File @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) + +pragma solidity ^0.8.0; + +/** + * @dev String operations. + */ +library StringsUpgradeable { + bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + // Inspired by OraclizeAPI's implementation - MIT licence + // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol + + if (value == 0) { + return "0"; + } + uint256 temp = value; + uint256 digits; + while (temp != 0) { + digits++; + temp /= 10; + } + bytes memory buffer = new bytes(digits); + while (value != 0) { + digits -= 1; + buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); + value /= 10; + } + return string(buffer); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + if (value == 0) { + return "0x00"; + } + uint256 temp = value; + uint256 length = 0; + while (temp != 0) { + length++; + temp >>= 8; + } + return toHexString(value, length); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString( + uint256 value, + uint256 length + ) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = _HEX_SYMBOLS[value & 0xf]; + value >>= 4; + } + require(value == 0, "Strings: hex length insufficient"); + return string(buffer); + } +} + +// File @openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +abstract contract AccessControlUpgradeable is + Initializable, + ContextUpgradeable, + IAccessControlUpgradeable, + ERC165Upgradeable +{ + function __AccessControl_init() internal onlyInitializing { + __Context_init_unchained(); + __ERC165_init_unchained(); + __AccessControl_init_unchained(); + } + + function __AccessControl_init_unchained() internal onlyInitializing {} + + struct RoleData { + mapping(address => bool) members; + bytes32 adminRole; + } + + mapping(bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with a standardized message including the required role. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + * + * _Available since v4.1._ + */ + modifier onlyRole(bytes32 role) { + _checkRole(role, _msgSender()); + _; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { + return + interfaceId == type(IAccessControlUpgradeable).interfaceId || + super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole( + bytes32 role, + address account + ) public view override returns (bool) { + return _roles[role].members[account]; + } + + /** + * @dev Revert with a standard message if `account` is missing `role`. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + */ + function _checkRole(bytes32 role, address account) internal view { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + StringsUpgradeable.toHexString(uint160(account), 20), + " is missing role ", + StringsUpgradeable.toHexString(uint256(role), 32) + ) + ) + ); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view override returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole( + bytes32 role, + address account + ) public virtual override onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole( + bytes32 role, + address account + ) public virtual override onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been revoked `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) public virtual override { + require( + account == _msgSender(), + "AccessControl: can only renounce roles for self" + ); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + * + * NOTE: This function is deprecated in favor of {_grantRole}. + */ + function _setupRole(bytes32 role, address account) internal virtual { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @dev Grants `role` to `account`. + * + * Internal function without access restriction. + */ + function _grantRole(bytes32 role, address account) internal virtual { + if (!hasRole(role, account)) { + _roles[role].members[account] = true; + emit RoleGranted(role, account, _msgSender()); + } + } + + /** + * @dev Revokes `role` from `account`. + * + * Internal function without access restriction. + */ + function _revokeRole(bytes32 role, address account) internal virtual { + if (hasRole(role, account)) { + _roles[role].members[account] = false; + emit RoleRevoked(role, account, _msgSender()); + } + } + + uint256[49] private __gap; +} + +// File contracts/mixins/MixinRoles.sol +pragma solidity ^0.8.0; + +// This contract mostly follows the pattern established by openzeppelin in +// openzeppelin/contracts-ethereum-package/contracts/access/roles + +contract MixinRoles is AccessControlUpgradeable { + // roles + bytes32 public constant LOCK_MANAGER_ROLE = keccak256("LOCK_MANAGER"); + bytes32 public constant KEY_GRANTER_ROLE = keccak256("KEY_GRANTER"); + + // events + event LockManagerAdded(address indexed account); + event LockManagerRemoved(address indexed account); + event KeyGranterAdded(address indexed account); + event KeyGranterRemoved(address indexed account); + + // initializer + function _initializeMixinRoles(address sender) internal { + // for admin mamangers to add other lock admins + _setRoleAdmin(LOCK_MANAGER_ROLE, LOCK_MANAGER_ROLE); + + // for lock managers to add/remove key granters + _setRoleAdmin(KEY_GRANTER_ROLE, LOCK_MANAGER_ROLE); + + if (!isLockManager(sender)) { + _setupRole(LOCK_MANAGER_ROLE, sender); + } + if (!isKeyGranter(sender)) { + _setupRole(KEY_GRANTER_ROLE, sender); + } + } + + // modifiers + modifier onlyLockManager() { + require( + hasRole(LOCK_MANAGER_ROLE, msg.sender), + "MixinRoles: caller does not have the LockManager role" + ); + _; + } + + modifier onlyKeyGranterOrManager() { + require( + isKeyGranter(msg.sender) || isLockManager(msg.sender), + "MixinRoles: caller does not have the KeyGranter or LockManager role" + ); + _; + } + + // lock manager functions + function isLockManager(address account) public view returns (bool) { + return hasRole(LOCK_MANAGER_ROLE, account); + } + + function addLockManager(address account) public onlyLockManager { + grantRole(LOCK_MANAGER_ROLE, account); + emit LockManagerAdded(account); + } + + function renounceLockManager() public { + renounceRole(LOCK_MANAGER_ROLE, msg.sender); + emit LockManagerRemoved(msg.sender); + } + + // key granter functions + function isKeyGranter(address account) public view returns (bool) { + return hasRole(KEY_GRANTER_ROLE, account); + } + + function addKeyGranter(address account) public onlyLockManager { + grantRole(KEY_GRANTER_ROLE, account); + emit KeyGranterAdded(account); + } + + function revokeKeyGranter(address _granter) public onlyLockManager { + revokeRole(KEY_GRANTER_ROLE, _granter); + emit KeyGranterRemoved(_granter); + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinDisable.sol +pragma solidity ^0.8.0; + +/** + * @title Mixin allowing the Lock owner to disable a Lock (preventing new purchases) + * and then destroy it. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinDisable is MixinRoles, MixinFunds { + // Used to disable payable functions when deprecating an old lock + bool public isAlive; + + event Disable(); + + function _initializeMixinDisable() internal { + isAlive = true; + } + + // Only allow usage when contract is Alive + modifier onlyIfAlive() { + require(isAlive, "LOCK_DEPRECATED"); + _; + } + + /** + * @dev Used to disable lock before migrating keys and/or destroying contract + */ + function disableLock() external onlyLockManager onlyIfAlive { + emit Disable(); + isAlive = false; + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/interfaces/IUnlock.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @title The Unlock Interface + **/ + +interface IUnlock { + // Use initialize instead of a constructor to support proxies(for upgradeability via zos). + function initialize(address _unlockOwner) external; + + /** + * @dev deploy a ProxyAdmin contract used to upgrade locks + */ + function initializeProxyAdmin() external; + + // store contract proxy admin address + function proxyAdminAddress() external view; + + /** + * @notice Create lock (legacy) + * This deploys a lock for a creator. It also keeps track of the deployed lock. + * @param _expirationDuration the duration of the lock (pass 0 for unlimited duration) + * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. + * @param _keyPrice the price of each key + * @param _maxNumberOfKeys the maximum nimbers of keys to be edited + * @param _lockName the name of the lock + * param _salt [deprec] -- kept only for backwards copatibility + * This may be implemented as a sequence ID or with RNG. It's used with `create2` + * to know the lock's address before the transaction is mined. + * @dev internally call `createUpgradeableLock` + */ + function createLock( + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName, + bytes12 // _salt + ) external returns (address); + + /** + * @notice Create lock (default) + * This deploys a lock for a creator. It also keeps track of the deployed lock. + * @param data bytes containing the call to initialize the lock template + * @dev this call is passed as encoded function - for instance: + * bytes memory data = abi.encodeWithSignature( + * 'initialize(address,uint256,address,uint256,uint256,string)', + * msg.sender, + * _expirationDuration, + * _tokenAddress, + * _keyPrice, + * _maxNumberOfKeys, + * _lockName + * ); + * @return address of the create lock + */ + function createUpgradeableLock(bytes memory data) external returns (address); + + /** + * @notice Upgrade a lock to a specific version + * @dev only available for publicLockVersion > 10 (proxyAdmin /required) + * @param lockAddress the existing lock address + * @param version the version number you are targeting + * Likely implemented with OpenZeppelin TransparentProxy contract + */ + function upgradeLock( + address payable lockAddress, + uint16 version + ) external returns (address); + + /** + * This function keeps track of the added GDP, as well as grants of discount tokens + * to the referrer, if applicable. + * The number of discount tokens granted is based on the value of the referal, + * the current growth rate and the lock's discount token distribution rate + * This function is invoked by a previously deployed lock only. + */ + function recordKeyPurchase( + uint _value, + address _referrer // solhint-disable-line no-unused-vars + ) external; + + /** + * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. + * @dev [DEPRECATED] Kept for backwards compatibility + * This function will keep track of consumed discounts by a given user. + * It will also grant discount tokens to the creator who is granting the discount based on the + * amount of discount and compensation rate. + * This function is invoked by a previously deployed lock only. + */ + function recordConsumedDiscount( + uint _discount, + uint _tokens // solhint-disable-line no-unused-vars + ) external; + + /** + * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. + * @dev [DEPRECATED] Kept for backwards compatibility + * This function returns the discount available for a user, when purchasing a + * a key from a lock. + * This does not modify the state. It returns both the discount and the number of tokens + * consumed to grant that discount. + */ + function computeAvailableDiscountFor( + address _purchaser, // solhint-disable-line no-unused-vars + uint _keyPrice // solhint-disable-line no-unused-vars + ) external view returns (uint discount, uint tokens); + + // Function to read the globalTokenURI field. + function globalBaseTokenURI() external view returns (string memory); + + /** + * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalBaseTokenURI() external view returns (string memory); + + // Function to read the globalTokenSymbol field. + function globalTokenSymbol() external view returns (string memory); + + // Function to read the chainId field. + function chainId() external view returns (uint); + + /** + * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. + */ + function getGlobalTokenSymbol() external view returns (string memory); + + /** + * @notice Allows the owner to update configuration variables + */ + function configUnlock( + address _udt, + address _weth, + uint _estimatedGasForPurchase, + string calldata _symbol, + string calldata _URI, + uint _chainId + ) external; + + /** + * @notice Add a PublicLock template to be used for future calls to `createLock`. + * @dev This is used to upgrade conytract per version number + */ + function addLockTemplate(address impl, uint16 version) external; + + // match lock templates addresses with version numbers + function publicLockImpls(uint16 _version) external view; + + // match version numbers with lock templates addresses + function publicLockVersions(address _impl) external view; + + // the latest existing lock template version + function publicLockLatestVersion() external view; + + /** + * @notice Upgrade the PublicLock template used for future calls to `createLock`. + * @dev This will initialize the template and revokeOwnership. + */ + function setLockTemplate(address payable _publicLockAddress) external; + + // Allows the owner to change the value tracking variables as needed. + function resetTrackedValue( + uint _grossNetworkProduct, + uint _totalDiscountGranted + ) external; + + function grossNetworkProduct() external view returns (uint); + + function totalDiscountGranted() external view returns (uint); + + function locks( + address + ) + external + view + returns (bool deployed, uint totalSales, uint yieldedDiscountTokens); + + // The address of the public lock template, used when `createLock` is called + function publicLockAddress() external view returns (address); + + // Map token address to exchange contract address if the token is supported + // Used for GDP calculations + function uniswapOracles(address) external view returns (address); + + // The WETH token address, used for value calculations + function weth() external view returns (address); + + // The UDT token address, used to mint tokens on referral + function udt() external view returns (address); + + // The approx amount of gas required to purchase a key + function estimatedGasForPurchase() external view returns (uint); + + // The version number of the current Unlock implementation on this network + function unlockVersion() external pure returns (uint16); + + /** + * @notice allows the owner to set the oracle address to use for value conversions + * setting the _oracleAddress to address(0) removes support for the token + * @dev This will also call update to ensure at least one datapoint has been recorded. + */ + function setOracle(address _tokenAddress, address _oracleAddress) external; + + // Initialize the Ownable contract, granting contract ownership to the specified sender + function __initializeOwnable(address sender) external; + + /** + * @dev Returns true if the caller is the current owner. + */ + function isOwner() external view returns (bool); + + /** + * @dev Returns the address of the current owner. + */ + function owner() external view returns (address); + + /** + * @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() external; + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) external; +} + +// File contracts/interfaces/hooks/ILockKeyCancelHook.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @notice Functions to be implemented by a keyCancelHook. + * @dev Lock hooks are configured by calling `setEventHooks` on the lock. + */ +interface ILockKeyCancelHook { + /** + * @notice If the lock owner has registered an implementer + * then this hook is called with every key cancel. + * @param operator the msg.sender issuing the cancel + * @param to the account which had the key canceled + * @param refund the amount sent to the `to` account (ETH or a ERC-20 token) + */ + function onKeyCancel(address operator, address to, uint256 refund) external; +} + +// File contracts/interfaces/hooks/ILockKeyPurchaseHook.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @notice Functions to be implemented by a keyPurchaseHook. + * @dev Lock hooks are configured by calling `setEventHooks` on the lock. + */ +interface ILockKeyPurchaseHook { + /** + * @notice Used to determine the purchase price before issueing a transaction. + * This allows the hook to offer a discount on purchases. + * This may revert to prevent a purchase. + * @param from the msg.sender making the purchase + * @param recipient the account which will be granted a key + * @param referrer the account which referred this key sale + * @param data arbitrary data populated by the front-end which initiated the sale + * @return minKeyPrice the minimum value/price required to purchase a key with these settings + * @dev the lock's address is the `msg.sender` when this function is called via + * the lock's `purchasePriceFor` function + */ + function keyPurchasePrice( + address from, + address recipient, + address referrer, + bytes calldata data + ) external view returns (uint minKeyPrice); + + /** + * @notice If the lock owner has registered an implementer then this hook + * is called with every key sold. + * @param from the msg.sender making the purchase + * @param recipient the account which will be granted a key + * @param referrer the account which referred this key sale + * @param data arbitrary data populated by the front-end which initiated the sale + * @param minKeyPrice the price including any discount granted from calling this + * hook's `keyPurchasePrice` function + * @param pricePaid the value/pricePaid included with the purchase transaction + * @dev the lock's address is the `msg.sender` when this function is called + */ + function onKeyPurchase( + address from, + address recipient, + address referrer, + bytes calldata data, + uint minKeyPrice, + uint pricePaid + ) external; +} + +// File contracts/interfaces/hooks/ILockValidKeyHook.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @notice Functions to be implemented by a hasValidKey Hook. + * @dev Lock hooks are configured by calling `setEventHooks` on the lock. + */ +interface ILockValidKeyHook { + /** + * @notice If the lock owner has registered an implementer then this hook + * is called every time balanceOf is called + * @param lockAddress the address of the current lock + * @param keyOwner the potential owner of the key for which we are retrieving the `balanceof` + * @param expirationTimestamp the key expiration timestamp + */ + function hasValidKey( + address lockAddress, + address keyOwner, + uint256 expirationTimestamp, + bool isValidKey + ) external view returns (bool); +} + +// File contracts/interfaces/hooks/ILockTokenURIHook.sol +pragma solidity >=0.5.17 <0.9.0; + +/** + * @notice Functions to be implemented by a tokenURIHook. + * @dev Lock hooks are configured by calling `setEventHooks` on the lock. + */ +interface ILockTokenURIHook { + /** + * @notice If the lock owner has registered an implementer + * then this hook is called every time `tokenURI()` is called + * @param lockAddress the address of the lock + * @param operator the msg.sender issuing the call + * @param owner the owner of the key for which we are retrieving the `tokenUri` + * @param keyId the id (tokenId) of the key (if applicable) + * @param expirationTimestamp the key expiration timestamp + * @return the tokenURI + */ + function tokenURI( + address lockAddress, + address operator, + address owner, + uint256 keyId, + uint expirationTimestamp + ) external view returns (string memory); +} + +// File contracts/mixins/MixinLockCore.sol +pragma solidity ^0.8.0; + +// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; + +/** + * @title Mixin for core lock data and functions. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinLockCore is MixinRoles, MixinFunds, MixinDisable { + using AddressUpgradeable for address; + + event Withdrawal( + address indexed sender, + address indexed tokenAddress, + address indexed beneficiary, + uint amount + ); + + event PricingChanged( + uint oldKeyPrice, + uint keyPrice, + address oldTokenAddress, + address tokenAddress + ); + + /** + * @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 + ); + + // Unlock Protocol address + // TODO: should we make that private/internal? + IUnlock public unlockProtocol; + + // Duration in seconds for which the keys are valid, after creation + // should we take a smaller type use less gas? + uint public expirationDuration; + + // price in wei of the next key + // TODO: allow support for a keyPriceCalculator which could set prices dynamically + uint public keyPrice; + + // Max number of keys sold if the keyReleaseMechanism is public + uint public maxNumberOfKeys; + + // A count of how many new key purchases there have been + uint internal _totalSupply; + + // The account which will receive funds on withdrawal + address payable public beneficiary; + + // The denominator component for values specified in basis points. + uint internal constant BASIS_POINTS_DEN = 10000; + + ILockKeyPurchaseHook public onKeyPurchaseHook; + ILockKeyCancelHook public onKeyCancelHook; + ILockValidKeyHook public onValidKeyHook; + ILockTokenURIHook public onTokenURIHook; + + // Ensure that the Lock has not sold all of its keys. + modifier notSoldOut() { + require(maxNumberOfKeys > _totalSupply, "LOCK_SOLD_OUT"); + _; + } + + modifier onlyLockManagerOrBeneficiary() { + require( + isLockManager(msg.sender) || msg.sender == beneficiary, + "ONLY_LOCK_MANAGER_OR_BENEFICIARY" + ); + _; + } + + function _initializeMixinLockCore( + address payable _beneficiary, + uint _expirationDuration, + uint _keyPrice, + uint _maxNumberOfKeys + ) internal { + require( + _expirationDuration <= 100 * 365 * 24 * 60 * 60, + "MAX_EXPIRATION_100_YEARS" + ); + unlockProtocol = IUnlock(msg.sender); // Make sure we link back to Unlock's smart contract. + beneficiary = _beneficiary; + expirationDuration = _expirationDuration == 0 + ? type(uint).max + : _expirationDuration; + keyPrice = _keyPrice; + maxNumberOfKeys = _maxNumberOfKeys; + } + + // The version number of the current implementation on this network + function publicLockVersion() public pure returns (uint16) { + return 9; + } + + /** + * @dev Called by owner to withdraw all funds from the lock and send them to the `beneficiary`. + * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually + * the same as `tokenAddress` in MixinFunds. + * @param _amount specifies the max amount to withdraw, which may be reduced when + * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. + * + * TODO: consider allowing anybody to trigger this as long as it goes to owner anyway? + * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` + * use cases. + */ + function withdraw( + address _tokenAddress, + uint _amount + ) external onlyLockManagerOrBeneficiary { + // get balance + uint balance; + if (_tokenAddress == address(0)) { + balance = address(this).balance; + } else { + balance = IERC20Upgradeable(_tokenAddress).balanceOf(address(this)); + } + + uint amount; + if (_amount == 0 || _amount > balance) { + require(balance > 0, "NOT_ENOUGH_FUNDS"); + amount = balance; + } else { + amount = _amount; + } + + emit Withdrawal(msg.sender, _tokenAddress, beneficiary, amount); + // Security: re-entrancy not a risk as this is the last line of an external function + _transfer(_tokenAddress, beneficiary, amount); + } + + /** + * A function which lets the owner of the lock change the pricing for future purchases. + * This consists of 2 parts: The token address and the price in the given token. + * In order to set the token to ETH, use 0 for the token Address. + */ + function updateKeyPricing( + uint _keyPrice, + address _tokenAddress + ) external onlyLockManager onlyIfAlive { + uint oldKeyPrice = keyPrice; + address oldTokenAddress = tokenAddress; + require( + _tokenAddress == address(0) || + IERC20Upgradeable(_tokenAddress).totalSupply() > 0, + "INVALID_TOKEN" + ); + keyPrice = _keyPrice; + tokenAddress = _tokenAddress; + emit PricingChanged(oldKeyPrice, keyPrice, oldTokenAddress, tokenAddress); + } + + /** + * A function which lets the owner of the lock update the beneficiary account, + * which receives funds on withdrawal. + */ + function updateBeneficiary( + address payable _beneficiary + ) external onlyLockManagerOrBeneficiary { + require(_beneficiary != address(0), "INVALID_ADDRESS"); + beneficiary = _beneficiary; + } + + /** + * @notice Allows a lock manager to add or remove an event hook + */ + function setEventHooks( + address _onKeyPurchaseHook, + address _onKeyCancelHook, + address _onValidKeyHook, + address _onTokenURIHook + ) external onlyLockManager { + require( + _onKeyPurchaseHook == address(0) || _onKeyPurchaseHook.isContract(), + "INVALID_ON_KEY_SOLD_HOOK" + ); + require( + _onKeyCancelHook == address(0) || _onKeyCancelHook.isContract(), + "INVALID_ON_KEY_CANCEL_HOOK" + ); + require( + _onValidKeyHook == address(0) || _onValidKeyHook.isContract(), + "INVALID_ON_VALID_KEY_HOOK" + ); + require( + _onTokenURIHook == address(0) || _onTokenURIHook.isContract(), + "INVALID_ON_TOKEN_URI_HOOK" + ); + onKeyPurchaseHook = ILockKeyPurchaseHook(_onKeyPurchaseHook); + onKeyCancelHook = ILockKeyCancelHook(_onKeyCancelHook); + onTokenURIHook = ILockTokenURIHook(_onTokenURIHook); + onValidKeyHook = ILockValidKeyHook(_onValidKeyHook); + } + + function totalSupply() public view returns (uint256) { + return _totalSupply; + } + + /** + * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. + * @param _spender address that can spend tokens belonging to the lock + * @param _amount amount of tokens that can be spent by the spender + */ + function approveBeneficiary( + address _spender, + uint _amount + ) public onlyLockManagerOrBeneficiary returns (bool) { + return IERC20Upgradeable(tokenAddress).approve(_spender, _amount); + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinKeys.sol +pragma solidity ^0.8.0; + +/** + * @title Mixin for managing `Key` data, as well as the * Approval related functions needed to meet the ERC721 + * standard. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinKeys is MixinLockCore { + // The struct for a key + struct Key { + uint tokenId; + uint expirationTimestamp; + } + + // Emitted when the Lock owner expires a user's Key + event ExpireKey(uint indexed tokenId); + + // Emitted when the expiration of a key is modified + event ExpirationChanged(uint indexed _tokenId, uint _amount, bool _timeAdded); + + event KeyManagerChanged(uint indexed _tokenId, address indexed _newManager); + + // Keys + // Each owner can have at most exactly one key + // TODO: could we use public here? (this could be confusing though because it getter will + // return 0 values when missing a key) + mapping(address => Key) internal keyByOwner; + + // Each tokenId can have at most exactly one owner at a time. + // Returns 0 if the token does not exist + // TODO: once we decouple tokenId from owner address (incl in js), then we can consider + // merging this with totalSupply into an array instead. + mapping(uint => address) internal _ownerOf; + + // Keep track of the total number of unique owners for this lock (both expired and valid). + // This may be larger than totalSupply + uint public numberOfOwners; + + // A given key has both an owner and a manager. + // If keyManager == address(0) then the key owner is also the manager + // Each key can have at most 1 keyManager. + mapping(uint => address) public keyManagerOf; + + // Keeping track of approved transfers + // This is a mapping of addresses which have approved + // the transfer of a key to another address where their key can be transferred + // Note: the approver may actually NOT have a key... and there can only + // be a single approved address + mapping(uint => address) private approved; + + // Keeping track of approved operators for a given Key manager. + // This approves a given operator for all keys managed by the calling "keyManager" + // The caller may not currently be the keyManager for ANY keys. + // These approvals are never reset/revoked automatically, unlike "approved", + // which is reset on transfer. + mapping(address => mapping(address => bool)) + private managerToOperatorApproved; + + // Ensure that the caller is the keyManager of the key + // or that the caller has been approved + // for ownership of that key + modifier onlyKeyManagerOrApproved(uint _tokenId) { + require( + _isKeyManager(_tokenId, msg.sender) || + _isApproved(_tokenId, msg.sender) || + isApprovedForAll(_ownerOf[_tokenId], msg.sender), + "ONLY_KEY_MANAGER_OR_APPROVED" + ); + _; + } + + // Ensures that an owner owns or has owned a key in the past + modifier ownsOrHasOwnedKey(address _keyOwner) { + require( + keyByOwner[_keyOwner].expirationTimestamp > 0, + "HAS_NEVER_OWNED_KEY" + ); + _; + } + + // Ensures that an owner has a valid key + modifier hasValidKey(address _user) { + require(getHasValidKey(_user), "KEY_NOT_VALID"); + _; + } + + // Ensures that a key has an owner + modifier isKey(uint _tokenId) { + require(_ownerOf[_tokenId] != address(0), "NO_SUCH_KEY"); + _; + } + + // Ensure that the caller owns the key + modifier onlyKeyOwner(uint _tokenId) { + require(ownerOf(_tokenId) == msg.sender, "ONLY_KEY_OWNER"); + _; + } + + /** + * In the specific case of a Lock, each owner can own only at most 1 key. + * @return The number of NFTs owned by `_keyOwner`, either 0 or 1. + */ + function balanceOf(address _keyOwner) public view returns (uint) { + require(_keyOwner != address(0), "INVALID_ADDRESS"); + return getHasValidKey(_keyOwner) ? 1 : 0; + } + + /** + * Checks if the user has a non-expired key. + */ + function getHasValidKey( + address _keyOwner + ) public view returns (bool isValid) { + isValid = keyByOwner[_keyOwner].expirationTimestamp > block.timestamp; + + // use hook if it exists + if (address(onValidKeyHook) != address(0)) { + isValid = onValidKeyHook.hasValidKey( + address(this), + _keyOwner, + keyByOwner[_keyOwner].expirationTimestamp, + isValid + ); + } + } + + /** + * @notice Find the tokenId for a given user + * @return The tokenId of the NFT, else returns 0 + */ + function getTokenIdFor(address _account) public view returns (uint) { + return keyByOwner[_account].tokenId; + } + + /** + * @dev Returns the key's ExpirationTimestamp field for a given owner. + * @param _keyOwner address of the user for whom we search the key + * @dev Returns 0 if the owner has never owned a key for this lock + */ + function keyExpirationTimestampFor( + address _keyOwner + ) public view returns (uint) { + return keyByOwner[_keyOwner].expirationTimestamp; + } + + // Returns the owner of a given tokenId + function ownerOf(uint _tokenId) public view returns (address) { + return _ownerOf[_tokenId]; + } + + /** + * @notice Public function for updating transfer and cancel rights for a given key + * @param _tokenId The id of the key to assign rights for + * @param _keyManager The address with the manager's rights for the given key. + * Setting _keyManager to address(0) means the keyOwner is also the keyManager + */ + function setKeyManagerOf( + uint _tokenId, + address _keyManager + ) public isKey(_tokenId) { + require( + _isKeyManager(_tokenId, msg.sender) || isLockManager(msg.sender), + "UNAUTHORIZED_KEY_MANAGER_UPDATE" + ); + _setKeyManagerOf(_tokenId, _keyManager); + } + + function _setKeyManagerOf(uint _tokenId, address _keyManager) internal { + if (keyManagerOf[_tokenId] != _keyManager) { + keyManagerOf[_tokenId] = _keyManager; + _clearApproval(_tokenId); + emit KeyManagerChanged(_tokenId, _keyManager); + } + } + + /** + * This approves _approved to get ownership of _tokenId. + * Note: that since this is used for both purchase and transfer approvals + * the approved token may not exist. + */ + function approve( + address _approved, + uint _tokenId + ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { + require(msg.sender != _approved, "APPROVE_SELF"); + + approved[_tokenId] = _approved; + emit Approval(_ownerOf[_tokenId], _approved, _tokenId); + } + + /** + * @notice Get the approved address for a single NFT + * @dev Throws if `_tokenId` is not a valid NFT. + * @param _tokenId The NFT to find the approved address for + * @return The approved address for this NFT, or the zero address if there is none + */ + function getApproved( + uint _tokenId + ) public view isKey(_tokenId) returns (address) { + address approvedRecipient = approved[_tokenId]; + return approvedRecipient; + } + + /** + * @dev Tells whether an operator is approved by a given keyManager + * @param _owner owner address which you want to query the approval of + * @param _operator operator address which you want to query the approval of + * @return bool whether the given operator is approved by the given owner + */ + function isApprovedForAll( + address _owner, + address _operator + ) public view returns (bool) { + uint tokenId = keyByOwner[_owner].tokenId; + address keyManager = keyManagerOf[tokenId]; + if (keyManager == address(0)) { + return managerToOperatorApproved[_owner][_operator]; + } else { + return managerToOperatorApproved[keyManager][_operator]; + } + } + + /** + * Returns true if _keyManager is the manager of the key + * identified by _tokenId + */ + function _isKeyManager( + uint _tokenId, + address _keyManager + ) internal view returns (bool) { + if ( + keyManagerOf[_tokenId] == _keyManager || + (keyManagerOf[_tokenId] == address(0) && ownerOf(_tokenId) == _keyManager) + ) { + return true; + } else { + return false; + } + } + + /** + * Assigns the key a new tokenId (from totalSupply) if it does not already have + * one assigned. + */ + function _assignNewTokenId(Key storage _key) internal { + if (_key.tokenId == 0) { + // This is a brand new owner + // We increment the tokenId counter + _totalSupply++; + // we assign the incremented `_totalSupply` as the tokenId for the new key + _key.tokenId = _totalSupply; + } + } + + /** + * Records the owner of a given tokenId + */ + function _recordOwner(address _keyOwner, uint _tokenId) internal { + // check expiration ts should be set to know if owner had previously registered a key + Key memory key = keyByOwner[_keyOwner]; + if (key.expirationTimestamp == 0) { + numberOfOwners++; + } + + // We register the owner of the tokenID + _ownerOf[_tokenId] = _keyOwner; + } + + /** + * @notice Modify the expirationTimestamp of a key + * by a given amount. + * @param _tokenId The ID of the key to modify. + * @param _deltaT The amount of time in seconds by which + * to modify the keys expirationTimestamp + * @param _addTime Choose whether to increase or decrease + * expirationTimestamp (false == decrease, true == increase) + * @dev Throws if owner does not have a valid key. + */ + function _timeMachine( + uint _tokenId, + uint256 _deltaT, + bool _addTime + ) internal { + address tokenOwner = ownerOf(_tokenId); + require(tokenOwner != address(0), "NON_EXISTENT_KEY"); + Key storage key = keyByOwner[tokenOwner]; + uint formerTimestamp = key.expirationTimestamp; + bool validKey = getHasValidKey(tokenOwner); + if (_addTime) { + if (validKey) { + key.expirationTimestamp = formerTimestamp + _deltaT; + } else { + key.expirationTimestamp = block.timestamp + _deltaT; + } + } else { + key.expirationTimestamp = formerTimestamp - _deltaT; + } + emit ExpirationChanged(_tokenId, _deltaT, _addTime); + } + + /** + * @dev Sets or unsets the approval of a given operator + * An operator is allowed to transfer all tokens of the sender on their behalf + * @param _to operator address to set the approval + * @param _approved representing the status of the approval to be set + */ + function setApprovalForAll(address _to, bool _approved) public onlyIfAlive { + require(_to != msg.sender, "APPROVE_SELF"); + managerToOperatorApproved[msg.sender][_to] = _approved; + emit ApprovalForAll(msg.sender, _to, _approved); + } + + /** + * @dev Checks if the given user is approved to transfer the tokenId. + */ + function _isApproved( + uint _tokenId, + address _user + ) internal view returns (bool) { + return approved[_tokenId] == _user; + } + + /** + * @dev Function to clear current approval of a given token ID + * @param _tokenId uint256 ID of the token to be transferred + */ + function _clearApproval(uint256 _tokenId) internal { + if (approved[_tokenId] != address(0)) { + approved[_tokenId] = address(0); + } + } + + /** + * @dev Change the maximum number of keys the lock can edit + * @param _maxNumberOfKeys uint the maximum number of keys + */ + function setMaxNumberOfKeys(uint _maxNumberOfKeys) external onlyLockManager { + require( + _maxNumberOfKeys > _totalSupply, + "maxNumberOfKeys is smaller than existing supply" + ); + maxNumberOfKeys = _maxNumberOfKeys; + } + + /** + * A function to change the default duration of each key in the lock + * @notice keys previously bought are unaffected by this change (i.e. + * existing keys timestamps are not recalculated/updated) + * @param _newExpirationDuration the new amount of time for each key purchased + * or zero (0) for a non-expiring key + */ + function setExpirationDuration( + uint _newExpirationDuration + ) external onlyLockManager { + expirationDuration = _newExpirationDuration; + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinERC721Enumerable.sol +pragma solidity ^0.8.0; + +// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; + +/** + * @title Implements the ERC-721 Enumerable extension. + */ +contract MixinERC721Enumerable is + ERC165StorageUpgradeable, + MixinLockCore, // Implements totalSupply + MixinKeys +{ + function _initializeMixinERC721Enumerable() internal { + /** + * register the supported interface to conform to ERC721Enumerable via ERC165 + * 0x780e9d63 === + * bytes4(keccak256('totalSupply()')) ^ + * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ + * bytes4(keccak256('tokenByIndex(uint256)')) + */ + _registerInterface(0x780e9d63); + } + + /// @notice Enumerate valid NFTs + /// @dev Throws if `_index` >= `totalSupply()`. + /// @param _index A counter less than `totalSupply()` + /// @return The token identifier for the `_index`th NFT, + /// (sort order not specified) + function tokenByIndex(uint256 _index) public view returns (uint256) { + require(_index < _totalSupply, "OUT_OF_RANGE"); + return _index; + } + + /// @notice Enumerate NFTs assigned to an owner + /// @dev Throws if `_index` >= `balanceOf(_keyOwner)` or if + /// `_keyOwner` is the zero address, representing invalid NFTs. + /// @param _keyOwner An address where we are interested in NFTs owned by them + /// @param _index A counter less than `balanceOf(_keyOwner)` + /// @return The token identifier for the `_index`th NFT assigned to `_keyOwner`, + /// (sort order not specified) + function tokenOfOwnerByIndex( + address _keyOwner, + uint256 _index + ) public view returns (uint256) { + require( + _index < balanceOf(_keyOwner) && _keyOwner != address(0), + "ONLY_ONE_KEY_PER_OWNER" + ); + return getTokenIdFor(_keyOwner); + } + + function supportsInterface( + bytes4 interfaceId + ) + public + view + virtual + override(AccessControlUpgradeable, ERC165StorageUpgradeable) + returns (bool) + { + return super.supportsInterface(interfaceId); + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinGrantKeys.sol +pragma solidity ^0.8.0; + +/** + * @title Mixin allowing the Lock owner to grant / gift keys to users. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinGrantKeys is MixinRoles, MixinKeys { + /** + * Allows the Lock owner to give a collection of users a key with no charge. + * Each key may be assigned a different expiration date. + */ + function grantKeys( + address[] calldata _recipients, + uint[] calldata _expirationTimestamps, + address[] calldata _keyManagers + ) external onlyKeyGranterOrManager { + for (uint i = 0; i < _recipients.length; i++) { + address recipient = _recipients[i]; + uint expirationTimestamp = _expirationTimestamps[i]; + address keyManager = _keyManagers[i]; + + require(recipient != address(0), "INVALID_ADDRESS"); + + Key storage toKey = keyByOwner[recipient]; + require( + expirationTimestamp > toKey.expirationTimestamp, + "ALREADY_OWNS_KEY" + ); + + uint idTo = toKey.tokenId; + + if (idTo == 0) { + _assignNewTokenId(toKey); + idTo = toKey.tokenId; + _recordOwner(recipient, idTo); + } + // Set the key Manager + _setKeyManagerOf(idTo, keyManager); + emit KeyManagerChanged(idTo, keyManager); + + toKey.expirationTimestamp = expirationTimestamp; + // trigger event + emit Transfer( + address(0), // This is a creation. + recipient, + idTo + ); + } + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/UnlockUtils.sol +pragma solidity >=0.5.17 <0.8.5; + +// This contract provides some utility methods for use with the unlock protocol smart contracts. +// Borrowed from: +// https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L943 + +library UnlockUtils { + function strConcat( + string memory _a, + string memory _b, + string memory _c, + string memory _d + ) internal pure returns (string memory _concatenatedString) { + return string(abi.encodePacked(_a, _b, _c, _d)); + } + + function uint2Str( + uint _i + ) internal pure returns (string memory _uintAsString) { + // make a copy of the param to avoid security/no-assign-params error + uint c = _i; + if (_i == 0) { + return "0"; + } + uint j = _i; + uint len; + while (j != 0) { + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len; + while (c != 0) { + k = k - 1; + uint8 temp = (48 + uint8(c - (c / 10) * 10)); + bytes1 b1 = bytes1(temp); + bstr[k] = b1; + c /= 10; + } + return string(bstr); + } + + function address2Str(address _addr) internal pure returns (string memory) { + bytes32 value = bytes32(uint256(uint160(_addr))); + bytes memory alphabet = "0123456789abcdef"; + bytes memory str = new bytes(42); + str[0] = "0"; + str[1] = "x"; + for (uint i = 0; i < 20; i++) { + str[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)]; + } + return string(str); + } +} + +// File contracts/mixins/MixinLockMetadata.sol +pragma solidity ^0.8.0; + +// import '@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721EnumerableUpgradeable.sol'; + +/** + * @title Mixin for metadata about the Lock. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinLockMetadata is + ERC165StorageUpgradeable, + MixinRoles, + MixinLockCore, + MixinKeys +{ + using UnlockUtils for uint; + using UnlockUtils for address; + using UnlockUtils for string; + + /// A descriptive name for a collection of NFTs in this contract.Defaults to "Unlock-Protocol" but is settable by lock owner + string public name; + + /// An abbreviated name for NFTs in this contract. Defaults to "KEY" but is settable by lock owner + string private lockSymbol; + + // the base Token URI for this Lock. If not set by lock owner, the global URI stored in Unlock is used. + string private baseTokenURI; + + event NewLockSymbol(string symbol); + + function _initializeMixinLockMetadata(string calldata _lockName) internal { + ERC165StorageUpgradeable.__ERC165Storage_init(); + name = _lockName; + // registering the optional erc721 metadata interface with ERC165.sol using + // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 + _registerInterface(0x5b5e139f); + } + + /** + * Allows the Lock owner to assign a descriptive name for this Lock. + */ + function updateLockName(string calldata _lockName) external onlyLockManager { + name = _lockName; + } + + /** + * Allows the Lock owner to assign a Symbol for this Lock. + */ + function updateLockSymbol( + string calldata _lockSymbol + ) external onlyLockManager { + lockSymbol = _lockSymbol; + emit NewLockSymbol(_lockSymbol); + } + + /** + * @dev Gets the token symbol + * @return string representing the token name + */ + function symbol() external view returns (string memory) { + if (bytes(lockSymbol).length == 0) { + return unlockProtocol.globalTokenSymbol(); + } else { + return lockSymbol; + } + } + + /** + * Allows the Lock owner to update the baseTokenURI for this Lock. + */ + function setBaseTokenURI( + string calldata _baseTokenURI + ) external onlyLockManager { + baseTokenURI = _baseTokenURI; + } + + /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. + * @param _tokenId The iD of the token for which we want to retrieve the URI. + * If 0 is passed here, we just return the appropriate baseTokenURI. + * If a custom URI has been set we don't return the lock address. + * It may be included in the custom baseTokenURI if needed. + * @dev URIs are defined in RFC 3986. The URI may point to a JSON file + * that conforms to the "ERC721 Metadata JSON Schema". + * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md + */ + function tokenURI(uint256 _tokenId) external view returns (string memory) { + string memory URI; + string memory tokenId; + string memory lockAddress = address(this).address2Str(); + string memory seperator; + + if (_tokenId != 0) { + tokenId = _tokenId.uint2Str(); + } else { + tokenId = ""; + } + + if (address(onTokenURIHook) != address(0)) { + address tokenOwner = ownerOf(_tokenId); + uint expirationTimestamp = keyExpirationTimestampFor(tokenOwner); + + return + onTokenURIHook.tokenURI( + address(this), + msg.sender, + tokenOwner, + _tokenId, + expirationTimestamp + ); + } + + if (bytes(baseTokenURI).length == 0) { + URI = unlockProtocol.globalBaseTokenURI(); + seperator = "/"; + } else { + URI = baseTokenURI; + seperator = ""; + lockAddress = ""; + } + + return URI.strConcat(lockAddress, seperator, tokenId); + } + + function supportsInterface( + bytes4 interfaceId + ) + public + view + virtual + override(AccessControlUpgradeable, ERC165StorageUpgradeable) + returns (bool) + { + return super.supportsInterface(interfaceId); + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinPurchase.sol +pragma solidity ^0.8.0; + +/** + * @title Mixin for the purchase-related functions. + * @author HardlyDifficult + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ +contract MixinPurchase is MixinFunds, MixinDisable, MixinLockCore, MixinKeys { + event RenewKeyPurchase(address indexed owner, uint newExpiration); + + event GasRefunded( + address indexed receiver, + uint refundedAmount, + address tokenAddress + ); + + event UnlockCallFailed(address indexed lockAddress, address unlockAddress); + + // default to 0 + uint256 private _gasRefundValue; + + /** + * @dev Set the value/price to be refunded to the sender on purchase + */ + + function setGasRefundValue(uint256 _refundValue) external onlyLockManager { + _gasRefundValue = _refundValue; + } + + /** + * @dev Returns value/price to be refunded to the sender on purchase + */ + function gasRefundValue() external view returns (uint256 _refundValue) { + return _gasRefundValue; + } + + /** + * @dev Purchase function + * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount + * (_value is ignored when using ETH) + * @param _recipient address of the recipient of the purchased key + * @param _referrer address of the user making the referral + * @param _keyManager optional address to grant managing rights to a specific address on creation + * @param _data arbitrary data populated by the front-end which initiated the sale + * @notice when called for an existing and non-expired key, the `_keyManager` param will be ignored + * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the + * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more + * than keyPrice is approved for spending). + */ + function purchase( + uint256 _value, + address _recipient, + address _referrer, + address _keyManager, + bytes calldata _data + ) external payable onlyIfAlive notSoldOut { + require(_recipient != address(0), "INVALID_ADDRESS"); + + // Assign the key + Key storage toKey = keyByOwner[_recipient]; + uint idTo = toKey.tokenId; + uint newTimeStamp; + + if (idTo == 0) { + // Assign a new tokenId (if a new owner or previously transferred) + _assignNewTokenId(toKey); + // refresh the cached value + idTo = toKey.tokenId; + _recordOwner(_recipient, idTo); + // check for a non-expiring key + if (expirationDuration == type(uint).max) { + newTimeStamp = type(uint).max; + } else { + newTimeStamp = block.timestamp + expirationDuration; + } + toKey.expirationTimestamp = newTimeStamp; + + // set key manager + _setKeyManagerOf(idTo, _keyManager); + + // trigger event + emit Transfer( + address(0), // This is a creation. + _recipient, + idTo + ); + } else if (toKey.expirationTimestamp > block.timestamp) { + // prevent re-purchase of a valid non-expiring key + require( + toKey.expirationTimestamp != type(uint).max, + "A valid non-expiring key can not be purchased twice" + ); + + // This is an existing owner trying to extend their key + newTimeStamp = toKey.expirationTimestamp + expirationDuration; + toKey.expirationTimestamp = newTimeStamp; + + emit RenewKeyPurchase(_recipient, newTimeStamp); + } else { + // This is an existing owner trying to renew their expired or cancelled key + if (expirationDuration == type(uint).max) { + newTimeStamp = type(uint).max; + } else { + newTimeStamp = block.timestamp + expirationDuration; + } + toKey.expirationTimestamp = newTimeStamp; + + _setKeyManagerOf(idTo, _keyManager); + + emit RenewKeyPurchase(_recipient, newTimeStamp); + } + + uint inMemoryKeyPrice = _purchasePriceFor(_recipient, _referrer, _data); + + // make sure unlock is a contract, and we catch possible reverts + if (address(unlockProtocol).code.length > 0) { + try + unlockProtocol.recordKeyPurchase(inMemoryKeyPrice, _referrer) + {} catch { + // emit missing unlock + emit UnlockCallFailed(address(this), address(unlockProtocol)); + } + } else { + // emit missing unlock + emit UnlockCallFailed(address(this), address(unlockProtocol)); + } + + // We explicitly allow for greater amounts of ETH or tokens to allow 'donations' + uint pricePaid; + if (tokenAddress != address(0)) { + pricePaid = _value; + IERC20Upgradeable token = IERC20Upgradeable(tokenAddress); + token.transferFrom(msg.sender, address(this), pricePaid); + } else { + pricePaid = msg.value; + } + require(pricePaid >= inMemoryKeyPrice, "INSUFFICIENT_VALUE"); + + if (address(onKeyPurchaseHook) != address(0)) { + onKeyPurchaseHook.onKeyPurchase( + msg.sender, + _recipient, + _referrer, + _data, + inMemoryKeyPrice, + pricePaid + ); + } + + // refund gas + if (_gasRefundValue != 0) { + if (tokenAddress != address(0)) { + IERC20Upgradeable token = IERC20Upgradeable(tokenAddress); + token.transferFrom(address(this), msg.sender, _gasRefundValue); + } else { + (bool success, ) = msg.sender.call{value: _gasRefundValue}(""); + require(success, "Refund failed."); + } + emit GasRefunded(msg.sender, _gasRefundValue, tokenAddress); + } + } + + /** + * @notice returns the minimum price paid for a purchase with these params. + * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook + */ + function purchasePriceFor( + address _recipient, + address _referrer, + bytes calldata _data + ) external view returns (uint minKeyPrice) { + minKeyPrice = _purchasePriceFor(_recipient, _referrer, _data); + } + + /** + * @notice returns the minimum price paid for a purchase with these params. + * @dev minKeyPrice considers any discount from Unlock or the OnKeyPurchase hook + */ + function _purchasePriceFor( + address _recipient, + address _referrer, + bytes memory _data + ) internal view returns (uint minKeyPrice) { + if (address(onKeyPurchaseHook) != address(0)) { + minKeyPrice = onKeyPurchaseHook.keyPurchasePrice( + msg.sender, + _recipient, + _referrer, + _data + ); + } else { + minKeyPrice = keyPrice; + } + return minKeyPrice; + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/mixins/MixinRefunds.sol +pragma solidity ^0.8.0; + +contract MixinRefunds is MixinRoles, MixinFunds, MixinLockCore, MixinKeys { + // CancelAndRefund will return funds based on time remaining minus this penalty. + // This is calculated as `proRatedRefund * refundPenaltyBasisPoints / BASIS_POINTS_DEN`. + uint public refundPenaltyBasisPoints; + + uint public freeTrialLength; + + event CancelKey( + uint indexed tokenId, + address indexed owner, + address indexed sendTo, + uint refund + ); + + event RefundPenaltyChanged( + uint freeTrialLength, + uint refundPenaltyBasisPoints + ); + + function _initializeMixinRefunds() internal { + // default to 10% + refundPenaltyBasisPoints = 1000; + } + + /** + * @dev Invoked by the lock owner to destroy the user's ket and perform a refund and cancellation + * of the key + */ + function expireAndRefundFor( + address payable _keyOwner, + uint amount + ) external onlyLockManager hasValidKey(_keyOwner) { + _cancelAndRefund(_keyOwner, amount); + } + + /** + * @dev Destroys the key and sends a refund based on the amount of time remaining. + * @param _tokenId The id of the key to cancel. + */ + function cancelAndRefund( + uint _tokenId + ) external onlyKeyManagerOrApproved(_tokenId) { + address payable keyOwner = payable(ownerOf(_tokenId)); + uint refund = _getCancelAndRefundValue(keyOwner); + + _cancelAndRefund(keyOwner, refund); + } + + /** + * Allow the owner to change the refund penalty. + */ + function updateRefundPenalty( + uint _freeTrialLength, + uint _refundPenaltyBasisPoints + ) external onlyLockManager { + emit RefundPenaltyChanged(_freeTrialLength, _refundPenaltyBasisPoints); + + freeTrialLength = _freeTrialLength; + refundPenaltyBasisPoints = _refundPenaltyBasisPoints; + } + + /** + * @dev Determines how much of a refund a key owner would receive if they issued + * a cancelAndRefund block.timestamp. + * Note that due to the time required to mine a tx, the actual refund amount will be lower + * than what the user reads from this call. + */ + function getCancelAndRefundValueFor( + address _keyOwner + ) external view returns (uint refund) { + return _getCancelAndRefundValue(_keyOwner); + } + + /** + * @dev cancels the key for the given keyOwner and sends the refund to the msg.sender. + */ + function _cancelAndRefund(address payable _keyOwner, uint refund) internal { + Key storage key = keyByOwner[_keyOwner]; + + emit CancelKey(key.tokenId, _keyOwner, msg.sender, refund); + // expirationTimestamp is a proxy for hasKey, setting this to `block.timestamp` instead + // of 0 so that we can still differentiate hasKey from hasValidKey. + key.expirationTimestamp = block.timestamp; + + if (refund > 0) { + // Security: doing this last to avoid re-entrancy concerns + _transfer(tokenAddress, _keyOwner, refund); + } + + // inform the hook if there is one registered + if (address(onKeyCancelHook) != address(0)) { + onKeyCancelHook.onKeyCancel(msg.sender, _keyOwner, refund); + } + } + + /** + * @dev Determines how much of a refund a key owner would receive if they issued + * a cancelAndRefund now. + * @param _keyOwner The owner of the key check the refund value for. + */ + function _getCancelAndRefundValue( + address _keyOwner + ) private view hasValidKey(_keyOwner) returns (uint refund) { + Key storage key = keyByOwner[_keyOwner]; + + // return entire purchased price if key is non-expiring + if (expirationDuration == type(uint).max) { + return keyPrice; + } + + // Math: safeSub is not required since `hasValidKey` confirms timeRemaining is positive + uint timeRemaining = key.expirationTimestamp - block.timestamp; + if (timeRemaining + freeTrialLength >= expirationDuration) { + refund = keyPrice; + } else { + refund = (keyPrice * timeRemaining) / expirationDuration; + } + + // Apply the penalty if this is not a free trial + if ( + freeTrialLength == 0 || + timeRemaining + freeTrialLength < expirationDuration + ) { + uint penalty = (keyPrice * refundPenaltyBasisPoints) / BASIS_POINTS_DEN; + if (refund > penalty) { + refund -= penalty; + } else { + refund = 0; + } + } + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File @openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol@v4.4.2 +// OpenZeppelin Contracts v4.4.1 (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 IERC721ReceiverUpgradeable { + /** + * @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 `IERC721.onERC721Received.selector`. + */ + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external returns (bytes4); +} + +// File contracts/mixins/MixinTransfer.sol +pragma solidity ^0.8.0; + +/** + * @title Mixin for the transfer-related functions needed to meet the ERC721 + * standard. + * @dev `Mixins` are a design pattern seen in the 0x contracts. It simply + * separates logically groupings of code to ease readability. + */ + +contract MixinTransfer is MixinRoles, MixinFunds, MixinLockCore, MixinKeys { + using AddressUpgradeable for address; + + event TransferFeeChanged(uint transferFeeBasisPoints); + + // 0x150b7a02 == bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')) + bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; + + // The fee relative to keyPrice to charge when transfering a Key to another account + // (potentially on a 0x marketplace). + // This is calculated as `keyPrice * transferFeeBasisPoints / BASIS_POINTS_DEN`. + uint public transferFeeBasisPoints; + + /** + * @notice Allows the key owner to safely share their key (parent key) by + * transferring a portion of the remaining time to a new key (child key). + * @param _to The recipient of the shared key + * @param _tokenId the key to share + * @param _timeShared The amount of time shared + */ + function shareKey( + address _to, + uint _tokenId, + uint _timeShared + ) public onlyIfAlive onlyKeyManagerOrApproved(_tokenId) { + require( + transferFeeBasisPoints < BASIS_POINTS_DEN, + "KEY_TRANSFERS_DISABLED" + ); + require(_to != address(0), "INVALID_ADDRESS"); + address keyOwner = _ownerOf[_tokenId]; + require(getHasValidKey(keyOwner), "KEY_NOT_VALID"); + require(keyOwner != _to, "TRANSFER_TO_SELF"); + + Key storage fromKey = keyByOwner[keyOwner]; + Key storage toKey = keyByOwner[_to]; + uint idTo = toKey.tokenId; + uint time; + // get the remaining time for the origin key + uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; + // get the transfer fee based on amount of time wanted share + uint fee = getTransferFee(keyOwner, _timeShared); + uint timePlusFee = _timeShared + fee; + + // ensure that we don't try to share too much + if (timePlusFee < timeRemaining) { + // now we can safely set the time + time = _timeShared; + // deduct time from parent key, including transfer fee + _timeMachine(_tokenId, timePlusFee, false); + } else { + // we have to recalculate the fee here + fee = getTransferFee(keyOwner, timeRemaining); + time = timeRemaining - fee; + fromKey.expirationTimestamp = block.timestamp; // Effectively expiring the key + emit ExpireKey(_tokenId); + } + + if (idTo == 0) { + _assignNewTokenId(toKey); + idTo = toKey.tokenId; + _recordOwner(_to, idTo); + emit Transfer( + address(0), // This is a creation or time-sharing + _to, + idTo + ); + } else if (toKey.expirationTimestamp <= block.timestamp) { + // reset the key Manager for expired keys + _setKeyManagerOf(idTo, address(0)); + } + + // add time to new key + _timeMachine(idTo, time, true); + // trigger event + emit Transfer(keyOwner, _to, idTo); + + require( + _checkOnERC721Received(keyOwner, _to, idTo, ""), + "NON_COMPLIANT_ERC721_RECEIVER" + ); + } + + function transferFrom( + address _from, + address _recipient, + uint _tokenId + ) public onlyIfAlive hasValidKey(_from) onlyKeyManagerOrApproved(_tokenId) { + require(ownerOf(_tokenId) == _from, "TRANSFER_FROM: NOT_KEY_OWNER"); + require( + transferFeeBasisPoints < BASIS_POINTS_DEN, + "KEY_TRANSFERS_DISABLED" + ); + require(_recipient != address(0), "INVALID_ADDRESS"); + require(_from != _recipient, "TRANSFER_TO_SELF"); + uint fee = getTransferFee(_from, 0); + + Key storage fromKey = keyByOwner[_from]; + Key storage toKey = keyByOwner[_recipient]; + + uint previousExpiration = toKey.expirationTimestamp; + // subtract the fee from the senders key before the transfer + _timeMachine(_tokenId, fee, false); + + if (toKey.tokenId == 0) { + toKey.tokenId = _tokenId; + _recordOwner(_recipient, _tokenId); + // Clear any previous approvals + _clearApproval(_tokenId); + } + + if (previousExpiration <= block.timestamp) { + // The recipient did not have a key, or had a key but it expired. The new expiration is the sender's key expiration + // An expired key is no longer a valid key, so the new tokenID is the sender's tokenID + toKey.expirationTimestamp = fromKey.expirationTimestamp; + toKey.tokenId = _tokenId; + + // Reset the key Manager to the key owner + _setKeyManagerOf(_tokenId, address(0)); + + _recordOwner(_recipient, _tokenId); + } else { + require( + expirationDuration != type(uint).max, + "Recipient already owns a non-expiring key" + ); + // The recipient has a non expired key. We just add them the corresponding remaining time + // SafeSub is not required since the if confirms `previousExpiration - block.timestamp` cannot underflow + toKey.expirationTimestamp = + fromKey.expirationTimestamp + + previousExpiration - + block.timestamp; + } + + // Effectively expiring the key for the previous owner + fromKey.expirationTimestamp = block.timestamp; + + // Set the tokenID to 0 for the previous owner to avoid duplicates + fromKey.tokenId = 0; + + // trigger event + emit Transfer(_from, _recipient, _tokenId); + } + + /** + * @notice An ERC-20 style transfer. + * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). + * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user + * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. + */ + function transfer(address _to, uint _value) public returns (bool success) { + uint maxTimeToSend = _value * expirationDuration; + Key storage fromKey = keyByOwner[msg.sender]; + uint timeRemaining = fromKey.expirationTimestamp - block.timestamp; + if (maxTimeToSend < timeRemaining) { + shareKey(_to, fromKey.tokenId, maxTimeToSend); + } else { + transferFrom(msg.sender, _to, fromKey.tokenId); + } + + // Errors will cause a revert + return true; + } + + /** + * @notice Transfers the ownership of an NFT from one address to another address + * @dev This works identically to the other function with an extra data parameter, + * except this function just sets data to '' + * @param _from The current owner of the NFT + * @param _to The new owner + * @param _tokenId The NFT to transfer + */ + function safeTransferFrom(address _from, address _to, uint _tokenId) public { + safeTransferFrom(_from, _to, _tokenId, ""); + } + + /** + * @notice Transfers the ownership of an NFT from one address to another address. + * When transfer is complete, this functions + * checks if `_to` is a smart contract (code size > 0). If so, it calls + * `onERC721Received` on `_to` and throws if the return value is not + * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. + * @param _from The current owner of the NFT + * @param _to The new owner + * @param _tokenId The NFT to transfer + * @param _data Additional data with no specified format, sent in call to `_to` + */ + function safeTransferFrom( + address _from, + address _to, + uint _tokenId, + bytes memory _data + ) public { + transferFrom(_from, _to, _tokenId); + require( + _checkOnERC721Received(_from, _to, _tokenId, _data), + "NON_COMPLIANT_ERC721_RECEIVER" + ); + } + + /** + * Allow the Lock owner to change the transfer fee. + */ + function updateTransferFee( + uint _transferFeeBasisPoints + ) external onlyLockManager { + emit TransferFeeChanged(_transferFeeBasisPoints); + transferFeeBasisPoints = _transferFeeBasisPoints; + } + + /** + * Determines how much of a fee a key owner would need to pay in order to + * transfer the key to another account. This is pro-rated so the fee goes down + * overtime. + * @param _keyOwner The owner of the key check the transfer fee for. + */ + function getTransferFee( + address _keyOwner, + uint _time + ) public view returns (uint) { + if (!getHasValidKey(_keyOwner)) { + return 0; + } else { + Key storage key = keyByOwner[_keyOwner]; + uint timeToTransfer; + uint fee; + // Math: safeSub is not required since `hasValidKey` confirms timeToTransfer is positive + // this is for standard key transfers + if (_time == 0) { + timeToTransfer = key.expirationTimestamp - block.timestamp; + } else { + timeToTransfer = _time; + } + fee = (timeToTransfer * transferFeeBasisPoints) / BASIS_POINTS_DEN; + return fee; + } + } + + /** + * @dev Internal function to invoke `onERC721Received` on a target address + * The call is not executed if the target address is not a contract + * @param from address representing the previous owner of the given token ID + * @param to target address that will receive the tokens + * @param tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return whether the call correctly returned the expected magic value + */ + function _checkOnERC721Received( + address from, + address to, + uint256 tokenId, + bytes memory _data + ) internal returns (bool) { + if (!to.isContract()) { + return true; + } + bytes4 retval = IERC721ReceiverUpgradeable(to).onERC721Received( + msg.sender, + from, + tokenId, + _data + ); + return (retval == _ERC721_RECEIVED); + } + + uint256[1000] private __safe_upgrade_gap; +} + +// File contracts/PublicLock.sol +pragma solidity ^0.8.4; + +/** + * @title The Lock contract + * @author Julien Genestoux (unlock-protocol.com) + * @dev ERC165 allows our contract to be queried to determine whether it implements a given interface. + * Every ERC-721 compliant contract must implement the ERC165 interface. + * https://eips.ethereum.org/EIPS/eip-721 + */ +contract PublicLock is + Initializable, + ERC165StorageUpgradeable, + MixinRoles, + MixinFunds, + MixinDisable, + MixinLockCore, + MixinKeys, + MixinLockMetadata, + MixinERC721Enumerable, + MixinGrantKeys, + MixinPurchase, + MixinTransfer, + MixinRefunds +{ + function initialize( + address payable _lockCreator, + uint _expirationDuration, + address _tokenAddress, + uint _keyPrice, + uint _maxNumberOfKeys, + string calldata _lockName + ) public initializer { + MixinFunds._initializeMixinFunds(_tokenAddress); + MixinDisable._initializeMixinDisable(); + MixinLockCore._initializeMixinLockCore( + _lockCreator, + _expirationDuration, + _keyPrice, + _maxNumberOfKeys + ); + MixinLockMetadata._initializeMixinLockMetadata(_lockName); + MixinERC721Enumerable._initializeMixinERC721Enumerable(); + MixinRefunds._initializeMixinRefunds(); + MixinRoles._initializeMixinRoles(_lockCreator); + // registering the interface for erc721 with ERC165.sol using + // the ID specified in the standard: https://eips.ethereum.org/EIPS/eip-721 + _registerInterface(0x80ac58cd); + } + + /** + * @notice Allow the contract to accept tips in ETH sent directly to the contract. + * @dev This is okay to use even if the lock is priced in ERC-20 tokens + */ + receive() external payable {} + + /** + Overrides + */ + function supportsInterface( + bytes4 interfaceId + ) + public + view + virtual + override( + MixinERC721Enumerable, + MixinLockMetadata, + AccessControlUpgradeable, + ERC165StorageUpgradeable + ) + returns (bool) + { + return super.supportsInterface(interfaceId); + } +} From 584157d57b8851e748ac862fab4aed6957fb1d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 13:43:03 +0200 Subject: [PATCH 23/27] Update packages/unlock-js/scripts/compressAbi.js --- packages/unlock-js/scripts/compressAbi.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/unlock-js/scripts/compressAbi.js b/packages/unlock-js/scripts/compressAbi.js index 4e0cdb7e955..340599004dd 100644 --- a/packages/unlock-js/scripts/compressAbi.js +++ b/packages/unlock-js/scripts/compressAbi.js @@ -12,7 +12,7 @@ const path = require('path') const abis = require('@unlock-protocol/contracts') const unlockVersions = ['v10', 'v11', 'v12', 'v13'] -const publicLockVersions = ['v10', 'v11', 'v12', 'v13', 'v14'] +const publicLockVersions = ['v9', 'v10', 'v11', 'v12', 'v13', 'v14'] const data = { PublicLock: publicLockVersions.reduce( From 8eb31e61a4a1b2e1b7254243765de657153bb95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 14:42:28 +0200 Subject: [PATCH 24/27] unlockjs rebuild abis --- packages/unlock-js/scripts/compressAbi.js | 2 +- packages/unlock-js/src/abis.ts | 105 ++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/packages/unlock-js/scripts/compressAbi.js b/packages/unlock-js/scripts/compressAbi.js index 4e0cdb7e955..340599004dd 100644 --- a/packages/unlock-js/scripts/compressAbi.js +++ b/packages/unlock-js/scripts/compressAbi.js @@ -12,7 +12,7 @@ const path = require('path') const abis = require('@unlock-protocol/contracts') const unlockVersions = ['v10', 'v11', 'v12', 'v13'] -const publicLockVersions = ['v10', 'v11', 'v12', 'v13', 'v14'] +const publicLockVersions = ['v9', 'v10', 'v11', 'v12', 'v13', 'v14'] const data = { PublicLock: publicLockVersions.reduce( diff --git a/packages/unlock-js/src/abis.ts b/packages/unlock-js/src/abis.ts index f74f7501d4f..000131cb36c 100644 --- a/packages/unlock-js/src/abis.ts +++ b/packages/unlock-js/src/abis.ts @@ -4,6 +4,111 @@ const abis = { "PublicLock": { + "v9": { + "contractName": "PublicLock", + "abi": [ + "event Approval (address indexed owner,address indexed approved,uint256 indexed tokenId)", + "event ApprovalForAll (address indexed owner,address indexed operator,bool approved)", + "event CancelKey (uint256 indexed tokenId,address indexed owner,address indexed sendTo,uint256 refund)", + "event Disable ()", + "event ExpirationChanged (uint256 indexed _tokenId,uint256 _amount,bool _timeAdded)", + "event ExpireKey (uint256 indexed tokenId)", + "event GasRefunded (address indexed receiver,uint256 refundedAmount,address tokenAddress)", + "event KeyGranterAdded (address indexed account)", + "event KeyGranterRemoved (address indexed account)", + "event KeyManagerChanged (uint256 indexed _tokenId,address indexed _newManager)", + "event LockManagerAdded (address indexed account)", + "event LockManagerRemoved (address indexed account)", + "event NewLockSymbol (string symbol)", + "event PricingChanged (uint256 oldKeyPrice,uint256 keyPrice,address oldTokenAddress,address tokenAddress)", + "event RefundPenaltyChanged (uint256 freeTrialLength,uint256 refundPenaltyBasisPoints)", + "event RenewKeyPurchase (address indexed owner,uint256 newExpiration)", + "event RoleAdminChanged (bytes32 indexed role,bytes32 indexed previousAdminRole,bytes32 indexed newAdminRole)", + "event RoleGranted (bytes32 indexed role,address indexed account,address indexed sender)", + "event RoleRevoked (bytes32 indexed role,address indexed account,address indexed sender)", + "event Transfer (address indexed from,address indexed to,uint256 indexed tokenId)", + "event TransferFeeChanged (uint256 transferFeeBasisPoints)", + "event UnlockCallFailed (address indexed lockAddress,address unlockAddress)", + "event Withdrawal (address indexed sender,address indexed tokenAddress,address indexed beneficiary,uint256 amount)", + "function DEFAULT_ADMIN_ROLE() view returns (bytes32)", + "function KEY_GRANTER_ROLE() view returns (bytes32)", + "function LOCK_MANAGER_ROLE() view returns (bytes32)", + "function addKeyGranter(address account)", + "function addLockManager(address account)", + "function approve(address _approved,uint256 _tokenId)", + "function approveBeneficiary(address _spender,uint256 _amount) returns (bool)", + "function balanceOf(address _keyOwner) view returns (uint256)", + "function beneficiary() view returns (address)", + "function cancelAndRefund(uint256 _tokenId)", + "function disableLock()", + "function expirationDuration() view returns (uint256)", + "function expireAndRefundFor(address _keyOwner,uint256 amount)", + "function freeTrialLength() view returns (uint256)", + "function gasRefundValue() view returns (uint256 _refundValue)", + "function getApproved(uint256 _tokenId) view returns (address)", + "function getCancelAndRefundValueFor(address _keyOwner) view returns (uint256 refund)", + "function getHasValidKey(address _keyOwner) view returns (bool isValid)", + "function getRoleAdmin(bytes32 role) view returns (bytes32)", + "function getTokenIdFor(address _account) view returns (uint256)", + "function getTransferFee(address _keyOwner,uint256 _time) view returns (uint256)", + "function grantKeys(address[] _recipients,uint256[] _expirationTimestamps,address[] _keyManagers)", + "function grantRole(bytes32 role,address account)", + "function hasRole(bytes32 role,address account) view returns (bool)", + "function initialize(address _lockCreator,uint256 _expirationDuration,address _tokenAddress,uint256 _keyPrice,uint256 _maxNumberOfKeys,string _lockName)", + "function isAlive() view returns (bool)", + "function isApprovedForAll(address _owner,address _operator) view returns (bool)", + "function isKeyGranter(address account) view returns (bool)", + "function isLockManager(address account) view returns (bool)", + "function keyExpirationTimestampFor(address _keyOwner) view returns (uint256)", + "function keyManagerOf(uint256) view returns (address)", + "function keyPrice() view returns (uint256)", + "function maxNumberOfKeys() view returns (uint256)", + "function name() view returns (string)", + "function numberOfOwners() view returns (uint256)", + "function onKeyCancelHook() view returns (address)", + "function onKeyPurchaseHook() view returns (address)", + "function onTokenURIHook() view returns (address)", + "function onValidKeyHook() view returns (address)", + "function ownerOf(uint256 _tokenId) view returns (address)", + "function publicLockVersion() pure returns (uint16)", + "function purchase(uint256 _value,address _recipient,address _referrer,address _keyManager,bytes _data) payable", + "function purchasePriceFor(address _recipient,address _referrer,bytes _data) view returns (uint256 minKeyPrice)", + "function refundPenaltyBasisPoints() view returns (uint256)", + "function renounceLockManager()", + "function renounceRole(bytes32 role,address account)", + "function revokeKeyGranter(address _granter)", + "function revokeRole(bytes32 role,address account)", + "function safeTransferFrom(address _from,address _to,uint256 _tokenId)", + "function safeTransferFrom(address _from,address _to,uint256 _tokenId,bytes _data)", + "function setApprovalForAll(address _to,bool _approved)", + "function setBaseTokenURI(string _baseTokenURI)", + "function setEventHooks(address _onKeyPurchaseHook,address _onKeyCancelHook,address _onValidKeyHook,address _onTokenURIHook)", + "function setExpirationDuration(uint256 _newExpirationDuration)", + "function setGasRefundValue(uint256 _refundValue)", + "function setKeyManagerOf(uint256 _tokenId,address _keyManager)", + "function setMaxNumberOfKeys(uint256 _maxNumberOfKeys)", + "function shareKey(address _to,uint256 _tokenId,uint256 _timeShared)", + "function supportsInterface(bytes4 interfaceId) view returns (bool)", + "function symbol() view returns (string)", + "function tokenAddress() view returns (address)", + "function tokenByIndex(uint256 _index) view returns (uint256)", + "function tokenOfOwnerByIndex(address _keyOwner,uint256 _index) view returns (uint256)", + "function tokenURI(uint256 _tokenId) view returns (string)", + "function totalSupply() view returns (uint256)", + "function transfer(address _to,uint256 _value) returns (bool success)", + "function transferFeeBasisPoints() view returns (uint256)", + "function transferFrom(address _from,address _recipient,uint256 _tokenId)", + "function unlockProtocol() view returns (address)", + "function updateBeneficiary(address _beneficiary)", + "function updateKeyPricing(uint256 _keyPrice,address _tokenAddress)", + "function updateLockName(string _lockName)", + "function updateLockSymbol(string _lockSymbol)", + "function updateRefundPenalty(uint256 _freeTrialLength,uint256 _refundPenaltyBasisPoints)", + "function updateTransferFee(uint256 _transferFeeBasisPoints)", + "function withdraw(address _tokenAddress,uint256 _amount)" + ], + "bytecodeHash": "0x0cf7c1b77621773fd65811a23143e5e49946d2de75c18934b495940cab871397" + }, "v10": { "contractName": "PublicLock", "abi": [ From facb46bc66d958ccc7522dcd29a536d5caf1fc57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 14:42:50 +0200 Subject: [PATCH 25/27] unlockjs refactor previous functions --- .../src/PublicLock/previous/addKeyGranter.js | 17 ++++ .../src/PublicLock/previous/addLockManager.js | 24 ++++++ .../PublicLock/previous/approveBeneficiary.js | 44 +++++++++++ .../PublicLock/previous/cancelAndRefund.js | 24 ++++++ .../PublicLock/previous/expireAndRefundFor.js | 41 ++++++++++ .../previous/getCancelAndRefundValueFor.js | 23 ++++++ .../getKeyExpirationByLockForOwner.js | 34 ++++++++ .../src/PublicLock/previous/getLock.js | 11 +++ .../PublicLock/previous/getTokenIdForOwner.js | 17 ++++ .../src/PublicLock/previous/grantKey.js | 24 ++++++ .../src/PublicLock/previous/grantKeys.js | 77 +++++++++++++++++++ .../src/PublicLock/previous/index.js | 57 ++++++++++++++ .../PublicLock/previous/initializeTemplate.js | 33 ++++++++ .../src/PublicLock/previous/isKeyGranter.js | 11 +++ .../src/PublicLock/previous/isLockManager.js | 12 +++ .../src/PublicLock/previous/keyManagerOf.js | 9 +++ .../previous/renounceLockManager.js | 23 ++++++ .../PublicLock/previous/setBaseTokenURI.js | 23 ++++++ .../src/PublicLock/previous/setEventHooks.js | 21 +++++ .../PublicLock/previous/setKeyManagerOf.js | 26 +++++++ .../src/PublicLock/previous/shareKey.js | 33 ++++++++ .../src/PublicLock/previous/totalKeys.js | 9 +++ .../src/PublicLock/previous/updateKeyPrice.js | 61 +++++++++++++++ .../src/PublicLock/previous/updateLockName.js | 23 ++++++ .../PublicLock/previous/updateLockSymbol.js | 23 ++++++ .../previous/updateRefundPenalty.js | 28 +++++++ .../PublicLock/previous/updateTransferFee.js | 20 +++++ .../PublicLock/previous/withdrawFromLock.js | 59 ++++++++++++++ packages/unlock-js/src/PublicLock/v9/index.js | 36 ++++----- 29 files changed, 825 insertions(+), 18 deletions(-) create mode 100644 packages/unlock-js/src/PublicLock/previous/addKeyGranter.js create mode 100644 packages/unlock-js/src/PublicLock/previous/addLockManager.js create mode 100644 packages/unlock-js/src/PublicLock/previous/approveBeneficiary.js create mode 100644 packages/unlock-js/src/PublicLock/previous/cancelAndRefund.js create mode 100644 packages/unlock-js/src/PublicLock/previous/expireAndRefundFor.js create mode 100644 packages/unlock-js/src/PublicLock/previous/getCancelAndRefundValueFor.js create mode 100644 packages/unlock-js/src/PublicLock/previous/getKeyExpirationByLockForOwner.js create mode 100644 packages/unlock-js/src/PublicLock/previous/getLock.js create mode 100644 packages/unlock-js/src/PublicLock/previous/getTokenIdForOwner.js create mode 100644 packages/unlock-js/src/PublicLock/previous/grantKey.js create mode 100644 packages/unlock-js/src/PublicLock/previous/grantKeys.js create mode 100644 packages/unlock-js/src/PublicLock/previous/index.js create mode 100644 packages/unlock-js/src/PublicLock/previous/initializeTemplate.js create mode 100644 packages/unlock-js/src/PublicLock/previous/isKeyGranter.js create mode 100644 packages/unlock-js/src/PublicLock/previous/isLockManager.js create mode 100644 packages/unlock-js/src/PublicLock/previous/keyManagerOf.js create mode 100644 packages/unlock-js/src/PublicLock/previous/renounceLockManager.js create mode 100644 packages/unlock-js/src/PublicLock/previous/setBaseTokenURI.js create mode 100644 packages/unlock-js/src/PublicLock/previous/setEventHooks.js create mode 100644 packages/unlock-js/src/PublicLock/previous/setKeyManagerOf.js create mode 100644 packages/unlock-js/src/PublicLock/previous/shareKey.js create mode 100644 packages/unlock-js/src/PublicLock/previous/totalKeys.js create mode 100644 packages/unlock-js/src/PublicLock/previous/updateKeyPrice.js create mode 100644 packages/unlock-js/src/PublicLock/previous/updateLockName.js create mode 100644 packages/unlock-js/src/PublicLock/previous/updateLockSymbol.js create mode 100644 packages/unlock-js/src/PublicLock/previous/updateRefundPenalty.js create mode 100644 packages/unlock-js/src/PublicLock/previous/updateTransferFee.js create mode 100644 packages/unlock-js/src/PublicLock/previous/withdrawFromLock.js diff --git a/packages/unlock-js/src/PublicLock/previous/addKeyGranter.js b/packages/unlock-js/src/PublicLock/previous/addKeyGranter.js new file mode 100644 index 00000000000..c93b152b4f4 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/addKeyGranter.js @@ -0,0 +1,17 @@ +export default async function ( + { lockAddress, keyGranter }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + const transactionPromise = lockContract.addKeyGranter(keyGranter) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + + await this.provider.waitForTransaction(hash) + return true +} diff --git a/packages/unlock-js/src/PublicLock/previous/addLockManager.js b/packages/unlock-js/src/PublicLock/previous/addLockManager.js new file mode 100644 index 00000000000..d5eb853e1b2 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/addLockManager.js @@ -0,0 +1,24 @@ +/** + * Add lock manager to Contract + * @param {string} lockAddress address of the lock + * @param {string} userAddress address of the user + */ + +export default async function ( + { lockAddress, userAddress }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + const transactionPromise = lockContract.addLockManager(userAddress) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/approveBeneficiary.js b/packages/unlock-js/src/PublicLock/previous/approveBeneficiary.js new file mode 100644 index 00000000000..0e1a55d31c6 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/approveBeneficiary.js @@ -0,0 +1,44 @@ +import utils from '../../utils' +import { ZERO, MAX_UINT } from '../../constants' +import { getErc20Decimals } from '../../erc20' + +export default async function ( + { lockAddress, spender, amount = '0', decimals, erc20Address }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + if (!erc20Address || erc20Address !== ZERO) { + erc20Address = await lockContract.tokenAddress() + } + + if (erc20Address === ZERO) { + throw new Error('Lock can only set approval for ERC20') + } + + // decimals could be 0! + let actualAmount + if (amount !== MAX_UINT) { + if (decimals == null) { + decimals = await getErc20Decimals(erc20Address, this.provider) + } + actualAmount = utils.toDecimal(amount, decimals) + } else { + actualAmount = amount + } + + const transactionPromise = lockContract.approveBeneficiary( + spender, + actualAmount + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/cancelAndRefund.js b/packages/unlock-js/src/PublicLock/previous/cancelAndRefund.js new file mode 100644 index 00000000000..6ab1902dcfe --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/cancelAndRefund.js @@ -0,0 +1,24 @@ +export default async function ( + { lockAddress, tokenId }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + + if (!tokenId) { + const owner = await this.signer.getAddress() + tokenId = await lockContract.getTokenIdFor(owner) + } + + const transactionPromise = lockContract.cancelAndRefund(tokenId) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/expireAndRefundFor.js b/packages/unlock-js/src/PublicLock/previous/expireAndRefundFor.js new file mode 100644 index 00000000000..fe39f47df3f --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/expireAndRefundFor.js @@ -0,0 +1,41 @@ +import utils from '../../utils' +import { ZERO } from '../../constants' +import { getErc20Decimals } from '../../erc20' + +export default async function ( + { lockAddress, keyOwner, amount = '0', decimals, erc20Address }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + if (!erc20Address || erc20Address !== ZERO) { + erc20Address = await lockContract.tokenAddress() + } + + // decimals could be 0! + if (decimals == null) { + // get the decimals from the ERC20 contract or default to 18 + if (erc20Address !== ZERO) { + decimals = await getErc20Decimals(erc20Address, this.provider) + } else { + decimals = 18 + } + } + + const actualAmount = utils.toDecimal(amount, decimals) + + const transactionPromise = lockContract.expireAndRefundFor( + keyOwner, + actualAmount + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/getCancelAndRefundValueFor.js b/packages/unlock-js/src/PublicLock/previous/getCancelAndRefundValueFor.js new file mode 100644 index 00000000000..1e1c7e65bb5 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/getCancelAndRefundValueFor.js @@ -0,0 +1,23 @@ +import utils from '../../utils' +import { ZERO } from '../../constants' +import { getErc20Decimals } from '../../erc20' + +export async function getCancelAndRefundValueFor( + { lockAddress, owner, tokenAddress }, + transactionOptions = {}, + provider +) { + const lockContract = await this.getLockContract(lockAddress, provider) + const value = await lockContract.getCancelAndRefundValueFor(owner) + + let refundValue + if (tokenAddress === ZERO) { + refundValue = utils.fromWei(value, 'ether') + } else { + refundValue = await getErc20Decimals(tokenAddress, this.provider) + } + + return refundValue +} + +export default getCancelAndRefundValueFor diff --git a/packages/unlock-js/src/PublicLock/previous/getKeyExpirationByLockForOwner.js b/packages/unlock-js/src/PublicLock/previous/getKeyExpirationByLockForOwner.js new file mode 100644 index 00000000000..d52dd897cad --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/getKeyExpirationByLockForOwner.js @@ -0,0 +1,34 @@ +import { ETHERS_MAX_UINT } from '../../constants' + +/** + * Get key expiration by lock for owner + * @return Promise + */ +export default async function (lockAddress, owner, network) { + const lockContract = await this.getLockContract( + lockAddress, + this.providerForNetwork(network) + ) + + if ((await lockContract.publicLockVersion()) > 10) { + throw new Error('Only available until Lock v10') + } + + try { + const expiration = await lockContract.keyExpirationTimestampFor(owner) + if ( + expiration == + '3963877391197344453575983046348115674221700746820753546331534351508065746944' + ) { + // Handling NO_SUCH_KEY + // this portion is probably unnecessary, will need to test against the app to be sure + return 0 + } + if (expiration === ETHERS_MAX_UINT) { + return -1 + } + return parseInt(expiration, 10) + } catch (error) { + return 0 + } +} diff --git a/packages/unlock-js/src/PublicLock/previous/getLock.js b/packages/unlock-js/src/PublicLock/previous/getLock.js new file mode 100644 index 00000000000..c3262238e6d --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/getLock.js @@ -0,0 +1,11 @@ +import parseLockGetters from '../utils/parseLockGetters' + +/** + * Refresh the lock's data. + * We use the block version + * @return Promise + */ +export default async function (address, provider, options = {}) { + const update = await parseLockGetters.bind(this)(address, provider, options) + return update +} diff --git a/packages/unlock-js/src/PublicLock/previous/getTokenIdForOwner.js b/packages/unlock-js/src/PublicLock/previous/getTokenIdForOwner.js new file mode 100644 index 00000000000..fe035219922 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/getTokenIdForOwner.js @@ -0,0 +1,17 @@ +/** + * Get token id by lock for owner + * @return Promise + */ +export default async function (lockAddress, owner, network) { + const lockContract = await this.getLockContract( + lockAddress, + this.providerForNetwork(network) + ) + + try { + const tokenId = await lockContract.getTokenIdFor(owner) + return parseInt(tokenId, 10) + } catch (error) { + return 0 + } +} diff --git a/packages/unlock-js/src/PublicLock/previous/grantKey.js b/packages/unlock-js/src/PublicLock/previous/grantKey.js new file mode 100644 index 00000000000..7acbfd45eea --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/grantKey.js @@ -0,0 +1,24 @@ +import grantKeys from './grantKeys' + +export default async function ( + { lockAddress, recipient, expiration, keyManager }, + transactionOptions = {}, + callback +) { + const events = await grantKeys.bind(this)( + { + lockAddress, + recipients: [recipient], + expirations: expiration ? [expiration] : [], + keyManagers: keyManager ? [keyManager] : [], + }, + transactionOptions, + callback + ) + + if (events?.length) { + return events[0] + } + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/grantKeys.js b/packages/unlock-js/src/PublicLock/previous/grantKeys.js new file mode 100644 index 00000000000..2e9749f991c --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/grantKeys.js @@ -0,0 +1,77 @@ +import { ETHERS_MAX_UINT } from '../../constants' + +export default async function ( + { lockAddress, recipients, expirations, keyManagers }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + + if (!expirations?.length) { + // Let's get the expiration from the duration (+/- given that the transaction can take time to be mined!) + const duration = await lockContract.expirationDuration() + + if (ETHERS_MAX_UINT === duration) { + // Add equal number of expirations to recipients length + expirations = new Array(recipients.length).fill(ETHERS_MAX_UINT) + } else { + expirations = new Array(recipients.length).fill( + BigInt(Math.floor(new Date().getTime() / 1000)) + duration + ) + } + } + + if (!keyManagers?.length) { + // By default the key manager is the granter + const signer = this.signer + const manager = await signer.getAddress() + keyManagers = new Array(recipients.length).fill(manager) + } + + if (recipients.length !== expirations.length) { + throw new Error( + "Number of recipients don't match the number of expirations provided" + ) + } + + if (recipients.length !== keyManagers.length) { + throw new Error( + "Number of recipients don't match the number of keyManagers provided" + ) + } + + const transactionPromise = lockContract.grantKeys( + recipients, + expirations, + keyManagers, + transactionOptions || {} + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + + // Let's now wait for the transaction to go thru to return the token id + const receipt = await this.provider.waitForTransaction(hash) + const parser = lockContract.interface + + const transferEvents = receipt.logs + .map((log) => { + if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract + return parser.parseLog(log) + }) + .filter(({ fragment }) => fragment && fragment.name === 'Transfer') + + if (transferEvents.length) { + return transferEvents.map((item) => { + return { + id: item.args.tokenId.toString(), + owner: item.args.to.toString(), + } + }) + } + // There was no Transfer log (transaction failed?) + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/index.js b/packages/unlock-js/src/PublicLock/previous/index.js new file mode 100644 index 00000000000..7be78e081c0 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/index.js @@ -0,0 +1,57 @@ +import addKeyGranter from './addKeyGranter' +import addLockManager from './addLockManager' +import approveBeneficiary from './approveBeneficiary' +import cancelAndRefund from './cancelAndRefund' +import expireAndRefundFor from './expireAndRefundFor' +import getCancelAndRefundValueFor from './getCancelAndRefundValueFor' +import getKeyExpirationByLockForOwner from './getKeyExpirationByLockForOwner' +import getLock from './getLock' +import getTokenIdForOwner from './getTokenIdForOwner' +import grantKey from './grantKey' +import grantKeys from './grantKeys' +import initializeTemplate from './initializeTemplate' +import isKeyGranter from './isKeyGranter' +import isLockManager from './isLockManager' +import keyManagerOf from './keyManagerOf' +import renounceLockManager from './renounceLockManager' +import setBaseTokenURI from './setBaseTokenURI' +import setEventHooks from './setEventHooks' +import setKeyManagerOf from './setKeyManagerOf' +import shareKey from './shareKey' +import totalKeys from './totalKeys' +import updateKeyPrice from './updateKeyPrice' +import updateLockName from './updateLockName' +import updateLockSymbol from './updateLockSymbol' +import updateRefundPenalty from './updateRefundPenalty' +import updateTransferFee from './updateTransferFee' +import withdrawFromLock from './withdrawFromLock' + +export default { + initializeTemplate, + updateKeyPrice, + grantKey, + grantKeys, + getLock, + withdrawFromLock, + isLockManager, + isKeyGranter, + addKeyGranter, + expireAndRefundFor, + cancelAndRefund, + shareKey, + keyManagerOf, + getCancelAndRefundValueFor, + getTokenIdForOwner, + getKeyExpirationByLockForOwner, + approveBeneficiary, + totalKeys, + updateLockName, + updateLockSymbol, + setBaseTokenURI, + addLockManager, + renounceLockManager, + updateRefundPenalty, + setEventHooks, + updateTransferFee, + setKeyManagerOf, +} diff --git a/packages/unlock-js/src/PublicLock/previous/initializeTemplate.js b/packages/unlock-js/src/PublicLock/previous/initializeTemplate.js new file mode 100644 index 00000000000..915eaa9630d --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/initializeTemplate.js @@ -0,0 +1,33 @@ +import { ZERO } from '../../constants' + +/** + * Initialize a lock (will be called on the template only) + * @param {PropTypes.contract} contract + */ +export default async function ( + { templateAddress }, + transactionOptions = {}, + callback +) { + const owner = await this.signer.getAddress() + const expirationDuration = 0 + const tokenAddress = ZERO + const keyPrice = 0 + const maxNumberOfKeys = 0 + const lockName = 'Public Lock Template' + + const contract = await this.getLockContract(templateAddress) + + const initializeTransaction = await contract.initialize( + owner, + expirationDuration, + tokenAddress, + keyPrice, + maxNumberOfKeys, + lockName + ) + if (callback) { + callback(null, initializeTransaction.hash) + } + await this.provider.waitForTransaction(initializeTransaction.hash) +} diff --git a/packages/unlock-js/src/PublicLock/previous/isKeyGranter.js b/packages/unlock-js/src/PublicLock/previous/isKeyGranter.js new file mode 100644 index 00000000000..f838be21dfd --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/isKeyGranter.js @@ -0,0 +1,11 @@ +/** + * Yields true if the user is a key granter + * In this version, only the lock owner is a manager + * @param {string} lockAddress address of the lock + * @param {string} address address of the key grnater + */ +export default async function (lockAddress, address, provider) { + const lockContract = await this.getLockContract(lockAddress, provider) + + return lockContract.isKeyGranter(address) +} diff --git a/packages/unlock-js/src/PublicLock/previous/isLockManager.js b/packages/unlock-js/src/PublicLock/previous/isLockManager.js new file mode 100644 index 00000000000..d31b009944f --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/isLockManager.js @@ -0,0 +1,12 @@ +/** + * Yields true if the user is a lock manager + * In this version, only the lock owner is a manager + * @param {string} lockAddres address of the lock + * @param {string} userAddress address of the user + */ + +export default async function (lockAddres, userAddress, provider) { + const lockContract = await this.getLockContract(lockAddres, provider) + const owner = await lockContract.owner() + return owner.toLowerCase() === userAddress.toLowerCase() +} diff --git a/packages/unlock-js/src/PublicLock/previous/keyManagerOf.js b/packages/unlock-js/src/PublicLock/previous/keyManagerOf.js new file mode 100644 index 00000000000..fefdf73660a --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/keyManagerOf.js @@ -0,0 +1,9 @@ +/** + * @param {string} lockAddres address of the lock + * @param {string} tokenId address of the user + */ +export default async function (lockAddres, tokenId, provider) { + const lockContract = await this.getLockContract(lockAddres, provider) + + return lockContract.keyManagerOf(tokenId) +} diff --git a/packages/unlock-js/src/PublicLock/previous/renounceLockManager.js b/packages/unlock-js/src/PublicLock/previous/renounceLockManager.js new file mode 100644 index 00000000000..4825b53d1ff --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/renounceLockManager.js @@ -0,0 +1,23 @@ +/** + * Renounce lock manager + * @param {string} lockAddress address of the lock + */ + +export default async function ( + { lockAddress }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + const transactionPromise = lockContract.renounceLockManager() + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/setBaseTokenURI.js b/packages/unlock-js/src/PublicLock/previous/setBaseTokenURI.js new file mode 100644 index 00000000000..dbd1d94da56 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/setBaseTokenURI.js @@ -0,0 +1,23 @@ +/** + * Update the base token URI of the lock + * @param {object} params + * - {PropTypes.address} lockAddress : address of the lock for which we update the name + * - {string} baseTokenURI: the new base tokenURI that will be use by the lock + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { lockAddress, baseTokenURI }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress, this.provider) + const transactionPromise = lockContract.setBaseTokenURI(baseTokenURI) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + // Let's now wait for the keyPrice to have been changed before we return it + await this.provider.waitForTransaction(hash) + return baseTokenURI +} diff --git a/packages/unlock-js/src/PublicLock/previous/setEventHooks.js b/packages/unlock-js/src/PublicLock/previous/setEventHooks.js new file mode 100644 index 00000000000..8e8fe6bc6e8 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/setEventHooks.js @@ -0,0 +1,21 @@ +import { ZERO } from '../../constants' + +export default async function ( + { lockAddress, keyPurchase = ZERO, keyCancel = ZERO }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + + const transactionPromise = lockContract.setEventHooks(keyPurchase, keyCancel) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/setKeyManagerOf.js b/packages/unlock-js/src/PublicLock/previous/setKeyManagerOf.js new file mode 100644 index 00000000000..d315ab674c2 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/setKeyManagerOf.js @@ -0,0 +1,26 @@ +/** + * Change lock manager for a specific key + * @param {string} lockAddress address of the lock + * @param {string} managerAddress address of the user + */ + +export default async function ( + { lockAddress, managerAddress, tokenId }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + const transactionPromise = lockContract.setKeyManagerOf( + tokenId, + managerAddress + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + const tx = await this.provider.waitForTransaction(hash) + return tx +} diff --git a/packages/unlock-js/src/PublicLock/previous/shareKey.js b/packages/unlock-js/src/PublicLock/previous/shareKey.js new file mode 100644 index 00000000000..02df371822c --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/shareKey.js @@ -0,0 +1,33 @@ +export default async function ( + { lockAddress, tokenId, recipient, duration }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + if (!tokenId) { + // Let's assume transfer by seller :) + const owner = await this.signer.getAddress() + tokenId = await lockContract.getTokenIdFor(owner) + } + + if (!duration) { + const keyOwner = await lockContract.ownerOf(tokenId) + const expiration = await lockContract.keyExpirationTimestampFor(keyOwner) + duration = Math.floor(new Date().getTime() / 1000) - expiration + } + + const transactionPromise = lockContract.shareKey( + recipient, + tokenId, + duration, + transactionOptions + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + + return await this.provider.waitForTransaction(hash) +} diff --git a/packages/unlock-js/src/PublicLock/previous/totalKeys.js b/packages/unlock-js/src/PublicLock/previous/totalKeys.js new file mode 100644 index 00000000000..a64abf9168e --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/totalKeys.js @@ -0,0 +1,9 @@ +/** + * Returns the number of keys in owner's account. + * @param {string} lockAddres address of the lock + * @param {string} owner address of the user + */ +export default async function (lockAddres, owner, provider) { + const lockContract = await this.getLockContract(lockAddres, provider) + return lockContract.balanceOf(owner) +} diff --git a/packages/unlock-js/src/PublicLock/previous/updateKeyPrice.js b/packages/unlock-js/src/PublicLock/previous/updateKeyPrice.js new file mode 100644 index 00000000000..98053ffbf7c --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/updateKeyPrice.js @@ -0,0 +1,61 @@ +import utils from '../../utils' +import { ZERO } from '../../constants' +import { getErc20Decimals } from '../../erc20' + +/** + * Changes the price of keys on a given lock + * @param {object} params + * - {PropTypes.address} lockAddress : address of the lock for which we update the price + * - {string} keyPrice : new price for the lock, as a string (as wei) + * - {string} decimals : Optional number of decimals (read from contract if unset) + * - {string} erc20Address : Optional address of ERC20, to retrieve decimals (read from contract if unset) + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { lockAddress, keyPrice, decimals, erc20Address }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + + // If none is set, let's get the current ERC20 address because we need to set one + if (!erc20Address) { + erc20Address = await lockContract.tokenAddress() + } + + // Get the decimals from the contract + if (decimals == null) { + if (erc20Address !== ZERO) { + decimals = await getErc20Decimals(erc20Address, this.provider) + } else { + decimals = 18 + } + } + const actualAmount = utils.toDecimal(keyPrice, decimals) + + const transactionPromise = lockContract.updateKeyPricing( + actualAmount, + erc20Address || ZERO + ) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + + // Let's now wait for the keyPrice to have been changed before we return it + const receipt = await this.provider.waitForTransaction(hash) + const parser = lockContract.interface + + const priceChangedEvent = receipt.logs + .map((log) => { + return parser.parseLog(log) + }) + .find(({ fragment }) => fragment && fragment.name === 'PricingChanged') + if (priceChangedEvent) { + // TODO: also return contract? + return utils.fromDecimal(priceChangedEvent.args.keyPrice, decimals) + } + // There was no NewEvent log (transaction failed?) + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/updateLockName.js b/packages/unlock-js/src/PublicLock/previous/updateLockName.js new file mode 100644 index 00000000000..00aab9325c5 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/updateLockName.js @@ -0,0 +1,23 @@ +/** + * Update the name of a lock + * @param {object} params + * - {PropTypes.address} lockAddress : address of the lock for which we update the name + * - {string} name: the new name of the lock + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { lockAddress, name }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress, this.provider) + const transactionPromise = lockContract.updateLockName(name) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + // Let's now wait for the keyPrice to have been changed before we return it + await this.provider.waitForTransaction(hash) + return name +} diff --git a/packages/unlock-js/src/PublicLock/previous/updateLockSymbol.js b/packages/unlock-js/src/PublicLock/previous/updateLockSymbol.js new file mode 100644 index 00000000000..b2d0a09dd13 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/updateLockSymbol.js @@ -0,0 +1,23 @@ +/** + * Update the three-letters symbol of a lock (default to KEY) + * @param {object} params + * - {PropTypes.address} lockAddress : address of the lock for which we update the symbol + * - {string} symbol: the new symbol of the lock + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { lockAddress, symbol }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress, this.provider) + const transactionPromise = lockContract.updateLockSymbol(symbol) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + // Let's now wait for the keyPrice to have been changed before we return it + await this.provider.waitForTransaction(hash) + return symbol +} diff --git a/packages/unlock-js/src/PublicLock/previous/updateRefundPenalty.js b/packages/unlock-js/src/PublicLock/previous/updateRefundPenalty.js new file mode 100644 index 00000000000..606a0e50398 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/updateRefundPenalty.js @@ -0,0 +1,28 @@ +/** + * Update refund penalty + * @param {object} params + * - {PropTypes.lockAddress} lockAddress : address of the lock for which we update refund penalty + * - {PropTypes.freeTrialLength} freeTrialLength value + * - {PropTypes.refundPenaltyBasisPoints} refundPenaltyBasisPoints value + * @param {function} transactionOptions + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { lockAddress, freeTrialLength, refundPenaltyBasisPoints }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress, this.provider) + const transactionPromise = lockContract.updateRefundPenalty( + freeTrialLength, + refundPenaltyBasisPoints + ) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + // Let's now wait for the keyPrice to have been changed before we return it + await this.provider.waitForTransaction(hash) + return name +} diff --git a/packages/unlock-js/src/PublicLock/previous/updateTransferFee.js b/packages/unlock-js/src/PublicLock/previous/updateTransferFee.js new file mode 100644 index 00000000000..8a74edbdff5 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/updateTransferFee.js @@ -0,0 +1,20 @@ +export default async function ( + { lockAddress, transferFeeBasisPoints }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + const transactionPromise = lockContract.updateTransferFee( + transferFeeBasisPoints + ) + + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash) + } + + await this.provider.waitForTransaction(hash) + + return null +} diff --git a/packages/unlock-js/src/PublicLock/previous/withdrawFromLock.js b/packages/unlock-js/src/PublicLock/previous/withdrawFromLock.js new file mode 100644 index 00000000000..488ca88c0f9 --- /dev/null +++ b/packages/unlock-js/src/PublicLock/previous/withdrawFromLock.js @@ -0,0 +1,59 @@ +import utils from '../../utils' +import { ZERO } from '../../constants' +import { getErc20Decimals } from '../../erc20' + +/** + * Triggers a transaction to withdraw funds from the lock and assign them to the owner. + * By default (amount=0), this withdraws all funds. + * @param {PropTypes.address} lockAddress + * @param {string} amount + * @param {number} erc20Address + * @param {number} decimals + * @param {function} callback invoked with the transaction hash + */ +export default async function ( + { erc20Address, lockAddress, amount = '0', decimals }, + transactionOptions = {}, + callback +) { + const lockContract = await this.getLockContract(lockAddress) + + if (!erc20Address || erc20Address !== ZERO) { + erc20Address = await lockContract.tokenAddress() + } + + // decimals could be 0! + if (decimals == null) { + // get the decimals from the ERC20 contract or default to 18 + if (erc20Address !== ZERO) { + decimals = await getErc20Decimals(erc20Address, this.provider) + } else { + decimals = 18 + } + } + + const actualAmount = utils.toDecimal(amount, decimals) + + const transactionPromise = lockContract.withdraw(erc20Address, actualAmount) + const hash = await this._handleMethodCall(transactionPromise) + + if (callback) { + callback(null, hash, await transactionPromise) + } + + // Let's now wait for the funds to have been withdrawn + const receipt = await this.provider.waitForTransaction(hash) + + const parser = lockContract.interface + const withdrawalEvent = receipt.logs + .map((log) => { + if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract + return parser.parseLog(log) + }) + .find(({ fragment }) => fragment && fragment.name === 'Withdrawal') + if (withdrawalEvent) { + return utils.fromWei(withdrawalEvent.args.amount.toString(), 'ether') + } + // There was no Withdrawal log (transaction failed?) + return null +} diff --git a/packages/unlock-js/src/PublicLock/v9/index.js b/packages/unlock-js/src/PublicLock/v9/index.js index 92aa585345c..f9bc26a2b31 100644 --- a/packages/unlock-js/src/PublicLock/v9/index.js +++ b/packages/unlock-js/src/PublicLock/v9/index.js @@ -6,36 +6,36 @@ import setExpirationDuration from './setExpirationDuration' import setEventHooks from './setEventHooks' import transferFrom from './transferFrom' import setGasRefundValue from './setGasRefundValue' -import v8 from '../v8' +import previous from '../previous' const { + addKeyGranter, + addLockManager, + approveBeneficiary, + cancelAndRefund, + expireAndRefundFor, + getCancelAndRefundValueFor, + getKeyExpirationByLockForOwner, + getLock, + getTokenIdForOwner, grantKey, grantKeys, - updateKeyPrice, - withdrawFromLock, initializeTemplate, - isLockManager, isKeyGranter, - addKeyGranter, - expireAndRefundFor, - cancelAndRefund, - shareKey, - getLock, + isLockManager, keyManagerOf, - getCancelAndRefundValueFor, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - approveBeneficiary, + renounceLockManager, + setBaseTokenURI, + setKeyManagerOf, + shareKey, totalKeys, + updateKeyPrice, updateLockName, updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, updateRefundPenalty, updateTransferFee, - setKeyManagerOf, -} = v8 + withdrawFromLock, +} = previous export default { version: 'v9', From d25062594e62afec296912e236bcdb4299f8e8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 14:10:07 +0200 Subject: [PATCH 26/27] unlokjs remove fixtures --- .../src/__tests__/helpers/fixtures/locks.js | 92 ------------------- 1 file changed, 92 deletions(-) diff --git a/packages/unlock-js/src/__tests__/helpers/fixtures/locks.js b/packages/unlock-js/src/__tests__/helpers/fixtures/locks.js index e098942e657..da0139f65d8 100644 --- a/packages/unlock-js/src/__tests__/helpers/fixtures/locks.js +++ b/packages/unlock-js/src/__tests__/helpers/fixtures/locks.js @@ -5,98 +5,6 @@ const THIRTY_DAYS = 60 * 60 * 24 * 30 const TEN_DAYS = 60 * 60 * 24 * 10 export default { - v4: [ - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: 100, - name: 'My Lock', - isERC20: false, - }, - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: UNLIMITED_KEYS_COUNT, - name: 'Unlimited Keys lock', - isERC20: false, - }, - { - expirationDuration: TEN_DAYS, - keyPrice: '1', - maxNumberOfKeys: 100, - name: 'ERC20 lock', - isERC20: true, - }, - ], - v6: [ - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: 100, - name: 'My Lock', - isERC20: false, - }, - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: UNLIMITED_KEYS_COUNT, - name: 'Unlimited Keys lock', - isERC20: false, - }, - { - expirationDuration: TEN_DAYS, - keyPrice: '1', - maxNumberOfKeys: 100, - name: 'ERC20 lock', - isERC20: true, - }, - ], - v7: [ - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: 100, - name: 'My Lock', - isERC20: false, - }, - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: UNLIMITED_KEYS_COUNT, - name: 'Unlimited Keys lock', - isERC20: false, - }, - { - expirationDuration: TEN_DAYS, - keyPrice: '1', - maxNumberOfKeys: 100, - name: 'ERC20 lock', - isERC20: true, - }, - ], - v8: [ - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: 100, - name: 'My Lock', - isERC20: false, - }, - { - expirationDuration: THIRTY_DAYS, - keyPrice: '0.1', - maxNumberOfKeys: UNLIMITED_KEYS_COUNT, - name: 'Unlimited Keys lock', - isERC20: false, - }, - { - expirationDuration: TEN_DAYS, - keyPrice: '1', - maxNumberOfKeys: 100, - name: 'ERC20 lock', - isERC20: true, - }, - ], v9: [ { expirationDuration: THIRTY_DAYS, From c4f31a6dd2686d5e155dd135bed96b5a140880f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renaud?= Date: Fri, 23 Aug 2024 14:09:40 +0200 Subject: [PATCH 27/27] unlockjs remove versions --- packages/unlock-js/src/PublicLock/index.ts | 8 - .../src/PublicLock/v4/cancelAndRefund.js | 18 -- .../v4/getKeyExpirationByLockForOwner.js | 34 ---- .../unlock-js/src/PublicLock/v4/getLock.js | 11 -- .../PublicLock/v4/getPurchaseKeysArguments.js | 55 ------ .../src/PublicLock/v4/getTokenIdForOwner.js | 17 -- .../unlock-js/src/PublicLock/v4/grantKey.js | 23 --- .../unlock-js/src/PublicLock/v4/grantKeys.js | 59 ------- packages/unlock-js/src/PublicLock/v4/index.js | 41 ----- .../src/PublicLock/v4/isLockManager.js | 13 -- .../src/PublicLock/v4/purchaseKey.js | 95 ----------- .../src/PublicLock/v4/purchaseKeys.js | 24 --- .../src/PublicLock/v4/setBaseTokenURI.js | 23 --- .../unlock-js/src/PublicLock/v4/totalKeys.js | 9 - .../src/PublicLock/v4/updateKeyPrice.js | 60 ------- .../src/PublicLock/v4/updateLockName.js | 23 --- .../src/PublicLock/v4/updateLockSymbol.js | 23 --- .../src/PublicLock/v4/updateRefundPenalty.js | 28 ---- .../src/PublicLock/v4/withdrawFromLock.js | 42 ----- .../src/PublicLock/v6/addLockManager.js | 24 --- .../src/PublicLock/v6/cancelAndRefund.js | 18 -- .../unlock-js/src/PublicLock/v6/getLock.js | 11 -- .../unlock-js/src/PublicLock/v6/grantKey.js | 23 --- .../unlock-js/src/PublicLock/v6/grantKeys.js | 58 ------- packages/unlock-js/src/PublicLock/v6/index.js | 54 ------ .../src/PublicLock/v6/initializeTemplate.js | 33 ---- .../src/PublicLock/v6/isLockManager.js | 12 -- .../src/PublicLock/v6/purchaseKey.js | 156 ------------------ .../src/PublicLock/v6/purchaseKeys.js | 24 --- .../src/PublicLock/v6/renounceLockManager.js | 23 --- .../unlock-js/src/PublicLock/v6/shareKey.js | 33 ---- .../src/PublicLock/v6/updateKeyPrice.js | 61 ------- .../src/PublicLock/v6/updateTransferFee.js | 20 --- .../src/PublicLock/v6/withdrawFromLock.js | 59 ------- .../src/PublicLock/v7/addKeyGranter.js | 17 -- .../src/PublicLock/v7/cancelAndRefund.js | 24 --- .../src/PublicLock/v7/expireAndRefundFor.js | 41 ----- .../v7/getCancelAndRefundValueFor.js | 23 --- .../unlock-js/src/PublicLock/v7/grantKey.js | 24 --- .../unlock-js/src/PublicLock/v7/grantKeys.js | 77 --------- packages/unlock-js/src/PublicLock/v7/index.js | 67 -------- .../src/PublicLock/v7/isKeyGranter.js | 11 -- .../src/PublicLock/v7/isLockManager.js | 11 -- .../src/PublicLock/v7/keyManagerOf.js | 9 - .../src/PublicLock/v7/setEventHooks.js | 21 --- .../src/PublicLock/v7/setKeyManagerOf.js | 26 --- .../src/PublicLock/v8/approveBeneficiary.js | 44 ----- packages/unlock-js/src/PublicLock/v8/index.js | 70 -------- .../src/PublicLock/v8/keyManagerOf.js | 9 - packages/unlock-js/src/Unlock/index.ts | 10 -- .../unlock-js/src/Unlock/v4/createLock.js | 57 ------- packages/unlock-js/src/Unlock/v4/index.js | 9 - .../unlock-js/src/Unlock/v6/createLock.js | 60 ------- packages/unlock-js/src/Unlock/v6/index.js | 9 - .../unlock-js/src/Unlock/v7/createLock.js | 60 ------- packages/unlock-js/src/Unlock/v7/index.js | 9 - .../unlock-js/src/Unlock/v8/createLock.js | 60 ------- packages/unlock-js/src/Unlock/v8/index.js | 9 - packages/unlock-js/src/Unlock/v9/index.js | 12 -- .../walletServiceIntegration.test.js | 9 +- 60 files changed, 2 insertions(+), 1991 deletions(-) delete mode 100644 packages/unlock-js/src/PublicLock/v4/cancelAndRefund.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/getKeyExpirationByLockForOwner.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/getLock.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/getPurchaseKeysArguments.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/getTokenIdForOwner.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/grantKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/grantKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/index.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/isLockManager.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/purchaseKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/purchaseKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/setBaseTokenURI.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/totalKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/updateKeyPrice.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/updateLockName.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/updateLockSymbol.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/updateRefundPenalty.js delete mode 100644 packages/unlock-js/src/PublicLock/v4/withdrawFromLock.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/addLockManager.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/cancelAndRefund.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/getLock.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/grantKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/grantKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/index.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/initializeTemplate.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/isLockManager.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/purchaseKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/purchaseKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/renounceLockManager.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/shareKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/updateKeyPrice.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/updateTransferFee.js delete mode 100644 packages/unlock-js/src/PublicLock/v6/withdrawFromLock.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/addKeyGranter.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/cancelAndRefund.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/expireAndRefundFor.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/getCancelAndRefundValueFor.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/grantKey.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/grantKeys.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/index.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/isKeyGranter.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/isLockManager.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/keyManagerOf.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/setEventHooks.js delete mode 100644 packages/unlock-js/src/PublicLock/v7/setKeyManagerOf.js delete mode 100644 packages/unlock-js/src/PublicLock/v8/approveBeneficiary.js delete mode 100644 packages/unlock-js/src/PublicLock/v8/index.js delete mode 100644 packages/unlock-js/src/PublicLock/v8/keyManagerOf.js delete mode 100644 packages/unlock-js/src/Unlock/v4/createLock.js delete mode 100644 packages/unlock-js/src/Unlock/v4/index.js delete mode 100644 packages/unlock-js/src/Unlock/v6/createLock.js delete mode 100644 packages/unlock-js/src/Unlock/v6/index.js delete mode 100644 packages/unlock-js/src/Unlock/v7/createLock.js delete mode 100644 packages/unlock-js/src/Unlock/v7/index.js delete mode 100644 packages/unlock-js/src/Unlock/v8/createLock.js delete mode 100644 packages/unlock-js/src/Unlock/v8/index.js delete mode 100644 packages/unlock-js/src/Unlock/v9/index.js diff --git a/packages/unlock-js/src/PublicLock/index.ts b/packages/unlock-js/src/PublicLock/index.ts index a1f3a882a6d..bc98c0fc69e 100644 --- a/packages/unlock-js/src/PublicLock/index.ts +++ b/packages/unlock-js/src/PublicLock/index.ts @@ -1,7 +1,3 @@ -import v4 from './v4' -import v6 from './v6' -import v7 from './v7' -import v8 from './v8' import v9 from './v9' import v10 from './v10' import v11 from './v11' @@ -10,10 +6,6 @@ import v13 from './v13' import v14 from './v14' export default { - v4, - v6, - v7, - v8, v9, v10, v11, diff --git a/packages/unlock-js/src/PublicLock/v4/cancelAndRefund.js b/packages/unlock-js/src/PublicLock/v4/cancelAndRefund.js deleted file mode 100644 index 565783f34ed..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/cancelAndRefund.js +++ /dev/null @@ -1,18 +0,0 @@ -export default async function ( - { lockAddress }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.cancelAndRefund() - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v4/getKeyExpirationByLockForOwner.js b/packages/unlock-js/src/PublicLock/v4/getKeyExpirationByLockForOwner.js deleted file mode 100644 index d52dd897cad..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/getKeyExpirationByLockForOwner.js +++ /dev/null @@ -1,34 +0,0 @@ -import { ETHERS_MAX_UINT } from '../../constants' - -/** - * Get key expiration by lock for owner - * @return Promise - */ -export default async function (lockAddress, owner, network) { - const lockContract = await this.getLockContract( - lockAddress, - this.providerForNetwork(network) - ) - - if ((await lockContract.publicLockVersion()) > 10) { - throw new Error('Only available until Lock v10') - } - - try { - const expiration = await lockContract.keyExpirationTimestampFor(owner) - if ( - expiration == - '3963877391197344453575983046348115674221700746820753546331534351508065746944' - ) { - // Handling NO_SUCH_KEY - // this portion is probably unnecessary, will need to test against the app to be sure - return 0 - } - if (expiration === ETHERS_MAX_UINT) { - return -1 - } - return parseInt(expiration, 10) - } catch (error) { - return 0 - } -} diff --git a/packages/unlock-js/src/PublicLock/v4/getLock.js b/packages/unlock-js/src/PublicLock/v4/getLock.js deleted file mode 100644 index c3262238e6d..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/getLock.js +++ /dev/null @@ -1,11 +0,0 @@ -import parseLockGetters from '../utils/parseLockGetters' - -/** - * Refresh the lock's data. - * We use the block version - * @return Promise - */ -export default async function (address, provider, options = {}) { - const update = await parseLockGetters.bind(this)(address, provider, options) - return update -} diff --git a/packages/unlock-js/src/PublicLock/v4/getPurchaseKeysArguments.js b/packages/unlock-js/src/PublicLock/v4/getPurchaseKeysArguments.js deleted file mode 100644 index 0d8c3ea4726..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/getPurchaseKeysArguments.js +++ /dev/null @@ -1,55 +0,0 @@ -import formatKeyPrice from '../utils/formatKeyPrice' -import utils from '../../utils' - -export default async function getPurchaseKeysArguments({ - lockAddress, - erc20Address, - decimals, - owners = [], - keyManagers = [], - keyPrices = [], - referrers = [], - data = '0x', -}) { - // If erc20Address was not provided, get it - const lockContract = await this.getLockContract(lockAddress) - erc20Address = await lockContract.tokenAddress() - // if ERC20 is set we approve the entire amount - // We might not have the keyPrice, in which case, we need to retrieve from the the lock! - const getPrice = async (price) => - !price - ? await lockContract.keyPrice() - : await formatKeyPrice(price, erc20Address, decimals, this.provider) - - const prices = await Promise.all( - (keyPrices.length === owners.length - ? keyPrices - : Array(owners.length).fill(null) - ).map((kp) => getPrice(kp)) - ) - - // calculate total price for all keys - const totalPrice = prices.reduce( - (total, kp) => total + kp, - utils.bigNumberify(0) - ) - - const items = owners.map((owner, i) => { - return { - lockAddress, - owner, - keyManager: keyManagers[i], - keyPrice: keyPrices[i], - referrer: referrers[i], - data: data[i], - erc20Address, - decimals, - } - }) - return { - items, - totalPrice, - erc20Address, - totalAmountToApprove: totalPrice, - } -} diff --git a/packages/unlock-js/src/PublicLock/v4/getTokenIdForOwner.js b/packages/unlock-js/src/PublicLock/v4/getTokenIdForOwner.js deleted file mode 100644 index fe035219922..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/getTokenIdForOwner.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Get token id by lock for owner - * @return Promise - */ -export default async function (lockAddress, owner, network) { - const lockContract = await this.getLockContract( - lockAddress, - this.providerForNetwork(network) - ) - - try { - const tokenId = await lockContract.getTokenIdFor(owner) - return parseInt(tokenId, 10) - } catch (error) { - return 0 - } -} diff --git a/packages/unlock-js/src/PublicLock/v4/grantKey.js b/packages/unlock-js/src/PublicLock/v4/grantKey.js deleted file mode 100644 index 2e1cbfdca57..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/grantKey.js +++ /dev/null @@ -1,23 +0,0 @@ -import grantKeys from './grantKeys' - -export default async function ( - { lockAddress, recipient, expiration }, - transactionOptions = {}, - callback -) { - const events = await grantKeys.bind(this)( - { - lockAddress, - recipients: [recipient], - expirations: expiration ? [expiration] : [], - }, - transactionOptions, - callback - ) - - if (events?.length) { - return events[0] - } - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v4/grantKeys.js b/packages/unlock-js/src/PublicLock/v4/grantKeys.js deleted file mode 100644 index f78f1ef9aa8..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/grantKeys.js +++ /dev/null @@ -1,59 +0,0 @@ -import { ETHERS_MAX_UINT } from '../../constants' - -export default async function ( - { lockAddress, recipients, expirations }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!expirations?.length) { - // Let's get the expiration from the duration (+/- given that the transaction can take time to be mined!) - const duration = await lockContract.expirationDuration() - - if (ETHERS_MAX_UINT === duration) { - // Add equal number of expirations to recipients length - expirations = new Array(recipients.length).fill(ETHERS_MAX_UINT) - } else { - expirations = new Array(recipients.length).fill( - BigInt(Math.floor(new Date().getTime() / 1000)) + duration - ) - } - } - - if (recipients.length !== expirations.length) { - throw new Error( - "Number of recipients don't match the number of expirations provided" - ) - } - - const grantKeysOptions = {} - const transactionPromise = lockContract['grantKeys(address[],uint256[])']( - recipients, - expirations, - grantKeysOptions - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the transaction to go thru to return the token id - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - - const transferEvents = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .filter(({ fragment }) => fragment && fragment.name === 'Transfer') - - if (transferEvents.length) { - return transferEvents.map((item) => item.args._tokenId.toString()) - } - // There was no Transfer log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v4/index.js b/packages/unlock-js/src/PublicLock/v4/index.js deleted file mode 100644 index b7f88bfb939..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/index.js +++ /dev/null @@ -1,41 +0,0 @@ -import abis from '../../abis' -import purchaseKey from './purchaseKey' -import purchaseKeys from './purchaseKeys' -import grantKey from './grantKey' -import grantKeys from './grantKeys' -import updateKeyPrice from './updateKeyPrice' -import withdrawFromLock from './withdrawFromLock' -import isLockManager from './isLockManager' -import cancelAndRefund from './cancelAndRefund' -import getLock from './getLock' -import getTokenIdForOwner from './getTokenIdForOwner' -import getKeyExpirationByLockForOwner from './getKeyExpirationByLockForOwner' -import totalKeys from './totalKeys' -import updateLockName from './updateLockName' -import updateLockSymbol from './updateLockSymbol' -import setBaseTokenURI from './setBaseTokenURI' -import updateRefundPenalty from './updateRefundPenalty' -import getPurchaseKeysArguments from './getPurchaseKeysArguments' - -export default { - getPurchaseKeysArguments, - purchaseKey, - purchaseKeys, - grantKey, - grantKeys, - updateKeyPrice, - getLock, - withdrawFromLock, - isLockManager, - version: 'v4', - Unlock: abis.Unlock.v4, - PublicLock: abis.PublicLock.v4, - cancelAndRefund, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - updateRefundPenalty, -} diff --git a/packages/unlock-js/src/PublicLock/v4/isLockManager.js b/packages/unlock-js/src/PublicLock/v4/isLockManager.js deleted file mode 100644 index 0bf6f31b3cf..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/isLockManager.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Yields true if the user is a lock manager - * In this version, only the lock owner is a manager - * @param {string} lockAddres address of the lock - * @param {string} userAddress address of the user - */ -export default async function (lockAddres, userAddress, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - - const owner = await lockContract.owner() - - return owner.toLowerCase() === userAddress.toLowerCase() -} diff --git a/packages/unlock-js/src/PublicLock/v4/purchaseKey.js b/packages/unlock-js/src/PublicLock/v4/purchaseKey.js deleted file mode 100644 index b0369584047..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/purchaseKey.js +++ /dev/null @@ -1,95 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' -import approveAllowance from '../utils/approveAllowance' - -/** - * Purchase key function. This implementation requires the following - * @param {object} params: - * - {PropTypes.address} lockAddress - * - {PropTypes.address} owner - * - {string} keyPrice - * - {PropTypes.address} erc20Address - * - {number} decimals - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, owner, keyPrice, erc20Address, decimals }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!owner) { - owner = await this.signer.getAddress() - } - if (!erc20Address || erc20Address !== ZERO) { - erc20Address = await lockContract.tokenAddress() - } - let actualAmount - - // decimals could be 0! - if (!keyPrice) { - // We might not have the keyPrice, in which case, we need to retrieve from the the lock! - actualAmount = await lockContract.keyPrice() - } else if (decimals == null) { - // get the decimals from the ERC20 contract or default to 18 - if (erc20Address && erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - actualAmount = utils.toDecimal(keyPrice, decimals) - } - - const callData = lockContract.interface.encodeFunctionData('purchaseFor', [ - owner, - ]) - - // tx options - if (!erc20Address || erc20Address === ZERO) { - transactionOptions.value = actualAmount - } - - // If the lock is priced in ERC20, we need to approve the transfer - const approvalOptions = { - erc20Address, - address: lockAddress, - totalAmountToApprove: actualAmount, - } - - // Only ask for approval if the lock is priced in ERC20 - if (approvalOptions.erc20Address && approvalOptions.erc20Address !== ZERO) { - await approveAllowance.bind(this)(approvalOptions) - } - - const transactionPromise = lockContract.purchaseFor(owner, transactionOptions) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the transaction to go thru to return the token id - const receipt = await this.provider.waitForTransaction(hash) - - if (receipt.status === 0) { - throw new Error('Transaction failed') - } - - const parser = lockContract.interface - - const transferEvent = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .find(({ fragment }) => fragment && fragment.name === 'Transfer') - - if (transferEvent) { - return transferEvent.args._tokenId.toString() - } - // There was no Transfer log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v4/purchaseKeys.js b/packages/unlock-js/src/PublicLock/v4/purchaseKeys.js deleted file mode 100644 index 33e1ea37623..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/purchaseKeys.js +++ /dev/null @@ -1,24 +0,0 @@ -import multiplePurchaseWrapper from '../utils/multiplePurchaseWrapper' -import purchaseKey from './purchaseKey' - -/** - * Purchase key function. This implementation requires the followin - * @param {object} params: - * - {PropTypes.arrayOf(PropTypes.address)} lockAddress - * - {PropTypes.arrayOf(PropTypes.address)} owners - * - {PropTypes.arrayOf(string)} keyPrices - * - {PropTypes.address} erc20Address - * - {number} decimals - * - {PropTypes.arrayOf(PropTypes.address)} referrers (address which will receive UDT - if applicable) - * - {PropTypes.arrayOf(PropTypes.array[bytes])} _data (array of array of bytes, not used in transaction but can be used by hooks) - * @param {function} callback invoked with the transaction hash - * */ - -export default async function (params, transactionOptions = {}, callback) { - return await multiplePurchaseWrapper.bind(this)( - purchaseKey, - params, - transactionOptions, - callback - ) -} diff --git a/packages/unlock-js/src/PublicLock/v4/setBaseTokenURI.js b/packages/unlock-js/src/PublicLock/v4/setBaseTokenURI.js deleted file mode 100644 index dbd1d94da56..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/setBaseTokenURI.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Update the base token URI of the lock - * @param {object} params - * - {PropTypes.address} lockAddress : address of the lock for which we update the name - * - {string} baseTokenURI: the new base tokenURI that will be use by the lock - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, baseTokenURI }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress, this.provider) - const transactionPromise = lockContract.setBaseTokenURI(baseTokenURI) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - // Let's now wait for the keyPrice to have been changed before we return it - await this.provider.waitForTransaction(hash) - return baseTokenURI -} diff --git a/packages/unlock-js/src/PublicLock/v4/totalKeys.js b/packages/unlock-js/src/PublicLock/v4/totalKeys.js deleted file mode 100644 index a64abf9168e..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/totalKeys.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Returns the number of keys in owner's account. - * @param {string} lockAddres address of the lock - * @param {string} owner address of the user - */ -export default async function (lockAddres, owner, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - return lockContract.balanceOf(owner) -} diff --git a/packages/unlock-js/src/PublicLock/v4/updateKeyPrice.js b/packages/unlock-js/src/PublicLock/v4/updateKeyPrice.js deleted file mode 100644 index 89914413456..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/updateKeyPrice.js +++ /dev/null @@ -1,60 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -/** - * Changes the price of keys on a given lock - * @param {object} params - * - {PropTypes.address} lockAddress : address of the lock for which we update the price - * - {string} keyPrice : new price for the lock, as a string (as wei) - * - {string} decimals : Optional number of decimals (read from contract if unset) - * - {string} erc20Address : Optional address of ERC20, to retrieve decimals (read from contract if unset) - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, keyPrice, decimals, erc20Address }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (decimals == null) { - // Get the decimals address from the contract - if (!erc20Address) { - erc20Address = await lockContract.tokenAddress() - } - - if (erc20Address && erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - } - const actualAmount = utils.toDecimal(keyPrice, decimals) - - const transactionPromise = - lockContract['updateKeyPrice(uint256)'](actualAmount) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the keyPrice to have been changed before we return it - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - - const priceChangedEvent = receipt.logs - .map((log) => { - return parser.parseLog(log) - }) - .filter( - ({ fragment }) => - fragment && fragment.signature === 'PriceChanged(uint256,uint256)' - )[0] - if (priceChangedEvent) { - return utils.fromDecimal(priceChangedEvent.args.keyPrice, decimals) - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v4/updateLockName.js b/packages/unlock-js/src/PublicLock/v4/updateLockName.js deleted file mode 100644 index 00aab9325c5..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/updateLockName.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Update the name of a lock - * @param {object} params - * - {PropTypes.address} lockAddress : address of the lock for which we update the name - * - {string} name: the new name of the lock - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, name }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress, this.provider) - const transactionPromise = lockContract.updateLockName(name) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - // Let's now wait for the keyPrice to have been changed before we return it - await this.provider.waitForTransaction(hash) - return name -} diff --git a/packages/unlock-js/src/PublicLock/v4/updateLockSymbol.js b/packages/unlock-js/src/PublicLock/v4/updateLockSymbol.js deleted file mode 100644 index b2d0a09dd13..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/updateLockSymbol.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Update the three-letters symbol of a lock (default to KEY) - * @param {object} params - * - {PropTypes.address} lockAddress : address of the lock for which we update the symbol - * - {string} symbol: the new symbol of the lock - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, symbol }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress, this.provider) - const transactionPromise = lockContract.updateLockSymbol(symbol) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - // Let's now wait for the keyPrice to have been changed before we return it - await this.provider.waitForTransaction(hash) - return symbol -} diff --git a/packages/unlock-js/src/PublicLock/v4/updateRefundPenalty.js b/packages/unlock-js/src/PublicLock/v4/updateRefundPenalty.js deleted file mode 100644 index 606a0e50398..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/updateRefundPenalty.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Update refund penalty - * @param {object} params - * - {PropTypes.lockAddress} lockAddress : address of the lock for which we update refund penalty - * - {PropTypes.freeTrialLength} freeTrialLength value - * - {PropTypes.refundPenaltyBasisPoints} refundPenaltyBasisPoints value - * @param {function} transactionOptions - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, freeTrialLength, refundPenaltyBasisPoints }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress, this.provider) - const transactionPromise = lockContract.updateRefundPenalty( - freeTrialLength, - refundPenaltyBasisPoints - ) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - // Let's now wait for the keyPrice to have been changed before we return it - await this.provider.waitForTransaction(hash) - return name -} diff --git a/packages/unlock-js/src/PublicLock/v4/withdrawFromLock.js b/packages/unlock-js/src/PublicLock/v4/withdrawFromLock.js deleted file mode 100644 index db8655dded5..00000000000 --- a/packages/unlock-js/src/PublicLock/v4/withdrawFromLock.js +++ /dev/null @@ -1,42 +0,0 @@ -import utils from '../../utils' - -/** - * Triggers a transaction to withdraw funds from the lock and assign them to the owner. - * By default (amount=0), this withdraws all funds. - * @param {PropTypes.address} lockAddress - * @param {string} amount - * @param {number} decimals - * TODO: get the decimal from the ERC20 contract - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, amount = '0', decimals = 18 }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - const actualAmount = utils.toDecimal(amount, decimals) - - const transactionPromise = lockContract['withdraw(uint256)'](actualAmount) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the funds to have been withdrawn - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - const withdrawalEvent = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .find(({ fragment }) => fragment && fragment.name === 'Withdrawal') - if (withdrawalEvent) { - return utils.fromWei(withdrawalEvent.args.amount.toString(), 'ether') - } - // There was no Withdrawal log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/addLockManager.js b/packages/unlock-js/src/PublicLock/v6/addLockManager.js deleted file mode 100644 index d5eb853e1b2..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/addLockManager.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Add lock manager to Contract - * @param {string} lockAddress address of the lock - * @param {string} userAddress address of the user - */ - -export default async function ( - { lockAddress, userAddress }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.addLockManager(userAddress) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/cancelAndRefund.js b/packages/unlock-js/src/PublicLock/v6/cancelAndRefund.js deleted file mode 100644 index 565783f34ed..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/cancelAndRefund.js +++ /dev/null @@ -1,18 +0,0 @@ -export default async function ( - { lockAddress }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.cancelAndRefund() - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/getLock.js b/packages/unlock-js/src/PublicLock/v6/getLock.js deleted file mode 100644 index c3262238e6d..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/getLock.js +++ /dev/null @@ -1,11 +0,0 @@ -import parseLockGetters from '../utils/parseLockGetters' - -/** - * Refresh the lock's data. - * We use the block version - * @return Promise - */ -export default async function (address, provider, options = {}) { - const update = await parseLockGetters.bind(this)(address, provider, options) - return update -} diff --git a/packages/unlock-js/src/PublicLock/v6/grantKey.js b/packages/unlock-js/src/PublicLock/v6/grantKey.js deleted file mode 100644 index 2e1cbfdca57..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/grantKey.js +++ /dev/null @@ -1,23 +0,0 @@ -import grantKeys from './grantKeys' - -export default async function ( - { lockAddress, recipient, expiration }, - transactionOptions = {}, - callback -) { - const events = await grantKeys.bind(this)( - { - lockAddress, - recipients: [recipient], - expirations: expiration ? [expiration] : [], - }, - transactionOptions, - callback - ) - - if (events?.length) { - return events[0] - } - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/grantKeys.js b/packages/unlock-js/src/PublicLock/v6/grantKeys.js deleted file mode 100644 index ed6e9bc9792..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/grantKeys.js +++ /dev/null @@ -1,58 +0,0 @@ -import { ETHERS_MAX_UINT } from '../../constants' - -export default async function ( - { lockAddress, recipients, expirations }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!expirations?.length) { - // Let's get the expiration from the duration (+/- given that the transaction can take time to be mined!) - const duration = await lockContract.expirationDuration() - - if (ETHERS_MAX_UINT === duration) { - // Add equal number of expirations to recipients length - expirations = new Array(recipients.length).fill(ETHERS_MAX_UINT) - } else { - expirations = new Array(recipients.length).fill( - BigInt(Math.floor(new Date().getTime() / 1000)) + duration - ) - } - } - - if (recipients.length !== expirations.length) { - throw new Error( - "Number of recipients don't match the number of expirations provided" - ) - } - - const transactionPromise = lockContract.grantKeys( - recipients, - expirations, - transactionOptions || {} - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the transaction to go thru to return the token id - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - - const transferEvents = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .filter(({ fragment }) => fragment && fragment.name === 'Transfer') - - if (transferEvents.length) { - return transferEvents.map((item) => item.args.tokenId.toString()) - } - // There was no Transfer log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/index.js b/packages/unlock-js/src/PublicLock/v6/index.js deleted file mode 100644 index 752f1508ec9..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/index.js +++ /dev/null @@ -1,54 +0,0 @@ -import abis from '../../abis' -import purchaseKey from './purchaseKey' -import purchaseKeys from './purchaseKeys' -import grantKey from './grantKey' -import grantKeys from './grantKeys' -import updateKeyPrice from './updateKeyPrice' -import withdrawFromLock from './withdrawFromLock' -import initializeTemplate from './initializeTemplate' -import isLockManager from './isLockManager' -import cancelAndRefund from './cancelAndRefund' -import shareKey from './shareKey' -import getLock from './getLock' -import addLockManager from './addLockManager' -import renounceLockManager from './renounceLockManager' -import updateTransferFee from './updateTransferFee' - -import v4 from '../v4' - -const { - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - setBaseTokenURI, - updateLockName, - updateLockSymbol, - updateRefundPenalty, -} = v4 - -export default { - version: 'v6', - Unlock: abis.Unlock.v6, - PublicLock: abis.PublicLock.v6, - initializeTemplate, - updateKeyPrice, - purchaseKey, - purchaseKeys, - getLock, - grantKey, - grantKeys, - withdrawFromLock, - isLockManager, - cancelAndRefund, - shareKey, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, - updateRefundPenalty, - updateTransferFee, -} diff --git a/packages/unlock-js/src/PublicLock/v6/initializeTemplate.js b/packages/unlock-js/src/PublicLock/v6/initializeTemplate.js deleted file mode 100644 index 915eaa9630d..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/initializeTemplate.js +++ /dev/null @@ -1,33 +0,0 @@ -import { ZERO } from '../../constants' - -/** - * Initialize a lock (will be called on the template only) - * @param {PropTypes.contract} contract - */ -export default async function ( - { templateAddress }, - transactionOptions = {}, - callback -) { - const owner = await this.signer.getAddress() - const expirationDuration = 0 - const tokenAddress = ZERO - const keyPrice = 0 - const maxNumberOfKeys = 0 - const lockName = 'Public Lock Template' - - const contract = await this.getLockContract(templateAddress) - - const initializeTransaction = await contract.initialize( - owner, - expirationDuration, - tokenAddress, - keyPrice, - maxNumberOfKeys, - lockName - ) - if (callback) { - callback(null, initializeTransaction.hash) - } - await this.provider.waitForTransaction(initializeTransaction.hash) -} diff --git a/packages/unlock-js/src/PublicLock/v6/isLockManager.js b/packages/unlock-js/src/PublicLock/v6/isLockManager.js deleted file mode 100644 index d31b009944f..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/isLockManager.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Yields true if the user is a lock manager - * In this version, only the lock owner is a manager - * @param {string} lockAddres address of the lock - * @param {string} userAddress address of the user - */ - -export default async function (lockAddres, userAddress, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - const owner = await lockContract.owner() - return owner.toLowerCase() === userAddress.toLowerCase() -} diff --git a/packages/unlock-js/src/PublicLock/v6/purchaseKey.js b/packages/unlock-js/src/PublicLock/v6/purchaseKey.js deleted file mode 100644 index 0e31d824f98..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/purchaseKey.js +++ /dev/null @@ -1,156 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' -import approveAllowance from '../utils/approveAllowance' - -/** - * Purchase key function. This implementation requires the following - * @param {object} params: - * - {PropTypes.address} lockAddress - * - {PropTypes.address} owner - * - {string} keyPrice - * - {PropTypes.address} erc20Address - * - {number} decimals - * - {PropTypes.address} referrer (address which will receive UDT - if applicable) - * - {PropTypes.array[bytes]} data (array of bytes, not used in transaction but can be used by hooks) - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, owner, keyPrice, erc20Address, decimals, referrer, data }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!owner) { - owner = await this.signer.getAddress() - } - - if (!referrer) { - referrer = ZERO - } - - if (!data) { - data = '0x' - } - - // If erc20Address was not provided, get it - if (!erc20Address) { - erc20Address = await lockContract.tokenAddress() - } - let actualAmount - if (!keyPrice) { - // We might not have the keyPrice, in which case, we need to retrieve from the the lock! - actualAmount = await lockContract.keyPrice() - } else if (decimals !== undefined && decimals !== null) { - // We have have a keyPrice and decinals, we just use them. - actualAmount = utils.toDecimal(keyPrice, decimals) - } else { - // get the decimals from the ERC20 contract or default to 18 - if (erc20Address && erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - actualAmount = utils.toDecimal(keyPrice, decimals) - } - - const purchaseArgs = [actualAmount, owner, referrer, data] - const callData = lockContract.interface.encodeFunctionData( - 'purchase', - purchaseArgs - ) - - // tx options - if (!erc20Address || erc20Address === ZERO) { - transactionOptions.value = actualAmount - } - - // If the lock is priced in ERC20, we need to approve the transfer - const approvalOptions = { - erc20Address, - address: lockAddress, - totalAmountToApprove: actualAmount, - } - - // Only ask for approval if the lock is priced in ERC20 - if (approvalOptions.erc20Address && approvalOptions.erc20Address !== ZERO) { - await approveAllowance.bind(this)(approvalOptions) - } - - // Estimate gas. Bump by 30% because estimates are wrong! - if (!transactionOptions.gasLimit) { - try { - // To get good estimates we need the gas price, because it matters in the actual execution (UDT calculation takes it into account) - // TODO remove once we move to use block.baseFee in UDT calculation - const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = - await this.provider.getFeeData() - - if (maxFeePerGas && maxPriorityFeePerGas) { - transactionOptions.maxFeePerGas = maxFeePerGas - transactionOptions.maxPriorityFeePerGas = maxPriorityFeePerGas - } else { - transactionOptions.gasPrice = gasPrice - } - - const gasLimitPromise = lockContract.purchase.estimateGas( - actualAmount, - owner, - referrer, - data, - transactionOptions - ) - - const gasLimit = await gasLimitPromise - // Remove the gas prices settings for the actual transaction (the wallet will set them) - delete transactionOptions.maxFeePerGas - delete transactionOptions.maxPriorityFeePerGas - delete transactionOptions.gasPrice - transactionOptions.gasLimit = (gasLimit * 13n) / 10n - } catch (error) { - console.error( - 'We could not estimate gas ourselves. Let wallet do it.', - error - ) - delete transactionOptions.maxFeePerGas - delete transactionOptions.maxPriorityFeePerGas - delete transactionOptions.gasPrice - } - } - - const transactionPromise = lockContract.purchase( - actualAmount, - owner, - referrer, - data, - transactionOptions - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the transaction to go thru to return the token id - const receipt = await this.provider.waitForTransaction(hash) - - if (receipt.status === 0) { - throw new Error('Transaction failed') - } - - const parser = lockContract.interface - - const transferEvent = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .find((evt) => evt && evt.fragment?.name === 'Transfer') - - if (transferEvent) { - return transferEvent.args.tokenId.toString() - } - // There was no Transfer log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/purchaseKeys.js b/packages/unlock-js/src/PublicLock/v6/purchaseKeys.js deleted file mode 100644 index 33e1ea37623..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/purchaseKeys.js +++ /dev/null @@ -1,24 +0,0 @@ -import multiplePurchaseWrapper from '../utils/multiplePurchaseWrapper' -import purchaseKey from './purchaseKey' - -/** - * Purchase key function. This implementation requires the followin - * @param {object} params: - * - {PropTypes.arrayOf(PropTypes.address)} lockAddress - * - {PropTypes.arrayOf(PropTypes.address)} owners - * - {PropTypes.arrayOf(string)} keyPrices - * - {PropTypes.address} erc20Address - * - {number} decimals - * - {PropTypes.arrayOf(PropTypes.address)} referrers (address which will receive UDT - if applicable) - * - {PropTypes.arrayOf(PropTypes.array[bytes])} _data (array of array of bytes, not used in transaction but can be used by hooks) - * @param {function} callback invoked with the transaction hash - * */ - -export default async function (params, transactionOptions = {}, callback) { - return await multiplePurchaseWrapper.bind(this)( - purchaseKey, - params, - transactionOptions, - callback - ) -} diff --git a/packages/unlock-js/src/PublicLock/v6/renounceLockManager.js b/packages/unlock-js/src/PublicLock/v6/renounceLockManager.js deleted file mode 100644 index 4825b53d1ff..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/renounceLockManager.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Renounce lock manager - * @param {string} lockAddress address of the lock - */ - -export default async function ( - { lockAddress }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.renounceLockManager() - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/shareKey.js b/packages/unlock-js/src/PublicLock/v6/shareKey.js deleted file mode 100644 index 02df371822c..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/shareKey.js +++ /dev/null @@ -1,33 +0,0 @@ -export default async function ( - { lockAddress, tokenId, recipient, duration }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - if (!tokenId) { - // Let's assume transfer by seller :) - const owner = await this.signer.getAddress() - tokenId = await lockContract.getTokenIdFor(owner) - } - - if (!duration) { - const keyOwner = await lockContract.ownerOf(tokenId) - const expiration = await lockContract.keyExpirationTimestampFor(keyOwner) - duration = Math.floor(new Date().getTime() / 1000) - expiration - } - - const transactionPromise = lockContract.shareKey( - recipient, - tokenId, - duration, - transactionOptions - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - return await this.provider.waitForTransaction(hash) -} diff --git a/packages/unlock-js/src/PublicLock/v6/updateKeyPrice.js b/packages/unlock-js/src/PublicLock/v6/updateKeyPrice.js deleted file mode 100644 index 98053ffbf7c..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/updateKeyPrice.js +++ /dev/null @@ -1,61 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -/** - * Changes the price of keys on a given lock - * @param {object} params - * - {PropTypes.address} lockAddress : address of the lock for which we update the price - * - {string} keyPrice : new price for the lock, as a string (as wei) - * - {string} decimals : Optional number of decimals (read from contract if unset) - * - {string} erc20Address : Optional address of ERC20, to retrieve decimals (read from contract if unset) - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { lockAddress, keyPrice, decimals, erc20Address }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - // If none is set, let's get the current ERC20 address because we need to set one - if (!erc20Address) { - erc20Address = await lockContract.tokenAddress() - } - - // Get the decimals from the contract - if (decimals == null) { - if (erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - } - const actualAmount = utils.toDecimal(keyPrice, decimals) - - const transactionPromise = lockContract.updateKeyPricing( - actualAmount, - erc20Address || ZERO - ) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the keyPrice to have been changed before we return it - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - - const priceChangedEvent = receipt.logs - .map((log) => { - return parser.parseLog(log) - }) - .find(({ fragment }) => fragment && fragment.name === 'PricingChanged') - if (priceChangedEvent) { - // TODO: also return contract? - return utils.fromDecimal(priceChangedEvent.args.keyPrice, decimals) - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/updateTransferFee.js b/packages/unlock-js/src/PublicLock/v6/updateTransferFee.js deleted file mode 100644 index 8a74edbdff5..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/updateTransferFee.js +++ /dev/null @@ -1,20 +0,0 @@ -export default async function ( - { lockAddress, transferFeeBasisPoints }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.updateTransferFee( - transferFeeBasisPoints - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v6/withdrawFromLock.js b/packages/unlock-js/src/PublicLock/v6/withdrawFromLock.js deleted file mode 100644 index 488ca88c0f9..00000000000 --- a/packages/unlock-js/src/PublicLock/v6/withdrawFromLock.js +++ /dev/null @@ -1,59 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -/** - * Triggers a transaction to withdraw funds from the lock and assign them to the owner. - * By default (amount=0), this withdraws all funds. - * @param {PropTypes.address} lockAddress - * @param {string} amount - * @param {number} erc20Address - * @param {number} decimals - * @param {function} callback invoked with the transaction hash - */ -export default async function ( - { erc20Address, lockAddress, amount = '0', decimals }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!erc20Address || erc20Address !== ZERO) { - erc20Address = await lockContract.tokenAddress() - } - - // decimals could be 0! - if (decimals == null) { - // get the decimals from the ERC20 contract or default to 18 - if (erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - } - - const actualAmount = utils.toDecimal(amount, decimals) - - const transactionPromise = lockContract.withdraw(erc20Address, actualAmount) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the funds to have been withdrawn - const receipt = await this.provider.waitForTransaction(hash) - - const parser = lockContract.interface - const withdrawalEvent = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .find(({ fragment }) => fragment && fragment.name === 'Withdrawal') - if (withdrawalEvent) { - return utils.fromWei(withdrawalEvent.args.amount.toString(), 'ether') - } - // There was no Withdrawal log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/addKeyGranter.js b/packages/unlock-js/src/PublicLock/v7/addKeyGranter.js deleted file mode 100644 index c93b152b4f4..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/addKeyGranter.js +++ /dev/null @@ -1,17 +0,0 @@ -export default async function ( - { lockAddress, keyGranter }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.addKeyGranter(keyGranter) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - await this.provider.waitForTransaction(hash) - return true -} diff --git a/packages/unlock-js/src/PublicLock/v7/cancelAndRefund.js b/packages/unlock-js/src/PublicLock/v7/cancelAndRefund.js deleted file mode 100644 index 6ab1902dcfe..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/cancelAndRefund.js +++ /dev/null @@ -1,24 +0,0 @@ -export default async function ( - { lockAddress, tokenId }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!tokenId) { - const owner = await this.signer.getAddress() - tokenId = await lockContract.getTokenIdFor(owner) - } - - const transactionPromise = lockContract.cancelAndRefund(tokenId) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/expireAndRefundFor.js b/packages/unlock-js/src/PublicLock/v7/expireAndRefundFor.js deleted file mode 100644 index fe39f47df3f..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/expireAndRefundFor.js +++ /dev/null @@ -1,41 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -export default async function ( - { lockAddress, keyOwner, amount = '0', decimals, erc20Address }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - if (!erc20Address || erc20Address !== ZERO) { - erc20Address = await lockContract.tokenAddress() - } - - // decimals could be 0! - if (decimals == null) { - // get the decimals from the ERC20 contract or default to 18 - if (erc20Address !== ZERO) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } else { - decimals = 18 - } - } - - const actualAmount = utils.toDecimal(amount, decimals) - - const transactionPromise = lockContract.expireAndRefundFor( - keyOwner, - actualAmount - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/getCancelAndRefundValueFor.js b/packages/unlock-js/src/PublicLock/v7/getCancelAndRefundValueFor.js deleted file mode 100644 index 1e1c7e65bb5..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/getCancelAndRefundValueFor.js +++ /dev/null @@ -1,23 +0,0 @@ -import utils from '../../utils' -import { ZERO } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -export async function getCancelAndRefundValueFor( - { lockAddress, owner, tokenAddress }, - transactionOptions = {}, - provider -) { - const lockContract = await this.getLockContract(lockAddress, provider) - const value = await lockContract.getCancelAndRefundValueFor(owner) - - let refundValue - if (tokenAddress === ZERO) { - refundValue = utils.fromWei(value, 'ether') - } else { - refundValue = await getErc20Decimals(tokenAddress, this.provider) - } - - return refundValue -} - -export default getCancelAndRefundValueFor diff --git a/packages/unlock-js/src/PublicLock/v7/grantKey.js b/packages/unlock-js/src/PublicLock/v7/grantKey.js deleted file mode 100644 index 7acbfd45eea..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/grantKey.js +++ /dev/null @@ -1,24 +0,0 @@ -import grantKeys from './grantKeys' - -export default async function ( - { lockAddress, recipient, expiration, keyManager }, - transactionOptions = {}, - callback -) { - const events = await grantKeys.bind(this)( - { - lockAddress, - recipients: [recipient], - expirations: expiration ? [expiration] : [], - keyManagers: keyManager ? [keyManager] : [], - }, - transactionOptions, - callback - ) - - if (events?.length) { - return events[0] - } - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/grantKeys.js b/packages/unlock-js/src/PublicLock/v7/grantKeys.js deleted file mode 100644 index 2e9749f991c..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/grantKeys.js +++ /dev/null @@ -1,77 +0,0 @@ -import { ETHERS_MAX_UINT } from '../../constants' - -export default async function ( - { lockAddress, recipients, expirations, keyManagers }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - if (!expirations?.length) { - // Let's get the expiration from the duration (+/- given that the transaction can take time to be mined!) - const duration = await lockContract.expirationDuration() - - if (ETHERS_MAX_UINT === duration) { - // Add equal number of expirations to recipients length - expirations = new Array(recipients.length).fill(ETHERS_MAX_UINT) - } else { - expirations = new Array(recipients.length).fill( - BigInt(Math.floor(new Date().getTime() / 1000)) + duration - ) - } - } - - if (!keyManagers?.length) { - // By default the key manager is the granter - const signer = this.signer - const manager = await signer.getAddress() - keyManagers = new Array(recipients.length).fill(manager) - } - - if (recipients.length !== expirations.length) { - throw new Error( - "Number of recipients don't match the number of expirations provided" - ) - } - - if (recipients.length !== keyManagers.length) { - throw new Error( - "Number of recipients don't match the number of keyManagers provided" - ) - } - - const transactionPromise = lockContract.grantKeys( - recipients, - expirations, - keyManagers, - transactionOptions || {} - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the transaction to go thru to return the token id - const receipt = await this.provider.waitForTransaction(hash) - const parser = lockContract.interface - - const transferEvents = receipt.logs - .map((log) => { - if (log.address.toLowerCase() !== lockAddress.toLowerCase()) return // Some events are triggered by the ERC20 contract - return parser.parseLog(log) - }) - .filter(({ fragment }) => fragment && fragment.name === 'Transfer') - - if (transferEvents.length) { - return transferEvents.map((item) => { - return { - id: item.args.tokenId.toString(), - owner: item.args.to.toString(), - } - }) - } - // There was no Transfer log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/index.js b/packages/unlock-js/src/PublicLock/v7/index.js deleted file mode 100644 index 33b1d8e4ec7..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/index.js +++ /dev/null @@ -1,67 +0,0 @@ -import abis from '../../abis' -import grantKey from './grantKey' -import grantKeys from './grantKeys' -import isLockManager from './isLockManager' -import isKeyGranter from './isKeyGranter' -import addKeyGranter from './addKeyGranter' -import expireAndRefundFor from './expireAndRefundFor' -import cancelAndRefund from './cancelAndRefund' -import keyManagerOf from './keyManagerOf' -import getCancelAndRefundValueFor from './getCancelAndRefundValueFor' -import setEventHooks from './setEventHooks' -import setKeyManagerOf from './setKeyManagerOf' -import v6 from '../v6' - -const { - shareKey, - initializeTemplate, - withdrawFromLock, - updateKeyPrice, - purchaseKey, - purchaseKeys, - getLock, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, - updateRefundPenalty, - updateTransferFee, -} = v6 - -export default { - version: 'v7', - Unlock: abis.Unlock.v7, - PublicLock: abis.PublicLock.v7, - initializeTemplate, - updateKeyPrice, - purchaseKey, - purchaseKeys, - getLock, - grantKey, - grantKeys, - withdrawFromLock, - isLockManager, - isKeyGranter, - addKeyGranter, - expireAndRefundFor, - cancelAndRefund, - shareKey, - keyManagerOf, - getCancelAndRefundValueFor, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, - updateRefundPenalty, - setEventHooks, - updateTransferFee, - setKeyManagerOf, -} diff --git a/packages/unlock-js/src/PublicLock/v7/isKeyGranter.js b/packages/unlock-js/src/PublicLock/v7/isKeyGranter.js deleted file mode 100644 index f838be21dfd..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/isKeyGranter.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Yields true if the user is a key granter - * In this version, only the lock owner is a manager - * @param {string} lockAddress address of the lock - * @param {string} address address of the key grnater - */ -export default async function (lockAddress, address, provider) { - const lockContract = await this.getLockContract(lockAddress, provider) - - return lockContract.isKeyGranter(address) -} diff --git a/packages/unlock-js/src/PublicLock/v7/isLockManager.js b/packages/unlock-js/src/PublicLock/v7/isLockManager.js deleted file mode 100644 index 3b8a1f06922..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/isLockManager.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Yields true if the user is a lock manager - * In this version, only the lock owner is a manager - * @param {string} lockAddres address of the lock - * @param {string} userAddress address of the user - */ -export default async function (lockAddres, userAddress, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - - return lockContract.isLockManager(userAddress) -} diff --git a/packages/unlock-js/src/PublicLock/v7/keyManagerOf.js b/packages/unlock-js/src/PublicLock/v7/keyManagerOf.js deleted file mode 100644 index 49041c114d4..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/keyManagerOf.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @param {string} lockAddres address of the lock - * @param {string} tokenId - */ -export default async function (lockAddres, tokenId, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - - return lockContract.keyManagerOf(tokenId) -} diff --git a/packages/unlock-js/src/PublicLock/v7/setEventHooks.js b/packages/unlock-js/src/PublicLock/v7/setEventHooks.js deleted file mode 100644 index 8e8fe6bc6e8..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/setEventHooks.js +++ /dev/null @@ -1,21 +0,0 @@ -import { ZERO } from '../../constants' - -export default async function ( - { lockAddress, keyPurchase = ZERO, keyCancel = ZERO }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - - const transactionPromise = lockContract.setEventHooks(keyPurchase, keyCancel) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v7/setKeyManagerOf.js b/packages/unlock-js/src/PublicLock/v7/setKeyManagerOf.js deleted file mode 100644 index d315ab674c2..00000000000 --- a/packages/unlock-js/src/PublicLock/v7/setKeyManagerOf.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Change lock manager for a specific key - * @param {string} lockAddress address of the lock - * @param {string} managerAddress address of the user - */ - -export default async function ( - { lockAddress, managerAddress, tokenId }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - const transactionPromise = lockContract.setKeyManagerOf( - tokenId, - managerAddress - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - const tx = await this.provider.waitForTransaction(hash) - return tx -} diff --git a/packages/unlock-js/src/PublicLock/v8/approveBeneficiary.js b/packages/unlock-js/src/PublicLock/v8/approveBeneficiary.js deleted file mode 100644 index 0e1a55d31c6..00000000000 --- a/packages/unlock-js/src/PublicLock/v8/approveBeneficiary.js +++ /dev/null @@ -1,44 +0,0 @@ -import utils from '../../utils' -import { ZERO, MAX_UINT } from '../../constants' -import { getErc20Decimals } from '../../erc20' - -export default async function ( - { lockAddress, spender, amount = '0', decimals, erc20Address }, - transactionOptions = {}, - callback -) { - const lockContract = await this.getLockContract(lockAddress) - if (!erc20Address || erc20Address !== ZERO) { - erc20Address = await lockContract.tokenAddress() - } - - if (erc20Address === ZERO) { - throw new Error('Lock can only set approval for ERC20') - } - - // decimals could be 0! - let actualAmount - if (amount !== MAX_UINT) { - if (decimals == null) { - decimals = await getErc20Decimals(erc20Address, this.provider) - } - actualAmount = utils.toDecimal(amount, decimals) - } else { - actualAmount = amount - } - - const transactionPromise = lockContract.approveBeneficiary( - spender, - actualAmount - ) - - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash) - } - - await this.provider.waitForTransaction(hash) - - return null -} diff --git a/packages/unlock-js/src/PublicLock/v8/index.js b/packages/unlock-js/src/PublicLock/v8/index.js deleted file mode 100644 index 12b97ee3931..00000000000 --- a/packages/unlock-js/src/PublicLock/v8/index.js +++ /dev/null @@ -1,70 +0,0 @@ -import abis from '../../abis' -import keyManagerOf from './keyManagerOf' -import approveBeneficiary from './approveBeneficiary' - -import v7 from '../v7' - -const { - grantKey, - grantKeys, - updateKeyPrice, - withdrawFromLock, - initializeTemplate, - isLockManager, - isKeyGranter, - addKeyGranter, - expireAndRefundFor, - cancelAndRefund, - shareKey, - getLock, - purchaseKey, - purchaseKeys, - getCancelAndRefundValueFor, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, - updateRefundPenalty, - setEventHooks, - updateTransferFee, - setKeyManagerOf, -} = v7 - -export default { - version: 'v8', - Unlock: abis.Unlock.v8, - PublicLock: abis.PublicLock.v8, - initializeTemplate, - updateKeyPrice, - purchaseKey, - purchaseKeys, - grantKey, - grantKeys, - getLock, - withdrawFromLock, - isLockManager, - isKeyGranter, - addKeyGranter, - expireAndRefundFor, - cancelAndRefund, - shareKey, - keyManagerOf, - getCancelAndRefundValueFor, - getTokenIdForOwner, - getKeyExpirationByLockForOwner, - approveBeneficiary, - totalKeys, - updateLockName, - updateLockSymbol, - setBaseTokenURI, - addLockManager, - renounceLockManager, - updateRefundPenalty, - setEventHooks, - updateTransferFee, - setKeyManagerOf, -} diff --git a/packages/unlock-js/src/PublicLock/v8/keyManagerOf.js b/packages/unlock-js/src/PublicLock/v8/keyManagerOf.js deleted file mode 100644 index fefdf73660a..00000000000 --- a/packages/unlock-js/src/PublicLock/v8/keyManagerOf.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @param {string} lockAddres address of the lock - * @param {string} tokenId address of the user - */ -export default async function (lockAddres, tokenId, provider) { - const lockContract = await this.getLockContract(lockAddres, provider) - - return lockContract.keyManagerOf(tokenId) -} diff --git a/packages/unlock-js/src/Unlock/index.ts b/packages/unlock-js/src/Unlock/index.ts index bb09757807d..49ba54e0cc1 100644 --- a/packages/unlock-js/src/Unlock/index.ts +++ b/packages/unlock-js/src/Unlock/index.ts @@ -1,19 +1,9 @@ -import v4 from './v4' -import v6 from './v6' -import v7 from './v7' -import v8 from './v8' -import v9 from './v9' import v10 from './v10' import v11 from './v11' import v12 from './v12' import v13 from './v13' export default { - v4, - v6, - v7, - v8, - v9, v10, v11, v12, diff --git a/packages/unlock-js/src/Unlock/v4/createLock.js b/packages/unlock-js/src/Unlock/v4/createLock.js deleted file mode 100644 index 59026e4ca9c..00000000000 --- a/packages/unlock-js/src/Unlock/v4/createLock.js +++ /dev/null @@ -1,57 +0,0 @@ -import ethersUtils from '../../utils' -import { ETHERS_MAX_UINT, UNLIMITED_KEYS_COUNT, ZERO } from '../../constants' - -import { getErc20Decimals } from '../../erc20' -import { _getKeyPrice } from '../utils' - -/** - * Creates a lock on behalf of the user, using version v4 - * @param {PropTypes.lock} lock - * @param {function} callback invoked with the transaction hash - */ -export default async function (lock, transactionOptions = {}, callback) { - const unlockContract = await this.getUnlockContract() - let { maxNumberOfKeys } = lock - if ( - typeof maxNumberOfKeys !== 'number' || - maxNumberOfKeys === UNLIMITED_KEYS_COUNT - ) { - maxNumberOfKeys = ETHERS_MAX_UINT - } - - const decimalKeyPrice = _getKeyPrice(lock, this.provider) - - const currencyContractAddress = lock.currencyContractAddress || ZERO - - const lockName = lock.name || 'New Lock' - const transactionPromise = unlockContract.functions[ - 'createLock(uint256,address,uint256,uint256,string)' - ]( - lock.expirationDuration, - currencyContractAddress, - decimalKeyPrice, - maxNumberOfKeys, - lockName - ) - const hash = await this._handleMethodCall(transactionPromise) - - if (callback) { - callback(null, hash, await transactionPromise) - } - // Let's now wait for the lock to be deployed before we return its address - const { logs } = await this.provider.waitForTransaction(hash) - const parsedLogs = logs - .map((log) => unlockContract.interface.parseLog(log)) - .map((log) => log || {}) - - const newLockEvent = parsedLogs.find( - ({ fragment }) => - fragment && fragment.signature === 'NewLock(address,address)' - ) - - if (newLockEvent) { - return newLockEvent.args.newLockAddress - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/Unlock/v4/index.js b/packages/unlock-js/src/Unlock/v4/index.js deleted file mode 100644 index 21720911e80..00000000000 --- a/packages/unlock-js/src/Unlock/v4/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import abis from '../../abis' -import createLock from './createLock' - -export default { - createLock, - version: 'v4', - Unlock: abis.Unlock.v4, - PublicLock: abis.PublicLock.v4, -} diff --git a/packages/unlock-js/src/Unlock/v6/createLock.js b/packages/unlock-js/src/Unlock/v6/createLock.js deleted file mode 100644 index aec7d7326b7..00000000000 --- a/packages/unlock-js/src/Unlock/v6/createLock.js +++ /dev/null @@ -1,60 +0,0 @@ -import ethersUtils from '../../utils' -import { ETHERS_MAX_UINT, UNLIMITED_KEYS_COUNT, ZERO } from '../../constants' - -import { getErc20Decimals } from '../../erc20' -import { _getKeyPrice } from '../utils' - -/** - * Creates a lock on behalf of the user, using version v6 - * @param {PropTypes.lock} lock - * @param {function} callback invoked with the transaction hash - */ -export default async function (lock, transactionOptions = {}, callback) { - const unlockContract = await this.getUnlockContract() - let { maxNumberOfKeys } = lock - if ( - typeof maxNumberOfKeys !== 'number' || - maxNumberOfKeys === UNLIMITED_KEYS_COUNT - ) { - maxNumberOfKeys = ETHERS_MAX_UINT - } - - const decimalKeyPrice = await _getKeyPrice(lock, this.provider) - - const currencyContractAddress = lock.currencyContractAddress || ZERO - - const lockName = lock.name - - // Building a salt from the lock name will prevent creators from creating 2 locks with the same name. - const salt = ethersUtils - .sha3(ethersUtils.utf8ToHex(lock.name)) - .substring(0, 26) // 2+24 - const transactionPromise = unlockContract.createLock( - lock.expirationDuration, - currencyContractAddress, - decimalKeyPrice, - maxNumberOfKeys, - lockName, - salt - ) - const hash = await this._handleMethodCall(transactionPromise) - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the lock to be deployed before we return its address - const { logs } = await this.provider.waitForTransaction(hash) - const parsedLogs = logs - .map((log) => unlockContract.interface.parseLog(log)) - .map((log) => log || {}) - - const newLockEvent = parsedLogs.find( - ({ fragment }) => fragment && fragment.name === 'NewLock' - ) - - if (newLockEvent) { - return newLockEvent.args.newLockAddress - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/Unlock/v6/index.js b/packages/unlock-js/src/Unlock/v6/index.js deleted file mode 100644 index a79deeb773d..00000000000 --- a/packages/unlock-js/src/Unlock/v6/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import abis from '../../abis' -import createLock from './createLock' - -export default { - createLock, - version: 'v6', - Unlock: abis.Unlock.v6, - PublicLock: abis.PublicLock.v6, -} diff --git a/packages/unlock-js/src/Unlock/v7/createLock.js b/packages/unlock-js/src/Unlock/v7/createLock.js deleted file mode 100644 index e4676cae686..00000000000 --- a/packages/unlock-js/src/Unlock/v7/createLock.js +++ /dev/null @@ -1,60 +0,0 @@ -import ethersUtils from '../../utils' -import { ETHERS_MAX_UINT, UNLIMITED_KEYS_COUNT, ZERO } from '../../constants' - -import { getErc20Decimals } from '../../erc20' -import { _getKeyPrice } from '../utils' - -/** - * Creates a lock on behalf of the user, using version v17 - * @param {PropTypes.lock} lock - * @param {function} callback invoked with the transaction hash - */ -export default async function (lock, transactionOptions = {}, callback) { - const unlockContract = await this.getUnlockContract() - let { maxNumberOfKeys } = lock - if ( - typeof maxNumberOfKeys !== 'number' || - maxNumberOfKeys === UNLIMITED_KEYS_COUNT - ) { - maxNumberOfKeys = ETHERS_MAX_UINT - } - - const decimalKeyPrice = await _getKeyPrice(lock, this.provider) - - const currencyContractAddress = lock.currencyContractAddress || ZERO - - const lockName = lock.name - - // Building a salt from the lock name will prevent creators from creating 2 locks with the same name. - const salt = ethersUtils - .sha3(ethersUtils.utf8ToHex(lock.name)) - .substring(0, 26) // 2+24 - const transactionPromise = unlockContract.createLock( - lock.expirationDuration, - currencyContractAddress, - decimalKeyPrice, - maxNumberOfKeys, - lockName, - salt - ) - const hash = await this._handleMethodCall(transactionPromise) - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the lock to be deployed before we return its address - const { logs } = await this.provider.waitForTransaction(hash) - const parsedLogs = logs - .map((log) => unlockContract.interface.parseLog(log)) - .map((log) => log || {}) - - const newLockEvent = parsedLogs.find( - ({ fragment }) => fragment && fragment.name === 'NewLock' - ) - - if (newLockEvent) { - return newLockEvent.args.newLockAddress - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/Unlock/v7/index.js b/packages/unlock-js/src/Unlock/v7/index.js deleted file mode 100644 index e2452c2b876..00000000000 --- a/packages/unlock-js/src/Unlock/v7/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import abis from '../../abis' -import createLock from './createLock' - -export default { - createLock, - version: 'v7', - Unlock: abis.Unlock.v7, - PublicLock: abis.PublicLock.v7, -} diff --git a/packages/unlock-js/src/Unlock/v8/createLock.js b/packages/unlock-js/src/Unlock/v8/createLock.js deleted file mode 100644 index 5b3d33d3c84..00000000000 --- a/packages/unlock-js/src/Unlock/v8/createLock.js +++ /dev/null @@ -1,60 +0,0 @@ -import ethersUtils from '../../utils' -import { ETHERS_MAX_UINT, UNLIMITED_KEYS_COUNT, ZERO } from '../../constants' - -import { getErc20Decimals } from '../../erc20' -import { _getKeyPrice } from '../utils' - -/** - * Creates a lock on behalf of the user, using version v17 - * @param {PropTypes.lock} lock - * @param {function} callback invoked with the transaction hash - */ -export default async function (lock, transactionOptions = {}, callback) { - const unlockContract = await this.getUnlockContract() - let { maxNumberOfKeys } = lock - if ( - typeof maxNumberOfKeys !== 'number' || - maxNumberOfKeys === UNLIMITED_KEYS_COUNT - ) { - maxNumberOfKeys = ETHERS_MAX_UINT - } - - const decimalKeyPrice = await _getKeyPrice(lock, this.provider) - - const currencyContractAddress = lock.currencyContractAddress || ZERO - - const lockName = lock.name - - // Building a salt from the lock name will prevent creators from creating 2 locks with the same name. - const salt = ethersUtils - .sha3(ethersUtils.utf8ToHex(lock.name)) - .substring(0, 26) // 2+24 - const transactionPromise = unlockContract.createLock( - lock.expirationDuration, - currencyContractAddress, - decimalKeyPrice, - maxNumberOfKeys, - lockName, - salt - ) - - const hash = await this._handleMethodCall(transactionPromise) - if (callback) { - callback(null, hash, await transactionPromise) - } - - // Let's now wait for the lock to be deployed before we return its address - const { logs } = await this.provider.waitForTransaction(hash) - const parsedLogs = logs - .map((log) => unlockContract.interface.parseLog(log)) - .map((log) => log || {}) - - const newLockEvent = parsedLogs.find( - ({ fragment }) => fragment && fragment.name === 'NewLock' - ) - if (newLockEvent) { - return newLockEvent.args.newLockAddress - } - // There was no NewEvent log (transaction failed?) - return null -} diff --git a/packages/unlock-js/src/Unlock/v8/index.js b/packages/unlock-js/src/Unlock/v8/index.js deleted file mode 100644 index 46f786d728a..00000000000 --- a/packages/unlock-js/src/Unlock/v8/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import abis from '../../abis' -import createLock from './createLock' - -export default { - createLock, - version: 'v8', - Unlock: abis.Unlock.v8, - PublicLock: abis.PublicLock.v8, -} diff --git a/packages/unlock-js/src/Unlock/v9/index.js b/packages/unlock-js/src/Unlock/v9/index.js deleted file mode 100644 index 283c2e405bc..00000000000 --- a/packages/unlock-js/src/Unlock/v9/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import abis from '../../abis' - -import v8 from '../v8' - -const { createLock } = v8 - -export default { - createLock, - version: 'v9', - Unlock: abis.Unlock.v9, - PublicLock: abis.PublicLock.v9, -} diff --git a/packages/unlock-js/src/__tests__/integration/walletServiceIntegration.test.js b/packages/unlock-js/src/__tests__/integration/walletServiceIntegration.test.js index 106f6bb9cc4..97ad6760260 100644 --- a/packages/unlock-js/src/__tests__/integration/walletServiceIntegration.test.js +++ b/packages/unlock-js/src/__tests__/integration/walletServiceIntegration.test.js @@ -49,9 +49,7 @@ import transferFrom from './lock/transferFrom' // Increasing timeouts // Unlock versions to test -export const UnlockVersionNumbers = Object.keys(UnlockVersions).filter( - (v) => !['v6', 'v4'].includes(v) // 'v6' is disabled it required erc1820 -) +export const UnlockVersionNumbers = Object.keys(UnlockVersions) describe.each(UnlockVersionNumbers)('Unlock %s', (unlockVersion) => { let walletService @@ -60,10 +58,7 @@ describe.each(UnlockVersionNumbers)('Unlock %s', (unlockVersion) => { let accounts // Unlock v4 can only interact w PublicLock v4 - const PublicLockVersions = - unlockVersion === 'v4' // Unlock v4 can only interact w PublicLock v4 - ? ['v4'] - : Object.keys(locks).filter((v) => !['v4', 'v6'].includes(v)) + const PublicLockVersions = Object.keys(locks) beforeAll(async () => { // deploy ERC20 and set balances