diff --git a/docs/contracts/Deferred.md b/docs/contracts/Deferred.md index 79cbc72..d6635d7 100644 --- a/docs/contracts/Deferred.md +++ b/docs/contracts/Deferred.md @@ -55,4 +55,11 @@ The tokens are eventually phyisically minted when they are first bought. So when It's important to know that **Deferred ERC721 can't be transferred by the token owner**, but only by the [Marketplace](./Marketplace.md). The marketplace is always allowed to transfer tokens, while the user is never allowed to. It's neither allowed to call `approve` on the contract. +The Marketplace calls the `transferToken` which will transfer the next `token` for the provided contract id for the buyer to get. This means that: + +1. If the buyer is the contract buyer, this will get the next token id owned by the first third-party investor, or if none the contract seller. +2. If the buyer is a third-party investor, this will get the next token id owned by the contract seller. + +Others methods like `transferFrom` or `safeTransferFrom` are disabled + This is of course done to prevent users from selling the tokens breaking their intrisic price, defined at the contract creation. The **token price will never change**. diff --git a/docs/contracts/Marketplace.md b/docs/contracts/Marketplace.md index 05475a5..102dc1c 100644 --- a/docs/contracts/Marketplace.md +++ b/docs/contracts/Marketplace.md @@ -20,16 +20,18 @@ If the Buyer of the contract buys the token, he will pay the token price plus th ## Buy process -The Marketplace contract provides two functions useful to buy a process, the `buyToken` method and the `tokenPriceForCaller` view method. +The Marketplace contract provides two functions useful to buy a process, the `buyNextToken` method and the `tokenPriceForCaller` view method. + +`buyNextToken` will always buy the next token available to be bought for the contract. ```solidity function tokenPriceForCaller( - uint256 _tokenId + uint256 _contractId ) external view returns (uint256) {} ``` ```solidity -function buyToken(uint256 _tokenId) external {} +function buyNextToken(uint256 _contractId) external {} ``` So the buy process is divided in two parts. diff --git a/ethereum/app/src/js/web3/contracts/Deferred.ts b/ethereum/app/src/js/web3/contracts/Deferred.ts index 1f53d17..41ca4fd 100644 --- a/ethereum/app/src/js/web3/contracts/Deferred.ts +++ b/ethereum/app/src/js/web3/contracts/Deferred.ts @@ -365,6 +365,44 @@ export const ABI = [ stateMutability: 'nonpayable', type: 'function', }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'contractCompleted', + outputs: [ + { + internalType: 'bool', + name: 'completed', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'contractProgress', + outputs: [ + { + internalType: 'uint256', + name: '_progress', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, { inputs: [ { @@ -459,6 +497,89 @@ export const ABI = [ stateMutability: 'view', type: 'function', }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'getContract', + outputs: [ + { + components: [ + { + internalType: 'string', + name: 'metadataUri', + type: 'string', + }, + { + components: [ + { + internalType: 'address', + name: 'seller', + type: 'address', + }, + { + internalType: 'uint256', + name: 'tokenFromId', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'tokenToId', + type: 'uint256', + }, + ], + internalType: 'struct Deferred.Seller[]', + name: 'sellers', + type: 'tuple[]', + }, + { + internalType: 'address[]', + name: 'buyers', + type: 'address[]', + }, + { + internalType: 'uint256', + name: 'ekokeReward', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'tokenPriceUsd', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'tokenFromId', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'tokenToId', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'closed', + type: 'bool', + }, + { + internalType: 'bool', + name: 'created', + type: 'bool', + }, + ], + internalType: 'struct Deferred.SellContract', + name: '_sellContract', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, { inputs: [ { @@ -509,6 +630,49 @@ export const ABI = [ stateMutability: 'view', type: 'function', }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'nextTokenIdToBuy', + outputs: [ + { + internalType: 'uint256', + name: '_nextTokenId', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + { + internalType: 'address', + name: '_caller', + type: 'address', + }, + ], + name: 'nextTokenIdToBuyFor', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, { inputs: [], name: 'owner', @@ -588,28 +752,28 @@ export const ABI = [ inputs: [ { internalType: 'address', - name: 'from', + name: '', type: 'address', }, { internalType: 'address', - name: 'to', + name: '', type: 'address', }, { internalType: 'uint256', - name: 'tokenId', + name: '', type: 'uint256', }, { internalType: 'bytes', - name: 'data', + name: '', type: 'bytes', }, ], name: 'safeTransferFrom', outputs: [], - stateMutability: 'nonpayable', + stateMutability: 'pure', type: 'function', }, { @@ -787,23 +951,23 @@ export const ABI = [ inputs: [ { internalType: 'address', - name: 'from', + name: '', type: 'address', }, { internalType: 'address', - name: 'to', + name: '', type: 'address', }, { internalType: 'uint256', - name: 'tokenId', + name: '', type: 'uint256', }, ], name: 'transferFrom', outputs: [], - stateMutability: 'nonpayable', + stateMutability: 'pure', type: 'function', }, { @@ -819,6 +983,35 @@ export const ABI = [ stateMutability: 'nonpayable', type: 'function', }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + ], + name: 'transferToken', + outputs: [ + { + internalType: 'uint256', + name: '_tokenId', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, ]; interface ContractAddress { diff --git a/ethereum/app/src/js/web3/contracts/Marketplace.ts b/ethereum/app/src/js/web3/contracts/Marketplace.ts index b1b4bf0..9bacc9e 100644 --- a/ethereum/app/src/js/web3/contracts/Marketplace.ts +++ b/ethereum/app/src/js/web3/contracts/Marketplace.ts @@ -83,6 +83,12 @@ export const ABI = [ name: 'seller', type: 'address', }, + { + indexed: false, + internalType: 'uint256', + name: 'contractId', + type: 'uint256', + }, { indexed: false, internalType: 'uint256', @@ -135,12 +141,18 @@ export const ABI = [ inputs: [ { internalType: 'uint256', - name: '_tokenId', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'buyNextToken', + outputs: [ + { + internalType: 'uint256', + name: 'tokenId', type: 'uint256', }, ], - name: 'buyToken', - outputs: [], stateMutability: 'nonpayable', type: 'function', }, @@ -177,6 +189,25 @@ export const ABI = [ stateMutability: 'nonpayable', type: 'function', }, + { + inputs: [ + { + internalType: 'uint256', + name: '_contractId', + type: 'uint256', + }, + ], + name: 'tokenPriceForCaller', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, { inputs: [ { diff --git a/ethereum/contracts/Deferred.sol b/ethereum/contracts/Deferred.sol index 401eb81..06b5e1b 100644 --- a/ethereum/contracts/Deferred.sol +++ b/ethereum/contracts/Deferred.sol @@ -6,7 +6,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {RewardPool} from "./RewardPool.sol"; // Uncomment this line to use console.log -import "hardhat/console.sol"; +// import "hardhat/console.sol"; contract Deferred is ERC721, Ownable { struct SellerRequest { @@ -72,6 +72,15 @@ contract Deferred is ERC721, Ownable { /// @dev lazy balances mapping(address => uint256) private lazyBalances; + /// @dev Next token id to buy for buyer for a sell contract + mapping(uint256 => uint256) private nextTokenIdForBuyer; + + /// @dev Next token id to buy for a third party for a sell contract + mapping(uint256 => uint256) private nextTokenIdForThirdParty; + + /// @dev Tokens for a contract already bought by a buyer + mapping(uint256 => uint256) private tokensBoughtByBuyer; + /// @dev list of sell contracts uint256[] private sellContractIds; @@ -101,6 +110,14 @@ contract Deferred is ERC721, Ownable { _; } + modifier onlyMarketplace() { + require( + msg.sender == marketplace && marketplace != address(0), + "Deferred: caller is not the marketplace" + ); + _; + } + constructor( address _initialOwner ) ERC721("Deferred", "DEFERRED") Ownable(_initialOwner) {} @@ -208,6 +225,13 @@ contract Deferred is ERC721, Ownable { sellContract.sellers.push(sellers[i]); } + // insert next token id for buyers + nextTokenIdForBuyer[contractId] = tokenFromId; + // insert next token id for third party + nextTokenIdForThirdParty[contractId] = tokenFromId; + // init tokensBoughtByBuyer + tokensBoughtByBuyer[contractId] = 0; + nextTokenId += _request.tokensAmount; // add contract id to the list sellContractIds.push(contractId); @@ -233,6 +257,77 @@ contract Deferred is ERC721, Ownable { emit ContractClosed(_contractId); } + /// @notice Get the next token id to buy for a sell contract for the caller + /// @param _contractId The id of the contract + /// @param _caller The address of the caller + /// @return _nextTokenId The next token id to buy + function nextTokenIdToBuyFor( + uint256 _contractId, + address _caller + ) public view returns (uint256) { + // get contract + SellContract memory sellContract = sellContracts[_contractId]; + require(sellContract.created, "Deferred: contract does not exist"); + + uint256 _nextTokenId = 0; + bool isBuyer = false; + + // check if caller is a buyer + for (uint256 i = 0; i < sellContract.buyers.length; i++) { + if (_caller == sellContract.buyers[i]) { + isBuyer = true; + break; + } + } + + if (isBuyer) { + // return next token id for buyer + _nextTokenId = nextTokenIdForBuyer[_contractId]; + } else { + // return next token id for third party + _nextTokenId = nextTokenIdForThirdParty[_contractId]; + } + + // if next token id is greater than the last token id, return 0 + if (_nextTokenId > sellContract.tokenToId) { + revert("Deferred: no more tokens to buy"); + } + + return _nextTokenId; + } + + /// @notice Get the next token id to buy for a sell contract for the caller + /// @param _contractId The id of the contract + /// @return _nextTokenId The next token id to buy + function nextTokenIdToBuy( + uint256 _contractId + ) public view returns (uint256 _nextTokenId) { + return nextTokenIdToBuyFor(_contractId, msg.sender); + } + + /// @notice tells whether all contract tokens have been bought by the buyers + /// @param _contractId The id of the contract + /// @return completed True if all tokens have been bought + function contractCompleted( + uint256 _contractId + ) public view returns (bool completed) { + SellContract memory sellContract = sellContracts[_contractId]; + require(sellContract.created, "Deferred: contract does not exist"); + + return + tokensBoughtByBuyer[_contractId] == + sellContract.tokenToId - sellContract.tokenFromId + 1; + } + + /// @notice Get the progress of a contract + /// @param _contractId The id of the contract + /// @return _progress The progress of the contract + function contractProgress( + uint256 _contractId + ) public view returns (uint256 _progress) { + return tokensBoughtByBuyer[_contractId]; + } + // ERC721 overrides /// @notice Get balance of a token owner @@ -256,32 +351,76 @@ contract Deferred is ERC721, Ownable { return super.ownerOf(tokenId); } - /// @notice Transfer a token from an address to another - /// @dev This method is called by the marketplace - /// @param from The address of the token owner - /// @param to The address of the token receiver - /// @param tokenId The id of the token - /// @param data idk - function safeTransferFrom( + /// @notice Get the contract by id + /// @param _contractId The id of the contract + /// @return _sellContract The contract + function getContract( + uint256 _contractId + ) public view returns (SellContract memory _sellContract) { + SellContract memory sellContract = sellContracts[_contractId]; + require(sellContract.created, "Deferred: contract does not exist"); + + return sellContract; + } + + /// @notice Transfer the next token for a contract from the caller to another address + /// @dev Only the marketplace can call this method + /// @param _contractId The id of the contract + /// @param from The address of the sender + /// @param to The address of the receiver + /// @return _tokenId The id of the token + function transferToken( + uint256 _contractId, address from, - address to, - uint256 tokenId, - bytes memory data - ) public override { + address to + ) public onlyMarketplace returns (uint256 _tokenId) { + // check caller is actually buying the next token + SellContract memory sellContract = sellContracts[_contractId]; + // get next token id + uint256 tokenId = nextTokenIdToBuyFor(_contractId, to); + + // check if from is the owner of the token require( - msg.sender == marketplace && marketplace != address(0), - "Deferred: caller is not the marketplace" + ownerOf(tokenId) == from, + "Deferred: from is not the owner of the token" ); + bool isBuyer = false; + for (uint256 i = 0; i < sellContract.buyers.length; i++) { + if (to == sellContract.buyers[i]) { + isBuyer = true; + break; + } + } + + // increment next token id based on the buyer + if (isBuyer) { + nextTokenIdForBuyer[_contractId] += 1; + tokensBoughtByBuyer[_contractId] += 1; + // increment third party if less or equal than buyer + if ( + nextTokenIdForThirdParty[_contractId] <= + nextTokenIdForBuyer[_contractId] + ) { + nextTokenIdForThirdParty[_contractId] = nextTokenIdForBuyer[ + _contractId + ]; + } + } else { + nextTokenIdForThirdParty[_contractId] += 1; + } + // if is lazy minting, mint the token if (_isLazy(tokenId)) { _lazyMint(tokenId, to); - lazyBalances[from] -= 1; + if (lazyBalances[from] > 0) { + lazyBalances[from] -= 1; + } // approve the marketplace to transfer the token super.approve(marketplace, tokenId); - return; + return tokenId; } // if the token is not allowed to marketplace, approve it first @@ -289,7 +428,10 @@ contract Deferred is ERC721, Ownable { super.approve(marketplace, tokenId); } - return super.safeTransferFrom(from, to, tokenId, data); + // transfer the token + super.transferFrom(from, to, tokenId); + + return tokenId; } /// @notice Get the token uri @@ -321,37 +463,20 @@ contract Deferred is ERC721, Ownable { } /// @notice Transfer a token from an address to another - /// @dev This method is called by the marketplace - /// @param from The address of the token owner - /// @param to The address of the token receiver - /// @param tokenId The id of the token - function transferFrom( - address from, - address to, - uint256 tokenId - ) public override { - require( - msg.sender == marketplace && marketplace != address(0), - "Deferred: caller is not the marketplace" - ); - - // if is lazy minting, mint the token - if (_isLazy(tokenId)) { - _lazyMint(tokenId, to); - lazyBalances[from] -= 1; - - // approve the marketplace to transfer the token - super.approve(marketplace, tokenId); - - return; - } - - // if the token is not allowed to marketplace, approve it first - if (super.getApproved(tokenId) != marketplace) { - super.approve(marketplace, tokenId); - } + /// @dev This method is not allowed. Only the marketplace can transfer a token using `transferToken` + function safeTransferFrom( + address, + address, + uint256, + bytes memory + ) public pure override { + revert("Deferred: safeTransferFrom is not allowed"); + } - super.transferFrom(from, to, tokenId); + /// @notice Transfer a token from an address to another + /// @dev This method is not allowed. Only the marketplace can transfer a token using `transferToken` + function transferFrom(address, address, uint256) public pure override { + revert("Deferred: transferFrom is not allowed"); } /// @notice Approve a token to be transferred to another address diff --git a/ethereum/contracts/Marketplace.sol b/ethereum/contracts/Marketplace.sol index 6badbd7..5a38dec 100644 --- a/ethereum/contracts/Marketplace.sol +++ b/ethereum/contracts/Marketplace.sol @@ -34,6 +34,7 @@ contract Marketplace is Ownable { event TokenBought( address indexed buyer, address indexed seller, + uint256 contractId, uint256 tokenId, uint256 price, uint256 paidAmount @@ -81,16 +82,25 @@ contract Marketplace is Ownable { interestRate = _interestRate; } - /// @notice Buy a deferred NFT with the configured USD ERC20 token - /// @param _tokenId The ID of the deferred NFT\ - function buyToken(uint256 _tokenId) external { + /// @notice Buy the next token for a deferred contractt with the configured USD ERC20 token + /// @param _contractId The ID of the contract to buy the token for + /// @return tokenId The ID of the bought token + function buyNextToken( + uint256 _contractId + ) external returns (uint256 tokenId) { require(rewardPool != address(0), "Marketplace: Reward pool not set"); // get the contract from deferred Deferred deferredContract = Deferred(deferred); // get the contract for token Deferred.SellContract memory sellContract = deferredContract - .tokenContract(_tokenId); + .getContract(_contractId); + + // get next token id to buy + uint256 _tokenId = deferredContract.nextTokenIdToBuyFor( + _contractId, + msg.sender + ); // get token buyer address tokenBuyer = msg.sender; @@ -132,7 +142,11 @@ contract Marketplace is Ownable { // if the buyer is a contract buyer, transfer the interest to the marketplace // transfer the NFT from the `tokenSeller` to the `tokenBuyer` - ERC721(deferred).transferFrom(tokenSeller, tokenBuyer, _tokenId); + uint256 boughtTokenId = Deferred(deferred).transferToken( + _contractId, + tokenSeller, + tokenBuyer + ); // if we need to send reward, send the reward to the `tokenBuyer` if (willSendReward) { @@ -143,27 +157,30 @@ contract Marketplace is Ownable { } // set the token as sold - soldTokens[_tokenId] = true; + soldTokens[boughtTokenId] = true; // emit the event emit TokenBought( tokenBuyer, tokenSeller, - _tokenId, + _contractId, + boughtTokenId, tokenPriceUsdErc20, requiredAllowance ); + + return boughtTokenId; } /// @notice Get the price of the token for the caller with the interests if the caller is a contract buyer - /// @param _tokenId The ID of the deferred NFT + /// @param _contractId The ID of the contract for the token /// @return _price The price of the token function tokenPriceForCaller( - uint256 _tokenId + uint256 _contractId ) external view returns (uint256) { Deferred deferredContract = Deferred(deferred); Deferred.SellContract memory sellContract = deferredContract - .tokenContract(_tokenId); + .getContract(_contractId); bool _isContractBuyer = isContractBuyer(sellContract); diff --git a/ethereum/test/Deferred.ts b/ethereum/test/Deferred.ts index 92bd24b..15eebb1 100644 --- a/ethereum/test/Deferred.ts +++ b/ethereum/test/Deferred.ts @@ -7,7 +7,7 @@ const NAME = "Deferred"; describe("Deferred", () => { interface Contract { - token: Deferred; + deferred: Deferred; rewardPoolContract: RewardPool; ekokeContract: Ekoke; owner: SignerWithAddress; @@ -25,7 +25,7 @@ describe("Deferred", () => { await ethers.getSigners(); const contract = await ethers.deployContract(NAME, [owner.address]); // set contracts - const token = contract as unknown as Deferred; + const deferred = contract as unknown as Deferred; const ekokeContract = await ethers.deployContract("Ekoke", [owner.address]); const ekoke = ekokeContract as unknown as Ekoke; @@ -38,12 +38,12 @@ describe("Deferred", () => { const rewardPool = rewardPoolContract as unknown as RewardPool; // set contracts - await token.adminSetDeferredMinter(minter.address); - await token.adminSetRewardPool(rewardPool.getAddress()); - await token.adminSetMarketplace(marketplace.address); + await deferred.adminSetDeferredMinter(minter.address); + await deferred.adminSetRewardPool(rewardPool.getAddress()); + await deferred.adminSetMarketplace(marketplace.address); deploy = { - token, + deferred, rewardPoolContract: rewardPool, ekokeContract: ekoke, owner, @@ -56,17 +56,17 @@ describe("Deferred", () => { }); it("Should has the correct name and symbol ", async () => { - const { token, marketplace } = deploy; - expect(await token.name()).to.equal(NAME); - expect(await token.symbol()).to.equal("DEFERRED"); - expect(await token.marketplace()).to.equal(marketplace.address); + const { deferred, marketplace } = deploy; + expect(await deferred.name()).to.equal(NAME); + expect(await deferred.symbol()).to.equal("DEFERRED"); + expect(await deferred.marketplace()).to.equal(marketplace.address); }); it("Should create contract with one seller", async () => { - const { token, minter, marketplace, rewardPoolContract, alice, bob } = + const { deferred, minter, marketplace, rewardPoolContract, alice, bob } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -82,15 +82,15 @@ describe("Deferred", () => { }); // alice should have 40_000 tokens - expect(await token.balanceOf(alice.address)).to.equal(40_000); + expect(await deferred.balanceOf(alice.address)).to.equal(40_000); // get token uri for token id 0 - expect(await token.tokenURI(0)).to.equal("metadataUri"); + expect(await deferred.tokenURI(0)).to.equal("metadataUri"); // owner of token id 0 should be alice - expect(await token.ownerOf(0)).to.equal(alice.address); + expect(await deferred.ownerOf(0)).to.equal(alice.address); // price should be 100 - expect(await token.tokenPriceUsd(0)).to.equal(100); + expect(await deferred.tokenPriceUsd(0)).to.equal(100); // tokens should be approved to marketplace - expect(await token.getApproved(0)).to.equal(marketplace.address); + expect(await deferred.getApproved(0)).to.equal(marketplace.address); // should have reserved reward const expectedReward = 1_000 * 40_000; @@ -98,10 +98,10 @@ describe("Deferred", () => { }); it("Should not reserve reward if reward is zero", async () => { - const { token, minter, marketplace, rewardPoolContract, alice, bob } = + const { deferred, minter, marketplace, rewardPoolContract, alice, bob } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -117,15 +117,15 @@ describe("Deferred", () => { }); // alice should have 40_000 tokens - expect(await token.balanceOf(alice.address)).to.equal(40_000); + expect(await deferred.balanceOf(alice.address)).to.equal(40_000); // get token uri for token id 0 - expect(await token.tokenURI(0)).to.equal("metadataUri"); + expect(await deferred.tokenURI(0)).to.equal("metadataUri"); // owner of token id 0 should be alice - expect(await token.ownerOf(0)).to.equal(alice.address); + expect(await deferred.ownerOf(0)).to.equal(alice.address); // price should be 100 - expect(await token.tokenPriceUsd(0)).to.equal(100); + expect(await deferred.tokenPriceUsd(0)).to.equal(100); // tokens should be approved to marketplace - expect(await token.getApproved(0)).to.equal(marketplace.address); + expect(await deferred.getApproved(0)).to.equal(marketplace.address); // should have reserved reward const expectedReward = 0; @@ -133,9 +133,9 @@ describe("Deferred", () => { }); it("Should create a contract with different quotas", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -155,15 +155,15 @@ describe("Deferred", () => { }); // alice should have 24_000 tokens - expect(await token.balanceOf(alice.address)).to.equal(24_000); + expect(await deferred.balanceOf(alice.address)).to.equal(24_000); // bob should have 16_000 tokens - expect(await token.balanceOf(bob.address)).to.equal(16_000); + expect(await deferred.balanceOf(bob.address)).to.equal(16_000); }); it("Should not create a contract with a duplicate id", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -183,7 +183,7 @@ describe("Deferred", () => { }); await expect( - token.connect(minter).createContract({ + deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -205,9 +205,9 @@ describe("Deferred", () => { }); it("Should create a contract with multiple buyers", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -224,10 +224,10 @@ describe("Deferred", () => { }); it("Should not create a contract with more than 100% quota", async () => { - const { token, minter, alice, bob } = deploy; + const { deferred, minter, alice, bob } = deploy; await expect( - token.connect(minter).createContract({ + deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -249,10 +249,10 @@ describe("Deferred", () => { }); it("Should not create a contract if not minter", async () => { - const { token, owner, alice } = deploy; + const { deferred, owner, alice } = deploy; await expect( - token.connect(owner).createContract({ + deferred.connect(owner).createContract({ contractId: 1, sellers: [ { @@ -270,10 +270,10 @@ describe("Deferred", () => { }); it("Should not create a contract with less than 100% quota", async () => { - const { token, minter, alice, bob } = deploy; + const { deferred, minter, alice, bob } = deploy; await expect( - token.connect(minter).createContract({ + deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -295,10 +295,10 @@ describe("Deferred", () => { }); it("Should not create a contract with a token amount not divisible by 100", async () => { - const { token, minter, alice } = deploy; + const { deferred, minter, alice } = deploy; await expect( - token.connect(minter).createContract({ + deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -316,10 +316,10 @@ describe("Deferred", () => { }); it("Should not create a contract with 0 tokens", async () => { - const { token, minter, alice } = deploy; + const { deferred, minter, alice } = deploy; await expect( - token.connect(minter).createContract({ + deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -337,9 +337,9 @@ describe("Deferred", () => { }); it("Should close a contract", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -359,20 +359,20 @@ describe("Deferred", () => { }); // alice should have 24_000 tokens - expect(await token.balanceOf(alice.address)).to.equal(24_000); + expect(await deferred.balanceOf(alice.address)).to.equal(24_000); // bob should have 16_000 tokens - expect(await token.balanceOf(bob.address)).to.equal(16_000); + expect(await deferred.balanceOf(bob.address)).to.equal(16_000); const contractId = 1; // close the contract - await token.connect(minter).closeContract(contractId); + await deferred.connect(minter).closeContract(contractId); }); it("Should not return closed contracts", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -391,20 +391,20 @@ describe("Deferred", () => { tokensAmount: 40_000, }); - expect((await token.tokenContract(0)).closed).to.equal(false); + expect((await deferred.tokenContract(0)).closed).to.equal(false); // close the contract - await token.connect(minter).closeContract(1); + await deferred.connect(minter).closeContract(1); - await expect(token.tokenContract(1)).to.be.revertedWith( + await expect(deferred.tokenContract(1)).to.be.revertedWith( "Deferred: token does not exist" ); }); it("Should allow marketplace to transfer tokens", async () => { - const { token, minter, alice, bob, marketplace } = deploy; + const { deferred, minter, alice, bob, marketplace } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -419,19 +419,23 @@ describe("Deferred", () => { tokensAmount: 40_000, }); - await token + const tokenId = await deferred.nextTokenIdToBuyFor(1, bob.address); + + await deferred .connect(marketplace) - .transferFrom(alice.address, bob.address, 0); + .transferToken(1, alice.address, bob.address); + + expect(await deferred.ownerOf(tokenId)).to.equal(bob.address); - expect(await token.balanceOf(alice.address)).to.equal(39_999); - expect(await token.balanceOf(bob.address)).to.equal(1); - expect(await token.ownerOf(0)).to.equal(bob.address); + expect(await deferred.balanceOf(alice.address)).to.equal(39_999); + expect(await deferred.balanceOf(bob.address)).to.equal(1); + expect(await deferred.ownerOf(0)).to.equal(bob.address); }); it("Should allow further transfers from marketplace", async () => { - const { token, minter, alice, bob, charlie, marketplace } = deploy; + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -446,27 +450,39 @@ describe("Deferred", () => { tokensAmount: 40_000, }); - await token + const tokenIdForThirdParty = await deferred.nextTokenIdToBuyFor( + 1, + charlie.address + ); + + await deferred .connect(marketplace) - .transferFrom(alice.address, charlie.address, 0); + .transferToken(1, alice.address, charlie.address); + + expect(await deferred.ownerOf(tokenIdForThirdParty)).to.equal( + charlie.address + ); + + expect(await deferred.balanceOf(alice.address)).to.equal(39_999); + expect(await deferred.balanceOf(charlie.address)).to.equal(1); + expect(await deferred.ownerOf(0)).to.equal(charlie.address); - expect(await token.balanceOf(alice.address)).to.equal(39_999); - expect(await token.balanceOf(charlie.address)).to.equal(1); - expect(await token.ownerOf(0)).to.equal(charlie.address); + const tokenIdForBuyer = await deferred.nextTokenIdToBuyFor(1, bob.address); - await token + await deferred .connect(marketplace) - .transferFrom(charlie.address, bob.address, 0); + .transferToken(1, charlie.address, bob.address); + expect(await deferred.ownerOf(tokenIdForBuyer)).to.equal(bob.address); - expect(await token.balanceOf(bob.address)).to.equal(1); - expect(await token.balanceOf(charlie.address)).to.equal(0); - expect(await token.ownerOf(0)).to.equal(bob.address); + expect(await deferred.balanceOf(bob.address)).to.equal(1); + expect(await deferred.balanceOf(charlie.address)).to.equal(0); + expect(await deferred.ownerOf(0)).to.equal(bob.address); }); it("Should allow marketplace to transfer tokens", async () => { - const { token, minter, alice, bob, marketplace } = deploy; + const { deferred, minter, alice, bob, marketplace } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -481,19 +497,137 @@ describe("Deferred", () => { tokensAmount: 40_000, }); - await token + const nextTokenId = await deferred.nextTokenIdToBuyFor(1, bob.address); + + await deferred + .connect(marketplace) + .transferToken(1, alice.address, bob.address); + expect(await deferred.ownerOf(nextTokenId)).to.equal(bob.address); + + expect(await deferred.balanceOf(alice.address)).to.equal(39_999); + expect(await deferred.balanceOf(bob.address)).to.equal(1); + expect(await deferred.ownerOf(0)).to.equal(bob.address); + }); + + it("Should increment next third party token id, if the buyer has bought first", async () => { + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; + + await deferred.connect(minter).createContract({ + contractId: 1, + sellers: [ + { + seller: alice.address, + quota: 100, + }, + ], + metadataUri: "metadataUri", + buyers: [bob.address], + ekokeReward: 1_000, + tokenPriceUsd: 100, + tokensAmount: 100, + }); + + const tokenId = await deferred.nextTokenIdToBuyFor(1, bob.address); + await deferred + .connect(marketplace) + .transferToken(1, alice.address, bob.address); + + // check third party next token id has incremented + const expected = tokenId + BigInt(1); + expect(await deferred.nextTokenIdToBuyFor(1, charlie.address)).to.equal( + expected + ); + expect(await deferred.nextTokenIdToBuyFor(1, bob.address)).to.equal( + expected + ); + + const expected2 = tokenId + BigInt(2); + // charlie buys + await deferred .connect(marketplace) - .transferFrom(alice.address, bob.address, 0); + .transferToken(1, alice.address, charlie.address); + expect(await deferred.nextTokenIdToBuyFor(1, charlie.address)).to.equal( + expected2 + ); + // for bob should be the same + expect(await deferred.nextTokenIdToBuyFor(1, bob.address)).to.equal( + expected + ); + + expect(await deferred.balanceOf(alice.address)).to.equal(98); + }); + + it("Should fail bad token owner for lazy minting", async () => { + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; + + await deferred.connect(minter).createContract({ + contractId: 1, + sellers: [ + { + seller: alice.address, + quota: 100, + }, + ], + metadataUri: "metadataUri", + buyers: [bob.address], + ekokeReward: 1_000, + tokenPriceUsd: 100, + tokensAmount: 100, + }); + + await expect( + deferred + .connect(marketplace) + .transferToken(1, charlie.address, bob.address) + ).to.be.revertedWith("Deferred: from is not the owner of the token"); + }); + + it("Should tell whether contract is completed", async () => { + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; + + await deferred.connect(minter).createContract({ + contractId: 1, + sellers: [ + { + seller: alice.address, + quota: 100, + }, + ], + metadataUri: "metadataUri", + buyers: [bob.address], + ekokeReward: 1_000, + tokenPriceUsd: 100, + tokensAmount: 100, + }); + + expect(await deferred.contractCompleted(1)).to.equal(false); + expect(await deferred.contractProgress(1)).to.equal(0); + + for (let i = 0; i < 100; i++) { + const tokenId = await deferred.nextTokenIdToBuyFor(1, bob.address); - expect(await token.balanceOf(alice.address)).to.equal(39_999); - expect(await token.balanceOf(bob.address)).to.equal(1); - expect(await token.ownerOf(0)).to.equal(bob.address); + await deferred + .connect(marketplace) + .transferToken(1, alice.address, charlie.address); + + expect(await deferred.ownerOf(tokenId)).to.equal(charlie.address); + expect(await deferred.contractProgress(1)).to.equal(i); + + await deferred + .connect(marketplace) + .transferToken(1, charlie.address, bob.address); + + expect(await deferred.ownerOf(tokenId)).to.equal(bob.address); + expect(await deferred.contractProgress(1)).to.equal(i + 1); + } + + expect(await deferred.contractCompleted(1)).to.equal(true); }); it("Should not allow approve", async () => { - const { token, minter, alice, bob, charlie, marketplace } = deploy; + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -509,14 +643,14 @@ describe("Deferred", () => { }); await expect( - token.connect(alice).approve(charlie.address, 0) + deferred.connect(alice).approve(charlie.address, 0) ).to.be.revertedWith("Deferred: approve is not allowed"); }); it("Should not allow setApprovalForAll", async () => { - const { token, minter, alice, bob, charlie } = deploy; + const { deferred, minter, alice, bob, charlie } = deploy; - await token.connect(minter).createContract({ + await deferred.connect(minter).createContract({ contractId: 1, sellers: [ { @@ -532,7 +666,55 @@ describe("Deferred", () => { }); await expect( - token.connect(alice).setApprovalForAll(charlie.address, true) + deferred.connect(alice).setApprovalForAll(charlie.address, true) ).to.be.revertedWith("Deferred: setApprovalForAll is not allowed"); }); + + it("should not allow transferFrom", async () => { + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; + + await deferred.connect(minter).createContract({ + contractId: 1, + sellers: [ + { + seller: alice.address, + quota: 100, + }, + ], + metadataUri: "metadataUri", + buyers: [bob.address], + ekokeReward: 1_000, + tokenPriceUsd: 100, + tokensAmount: 40_000, + }); + + await expect( + deferred.connect(alice).transferFrom(alice.address, charlie.address, 0) + ).to.be.revertedWith("Deferred: transferFrom is not allowed"); + }); + + it("Should not allow safeTransferFrom", async () => { + const { deferred, minter, alice, bob, charlie, marketplace } = deploy; + + await deferred.connect(minter).createContract({ + contractId: 1, + sellers: [ + { + seller: alice.address, + quota: 100, + }, + ], + metadataUri: "metadataUri", + buyers: [bob.address], + ekokeReward: 1_000, + tokenPriceUsd: 100, + tokensAmount: 40_000, + }); + + await expect( + deferred + .connect(alice) + .safeTransferFrom(alice.address, charlie.address, 0) + ).to.be.revertedWith("Deferred: safeTransferFrom is not allowed"); + }); }); diff --git a/ethereum/test/Marketplace.ts b/ethereum/test/Marketplace.ts index 385b634..63cbcb5 100644 --- a/ethereum/test/Marketplace.ts +++ b/ethereum/test/Marketplace.ts @@ -12,6 +12,7 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; const EKOKE_REWARD = 1000; const USD_PRICE = 100; const USDT_DECIMALS = 6; +const CONTRACT_ID = 1; const usdToUsdt = (usd: number) => usd * 10 ** USDT_DECIMALS; @@ -80,7 +81,7 @@ describe("RewardPool", () => { // create a sell contract await deferred.connect(minter).createContract({ - contractId: 1, + contractId: CONTRACT_ID, sellers: [ { seller: seller.address, @@ -111,13 +112,19 @@ describe("RewardPool", () => { it("Should buy a NFT with USDT as third-party", async () => { const { marketplace, thirdParty, seller, deferred, ekoke, usdt } = deploy; - const tokenId = 0; // give allowance to marketplace await usdt .connect(thirdParty) .approve(marketplace.getAddress(), usdToUsdt(USD_PRICE)); // buy - await marketplace.connect(thirdParty).buyToken(tokenId); + const expectedTokenId = await deferred.nextTokenIdToBuyFor( + CONTRACT_ID, + thirdParty.address + ); + await marketplace.connect(thirdParty).buyNextToken(CONTRACT_ID); + expect(await deferred.ownerOf(expectedTokenId)).to.equal( + thirdParty.address + ); // USDT balance of buyer expect(await usdt.balanceOf(thirdParty.address)).to.equal( @@ -127,7 +134,9 @@ describe("RewardPool", () => { expect(await usdt.balanceOf(seller.address)).to.equal(usdToUsdt(USD_PRICE)); // check NFT has been transferred - expect(await deferred.ownerOf(tokenId)).to.equal(thirdParty.address); + expect(await deferred.ownerOf(expectedTokenId)).to.equal( + thirdParty.address + ); // check buyer has received the reward expect(await ekoke.balanceOf(thirdParty.address)).to.equal(EKOKE_REWARD); @@ -136,7 +145,6 @@ describe("RewardPool", () => { it("Should buy a NFT with USDT as contract buyer", async () => { const { marketplace, buyer, usdt, seller, deferred, ekoke } = deploy; - const tokenId = 0; const interest = 10; // give allowance to marketplace await usdt @@ -146,7 +154,12 @@ describe("RewardPool", () => { usdToUsdt(USD_PRICE) + usdToUsdt(interest) ); // buy - await marketplace.connect(buyer).buyToken(tokenId); + const expectedTokenId = await deferred.nextTokenIdToBuyFor( + CONTRACT_ID, + buyer.address + ); + await marketplace.connect(buyer).buyNextToken(CONTRACT_ID); + expect(await deferred.ownerOf(expectedTokenId)).to.equal(buyer.address); // USDT balance of buyer expect(await usdt.balanceOf(buyer.address)).to.equal( @@ -160,7 +173,7 @@ describe("RewardPool", () => { ); // check NFT has been transferred - expect(await deferred.ownerOf(tokenId)).to.equal(buyer.address); + expect(await deferred.ownerOf(expectedTokenId)).to.equal(buyer.address); // check buyer has received the reward expect(await ekoke.balanceOf(buyer.address)).to.equal(EKOKE_REWARD); @@ -169,21 +182,19 @@ describe("RewardPool", () => { it("Should get token price as contract buyer", async () => { const { buyer, marketplace } = deploy; - const tokenId = 0; const interest = 10; // give allowance to marketplace expect( - await marketplace.connect(buyer).tokenPriceForCaller(tokenId) + await marketplace.connect(buyer).tokenPriceForCaller(CONTRACT_ID) ).to.equal(usdToUsdt(USD_PRICE) + (usdToUsdt(USD_PRICE) * interest) / 100); }); it("Should get token price as third-party", async () => { const { marketplace, thirdParty } = deploy; - const tokenId = 0; // give allowance to marketplace expect( - await marketplace.connect(thirdParty).tokenPriceForCaller(tokenId) + await marketplace.connect(thirdParty).tokenPriceForCaller(CONTRACT_ID) ).to.equal(usdToUsdt(USD_PRICE)); }); diff --git a/integration-tests/src/abi/Deferred.json b/integration-tests/src/abi/Deferred.json index e0c235b..8d38ede 100644 --- a/integration-tests/src/abi/Deferred.json +++ b/integration-tests/src/abi/Deferred.json @@ -367,6 +367,44 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "contractCompleted", + "outputs": [ + { + "internalType": "bool", + "name": "completed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "contractProgress", + "outputs": [ + { + "internalType": "uint256", + "name": "_progress", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -461,6 +499,89 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "getContract", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "metadataUri", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "seller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenFromId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenToId", + "type": "uint256" + } + ], + "internalType": "struct Deferred.Seller[]", + "name": "sellers", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "buyers", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "ekokeReward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenPriceUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenFromId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenToId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "closed", + "type": "bool" + }, + { + "internalType": "bool", + "name": "created", + "type": "bool" + } + ], + "internalType": "struct Deferred.SellContract", + "name": "_sellContract", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -511,6 +632,49 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "nextTokenIdToBuy", + "outputs": [ + { + "internalType": "uint256", + "name": "_nextTokenId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_caller", + "type": "address" + } + ], + "name": "nextTokenIdToBuyFor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "owner", @@ -590,28 +754,28 @@ "inputs": [ { "internalType": "address", - "name": "from", + "name": "", "type": "address" }, { "internalType": "address", - "name": "to", + "name": "", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "", "type": "uint256" }, { "internalType": "bytes", - "name": "data", + "name": "", "type": "bytes" } ], "name": "safeTransferFrom", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" }, { @@ -789,23 +953,23 @@ "inputs": [ { "internalType": "address", - "name": "from", + "name": "", "type": "address" }, { "internalType": "address", - "name": "to", + "name": "", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "", "type": "uint256" } ], "name": "transferFrom", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" }, { @@ -820,10 +984,39 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferToken", + "outputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" } ], - "bytecode": "0x60806040526000600a55600b80546001600160a01b0319908116909155600c805482169055600d8054909116905534801561003957600080fd5b50604051612ffe380380612ffe8339810160408190526100589161014a565b8060405180604001604052806008815260200167111959995c9c995960c21b81525060405180604001604052806008815260200167111151915494915160c21b81525081600090816100aa9190610219565b5060016100b78282610219565b5050506001600160a01b0381166100e857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100f1816100f8565b50506102d7565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006020828403121561015c57600080fd5b81516001600160a01b038116811461017357600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806101a457607f821691505b6020821081036101c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561021457806000526020600020601f840160051c810160208510156101f15750805b601f840160051c820191505b8181101561021157600081556001016101fd565b50505b505050565b81516001600160401b038111156102325761023261017a565b610246816102408454610190565b846101ca565b6020601f82116001811461027a57600083156102625750848201515b600019600385901b1c1916600184901b178455610211565b600084815260208120601f198516915b828110156102aa578785015182556020948501946001909201910161028a565b50848210156102c85786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b612d18806102e66000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c8063715018a6116100f9578063abc8c7af11610097578063d0ce736011610071578063d0ce736014610397578063d471cf5d146103aa578063e985e9c5146103bd578063f2fde38b146103d057600080fd5b8063abc8c7af1461035e578063b88d4fde14610371578063c87b56dd1461038457600080fd5b806395d89b41116100d357806395d89b41146103105780639be78f0514610318578063a22cb4651461032b578063a30fb0201461033e57600080fd5b8063715018a6146102e457806382558c2a146102ec5780638da5cb5b146102ff57600080fd5b806323b872dd116101665780635926912211610140578063592691221461028a5780636352211e146102ab57806366666aa9146102be57806370a08231146102d157600080fd5b806323b872dd146102515780633a0432421461026457806342842e0e1461027757600080fd5b8063017d6f99146101ae57806301ffc9a7146101de57806306fdde0314610201578063081812fc14610216578063095ea7b3146102295780631892dd9f1461023e575b600080fd5b600d546101c1906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101f16101ec3660046122b7565b6103e3565b60405190151581526020016101d5565b610209610435565b6040516101d5919061231a565b6101c161022436600461232d565b6104c7565b61023c61023736600461235b565b6104f1565b005b61023c61024c366004612387565b61053e565b61023c61025f3660046123a4565b610568565b6101c161027236600461232d565b61064d565b61023c6102853660046123a4565b610658565b61029d61029836600461232d565b610673565b6040519081526020016101d5565b6101c16102b936600461232d565b610688565b600c546101c1906001600160a01b031681565b61029d6102df366004612387565b6106b3565b61023c6106df565b61023c6102fa366004612387565b6106f3565b6006546001600160a01b03166101c1565b61020961071d565b61023c610326366004612387565b61072c565b61023c6103393660046123e5565b610756565b61035161034c36600461232d565b6107b1565b6040516101d591906124bc565b600b546101c1906001600160a01b031681565b61023c61037f36600461265b565b610a3f565b61020961039236600461232d565b610b2b565b61023c6103a536600461232d565b610b3d565b61023c6103b8366004612835565b610c83565b6101f16103cb366004612928565b611414565b61023c6103de366004612387565b61144b565b60006001600160e01b031982166380ac58cd60e01b148061041457506001600160e01b03198216635b5e139f60e01b145b8061042f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461044490612956565b80601f016020809104026020016040519081016040528092919081815260200182805461047090612956565b80156104bd5780601f10610492576101008083540402835291602001916104bd565b820191906000526020600020905b8154815290600101906020018083116104a057829003601f168201915b5050505050905090565b60006104d282611489565b156104e8575050600b546001600160a01b031690565b61042f826114f9565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b610546611522565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b03163314801561058c5750600b546001600160a01b031615155b6105a85760405162461bcd60e51b815260040161053590612990565b6105b181611489565b15610609576105c0818361154f565b6001600160a01b03831660009081526008602052604081208054600192906105e99084906129ed565b9091555050600b54610604906001600160a01b03168261155d565b505050565b600b546001600160a01b031661061e826114f9565b6001600160a01b03161461064257600b54610642906001600160a01b03168261155d565b610604838383611568565b600061042f826115ed565b61060483838360405180602001604052806000815250610a3f565b600061067e826107b1565b6080015192915050565b600061069382611489565b156106aa5761042f6106a4836115f8565b8361185a565b61042f826115ed565b6001600160a01b0381166000908152600860205260408120546106d583611c5a565b61042f9190612a00565b6106e7611522565b6106f16000611ca2565b565b6106fb611522565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60606001805461044490612956565b610734611522565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610535565b610804604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b600061080f836115f8565b9050600081116108615760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610535565b600081815260076020526040908190208151610120810190925280548290829061088a90612956565b80601f01602080910402602001604051908101604052809291908181526020018280546108b690612956565b80156109035780601f106108d857610100808354040283529160200191610903565b820191906000526020600020905b8154815290600101906020018083116108e657829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610986576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610931565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109e757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116109c9575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b600b546001600160a01b031633148015610a635750600b546001600160a01b031615155b610a7f5760405162461bcd60e51b815260040161053590612990565b610a8882611489565b15610ae057610a97828461154f565b6001600160a01b0384166000908152600860205260408120805460019290610ac09084906129ed565b9091555050600b54610adb906001600160a01b03168361155d565b610b25565b600b546001600160a01b0316610af5836114f9565b6001600160a01b031614610b1957600b54610b19906001600160a01b03168361155d565b610b2584848484611cf4565b50505050565b6060610b36826107b1565b5192915050565b600d546001600160a01b031633148015610b615750600d546001600160a01b031615155b610b7d5760405162461bcd60e51b815260040161053590612a13565b60008111610b9d5760405162461bcd60e51b815260040161053590612a55565b60008181526007602081905260409091200154610100900460ff16610bd45760405162461bcd60e51b815260040161053590612aa0565b60008181526007602081905260409091209081015460ff1615610c455760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610535565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b600d546001600160a01b031633148015610ca75750600d546001600160a01b031615155b610cc35760405162461bcd60e51b815260040161053590612a13565b805180610ce25760405162461bcd60e51b815260040161053590612a55565b60008181526007602081905260409091200154610100900460ff1615610d585760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610535565b600c546001600160a01b0316610db05760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610535565b60008260c0015111610e1a5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610535565b6000805b836040015151811015610ee55760006001600160a01b031684604001518281518110610e4c57610e4c612ae1565b6020026020010151600001516001600160a01b031603610eae5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610535565b83604001518181518110610ec457610ec4612ae1565b60200260200101516020015182610edb9190612af7565b9150600101610e1e565b508060ff16606414610f435760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610535565b60008360a0015111610fae5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610535565b60648360c00151610fbf9190612b26565b156110245760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610535565b60808301511561109d57600c54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b15801561108457600080fd5b505af1158015611098573d6000803e3d6000fd5b505050505b600a5460c08401516000906001906110b59084612a00565b6110bf91906129ed565b9050600085604001515167ffffffffffffffff8111156110e1576110e161256c565b60405190808252806020026020018201604052801561113f57816020015b61112c604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816110ff5790505b5090506000839050600060648860c0015161115a9190612b3a565b905060005b8860400151518110156112945760008960400151828151811061118457611184612ae1565b602002602001015190506000816020015160ff16846111a39190612b4e565b9050600060016111b38388612a00565b6111bd91906129ed565b905060405180606001604052808d6040015186815181106111e0576111e0612ae1565b6020026020010151600001516001600160a01b031681526020018781526020018281525087858151811061121657611216612ae1565b602090810291909101015261122c816001612a00565b9550816008600089878151811061124557611245612ae1565b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546112809190612a00565b90915550506001909301925061115f915050565b5060008781526007602090815260409091209089015181906112b69082612bac565b50606089015180516112d29160028401916020909101906121d9565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff191661010017905561131460018201600061223e565b60005b8451811015611391578160010185828151811061133657611336612ae1565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611317565b508860c00151600a60008282546113a89190612a00565b90915550506009805460018101825560009182527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600b546000906001600160a01b03838116911614806114445750826001600160a01b0316826001600160a01b0316145b9392505050565b611453611522565b6001600160a01b03811661147d57604051631e4fbdf760e01b815260006004820152602401610535565b61148681611ca2565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa9250505080156114e4575060408051601f3d908101601f191682019092526114e191810190612c6b565b60015b6114f057506001919050565b50600092915050565b600061150482611d0b565b506000828152600460205260409020546001600160a01b031661042f565b6006546001600160a01b031633146106f15760405163118cdaa760e01b8152336004820152602401610535565b6115598183611d44565b5050565b611559828233611d5e565b6001600160a01b03821661159257604051633250574960e11b815260006004820152602401610535565b600061159f838333611d6b565b9050836001600160a01b0316816001600160a01b031614610b25576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610535565b600061042f82611d0b565b6000805b6009548110156114f05760006009828154811061161b5761161b612ae1565b906000526020600020015490506000600760008381526020019081526020016000206040518061012001604052908160008201805461165990612956565b80601f016020809104026020016040519081016040528092919081815260200182805461168590612956565b80156116d25780601f106116a7576101008083540402835291602001916116d2565b820191906000526020600020905b8154815290600101906020018083116116b557829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611755576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611700565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156117b657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611798575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c090920191909152810151909150851080159061182757508060c001518511155b801561183557508060e00151155b801561184357508061010001515b1561185057509392505050565b50506001016115fc565b600080831161187b5760405162461bcd60e51b815260040161053590612a55565b60008381526007602081905260409091200154610100900460ff166118b25760405162461bcd60e51b815260040161053590612aa0565b6000838152600760205260409020600501548210156119395760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610535565b6000838152600760205260409020600601548211156119c05760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610535565b600083815260076020526040808220815161012081019092528054829082906119e890612956565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1490612956565b8015611a615780601f10611a3657610100808354040283529160200191611a61565b820191906000526020600020905b815481529060010190602001808311611a4457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ae4576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611a8f565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611b4557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b27575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b816020015151811015611bfb57600082602001518281518110611bc057611bc0612ae1565b6020026020010151905084816020015111158015611be2575080604001518511155b15611bf25751925061042f915050565b50600101611b9b565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610535565b60006001600160a01b038216611c86576040516322718ad960e21b815260006004820152602401610535565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611cff848484610568565b610b2584848484611e64565b6000818152600260205260408120546001600160a01b03168061042f57604051637e27328960e01b815260048101849052602401610535565b611559828260405180602001604052806000815250611f8d565b6106048383836001611fa4565b6000828152600260205260408120546001600160a01b0390811690831615611d9857611d988184866120aa565b6001600160a01b03811615611dd657611db5600085600080611fa4565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615611e05576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6001600160a01b0383163b15610b2557604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611ea6903390889087908790600401612c88565b6020604051808303816000875af1925050508015611ee1575060408051601f3d908101601f19168201909252611ede91810190612cc5565b60015b611f4a573d808015611f0f576040519150601f19603f3d011682016040523d82523d6000602084013e611f14565b606091505b508051600003611f4257604051633250574960e11b81526001600160a01b0385166004820152602401610535565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611f8657604051633250574960e11b81526001600160a01b0385166004820152602401610535565b5050505050565b611f97838361210e565b6106046000848484611e64565b8080611fb857506001600160a01b03821615155b1561207a576000611fc884611d0b565b90506001600160a01b03831615801590611ff45750826001600160a01b0316816001600160a01b031614155b801561200757506120058184611414565b155b156120305760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610535565b81156120785783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6120b5838383612173565b610604576001600160a01b0383166120e357604051637e27328960e01b815260048101829052602401610535565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610535565b6001600160a01b03821661213857604051633250574960e11b815260006004820152602401610535565b600061214683836000611d6b565b90506001600160a01b03811615610604576040516339e3563760e11b815260006004820152602401610535565b60006001600160a01b038316158015906121d15750826001600160a01b0316846001600160a01b031614806121ad57506121ad8484611414565b806121d157506000828152600460205260409020546001600160a01b038481169116145b949350505050565b82805482825590600052602060002090810192821561222e579160200282015b8281111561222e57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906121f9565b5061223a92915061225f565b5090565b50805460008255600302906000526020600020908101906114869190612274565b5b8082111561223a5760008155600101612260565b5b8082111561223a5780546001600160a01b03191681556000600182018190556002820155600301612275565b6001600160e01b03198116811461148657600080fd5b6000602082840312156122c957600080fd5b8135611444816122a1565b6000815180845260005b818110156122fa576020818501810151868301820152016122de565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061144460208301846122d4565b60006020828403121561233f57600080fd5b5035919050565b6001600160a01b038116811461148657600080fd5b6000806040838503121561236e57600080fd5b823561237981612346565b946020939093013593505050565b60006020828403121561239957600080fd5b813561144481612346565b6000806000606084860312156123b957600080fd5b83356123c481612346565b925060208401356123d481612346565b929592945050506040919091013590565b600080604083850312156123f857600080fd5b823561240381612346565b91506020830135801515811461241857600080fd5b809150509250929050565b600081518084526020840193506020830160005b8281101561247757815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612437565b5093949350505050565b600081518084526020840193506020830160005b828110156124775781516001600160a01b0316865260209586019590910190600101612495565b602081526000825161012060208401526124da6101408401826122d4565b90506020840151601f198483030160408501526124f78282612423565b9150506040840151601f198483030160608501526125158282612481565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161255461010085018215159052565b50610100840151801515610120850152509392505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125a5576125a561256c565b60405290565b60405160e0810167ffffffffffffffff811182821017156125a5576125a561256c565b604051601f8201601f1916810167ffffffffffffffff811182821017156125f7576125f761256c565b604052919050565b60008067ffffffffffffffff84111561261a5761261a61256c565b50601f8301601f191660200161262f816125ce565b91505082815283838301111561264457600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561267157600080fd5b843561267c81612346565b9350602085013561268c81612346565b925060408501359150606085013567ffffffffffffffff8111156126af57600080fd5b8501601f810187136126c057600080fd5b6126cf878235602084016125ff565b91505092959194509250565b600082601f8301126126ec57600080fd5b611444838335602085016125ff565b600067ffffffffffffffff8211156127155761271561256c565b5060051b60200190565b600082601f83011261273057600080fd5b813561274361273e826126fb565b6125ce565b8082825260208201915060208360061b86010192508583111561276557600080fd5b602085015b838110156127c4576040818803121561278257600080fd5b61278a612582565b813561279581612346565b8152602082013560ff811681146127ab57600080fd5b602082810191909152908452929092019160400161276a565b5095945050505050565b600082601f8301126127df57600080fd5b81356127ed61273e826126fb565b8082825260208201915060208360051b86010192508583111561280f57600080fd5b602085015b838110156127c457803561282781612346565b835260209283019201612814565b60006020828403121561284757600080fd5b813567ffffffffffffffff81111561285e57600080fd5b820160e0818503121561287057600080fd5b6128786125ab565b81358152602082013567ffffffffffffffff81111561289657600080fd5b6128a2868285016126db565b602083015250604082013567ffffffffffffffff8111156128c257600080fd5b6128ce8682850161271f565b604083015250606082013567ffffffffffffffff8111156128ee57600080fd5b6128fa868285016127ce565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561293b57600080fd5b823561294681612346565b9150602083013561241881612346565b600181811c9082168061296a57607f821691505b60208210810361298a57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6040820152666574706c61636560c81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561042f5761042f6129d7565b8082018082111561042f5761042f6129d7565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60ff818116838216019081111561042f5761042f6129d7565b634e487b7160e01b600052601260045260246000fd5b600082612b3557612b35612b10565b500690565b600082612b4957612b49612b10565b500490565b808202811582820484141761042f5761042f6129d7565b601f82111561060457806000526020600020601f840160051c81016020851015612b8c5750805b601f840160051c820191505b81811015611f865760008155600101612b98565b815167ffffffffffffffff811115612bc657612bc661256c565b612bda81612bd48454612956565b84612b65565b6020601f821160018114612c0e5760008315612bf65750848201515b600019600385901b1c1916600184901b178455611f86565b600084815260208120601f198516915b82811015612c3e5787850151825560209485019460019092019101612c1e565b5084821015612c5c5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b600060208284031215612c7d57600080fd5b815161144481612346565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612cbb908301846122d4565b9695505050505050565b600060208284031215612cd757600080fd5b8151611444816122a156fea2646970667358221220196efd2875dfc69ac9dfd4ff176f02be1bac0045cc1d181aea6dc39c48785ae364736f6c634300081c0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c8063715018a6116100f9578063abc8c7af11610097578063d0ce736011610071578063d0ce736014610397578063d471cf5d146103aa578063e985e9c5146103bd578063f2fde38b146103d057600080fd5b8063abc8c7af1461035e578063b88d4fde14610371578063c87b56dd1461038457600080fd5b806395d89b41116100d357806395d89b41146103105780639be78f0514610318578063a22cb4651461032b578063a30fb0201461033e57600080fd5b8063715018a6146102e457806382558c2a146102ec5780638da5cb5b146102ff57600080fd5b806323b872dd116101665780635926912211610140578063592691221461028a5780636352211e146102ab57806366666aa9146102be57806370a08231146102d157600080fd5b806323b872dd146102515780633a0432421461026457806342842e0e1461027757600080fd5b8063017d6f99146101ae57806301ffc9a7146101de57806306fdde0314610201578063081812fc14610216578063095ea7b3146102295780631892dd9f1461023e575b600080fd5b600d546101c1906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101f16101ec3660046122b7565b6103e3565b60405190151581526020016101d5565b610209610435565b6040516101d5919061231a565b6101c161022436600461232d565b6104c7565b61023c61023736600461235b565b6104f1565b005b61023c61024c366004612387565b61053e565b61023c61025f3660046123a4565b610568565b6101c161027236600461232d565b61064d565b61023c6102853660046123a4565b610658565b61029d61029836600461232d565b610673565b6040519081526020016101d5565b6101c16102b936600461232d565b610688565b600c546101c1906001600160a01b031681565b61029d6102df366004612387565b6106b3565b61023c6106df565b61023c6102fa366004612387565b6106f3565b6006546001600160a01b03166101c1565b61020961071d565b61023c610326366004612387565b61072c565b61023c6103393660046123e5565b610756565b61035161034c36600461232d565b6107b1565b6040516101d591906124bc565b600b546101c1906001600160a01b031681565b61023c61037f36600461265b565b610a3f565b61020961039236600461232d565b610b2b565b61023c6103a536600461232d565b610b3d565b61023c6103b8366004612835565b610c83565b6101f16103cb366004612928565b611414565b61023c6103de366004612387565b61144b565b60006001600160e01b031982166380ac58cd60e01b148061041457506001600160e01b03198216635b5e139f60e01b145b8061042f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461044490612956565b80601f016020809104026020016040519081016040528092919081815260200182805461047090612956565b80156104bd5780601f10610492576101008083540402835291602001916104bd565b820191906000526020600020905b8154815290600101906020018083116104a057829003601f168201915b5050505050905090565b60006104d282611489565b156104e8575050600b546001600160a01b031690565b61042f826114f9565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b610546611522565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b03163314801561058c5750600b546001600160a01b031615155b6105a85760405162461bcd60e51b815260040161053590612990565b6105b181611489565b15610609576105c0818361154f565b6001600160a01b03831660009081526008602052604081208054600192906105e99084906129ed565b9091555050600b54610604906001600160a01b03168261155d565b505050565b600b546001600160a01b031661061e826114f9565b6001600160a01b03161461064257600b54610642906001600160a01b03168261155d565b610604838383611568565b600061042f826115ed565b61060483838360405180602001604052806000815250610a3f565b600061067e826107b1565b6080015192915050565b600061069382611489565b156106aa5761042f6106a4836115f8565b8361185a565b61042f826115ed565b6001600160a01b0381166000908152600860205260408120546106d583611c5a565b61042f9190612a00565b6106e7611522565b6106f16000611ca2565b565b6106fb611522565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60606001805461044490612956565b610734611522565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610535565b610804604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b600061080f836115f8565b9050600081116108615760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610535565b600081815260076020526040908190208151610120810190925280548290829061088a90612956565b80601f01602080910402602001604051908101604052809291908181526020018280546108b690612956565b80156109035780601f106108d857610100808354040283529160200191610903565b820191906000526020600020905b8154815290600101906020018083116108e657829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610986576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610931565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109e757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116109c9575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b600b546001600160a01b031633148015610a635750600b546001600160a01b031615155b610a7f5760405162461bcd60e51b815260040161053590612990565b610a8882611489565b15610ae057610a97828461154f565b6001600160a01b0384166000908152600860205260408120805460019290610ac09084906129ed565b9091555050600b54610adb906001600160a01b03168361155d565b610b25565b600b546001600160a01b0316610af5836114f9565b6001600160a01b031614610b1957600b54610b19906001600160a01b03168361155d565b610b2584848484611cf4565b50505050565b6060610b36826107b1565b5192915050565b600d546001600160a01b031633148015610b615750600d546001600160a01b031615155b610b7d5760405162461bcd60e51b815260040161053590612a13565b60008111610b9d5760405162461bcd60e51b815260040161053590612a55565b60008181526007602081905260409091200154610100900460ff16610bd45760405162461bcd60e51b815260040161053590612aa0565b60008181526007602081905260409091209081015460ff1615610c455760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610535565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b600d546001600160a01b031633148015610ca75750600d546001600160a01b031615155b610cc35760405162461bcd60e51b815260040161053590612a13565b805180610ce25760405162461bcd60e51b815260040161053590612a55565b60008181526007602081905260409091200154610100900460ff1615610d585760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610535565b600c546001600160a01b0316610db05760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610535565b60008260c0015111610e1a5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610535565b6000805b836040015151811015610ee55760006001600160a01b031684604001518281518110610e4c57610e4c612ae1565b6020026020010151600001516001600160a01b031603610eae5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610535565b83604001518181518110610ec457610ec4612ae1565b60200260200101516020015182610edb9190612af7565b9150600101610e1e565b508060ff16606414610f435760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610535565b60008360a0015111610fae5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610535565b60648360c00151610fbf9190612b26565b156110245760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610535565b60808301511561109d57600c54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b15801561108457600080fd5b505af1158015611098573d6000803e3d6000fd5b505050505b600a5460c08401516000906001906110b59084612a00565b6110bf91906129ed565b9050600085604001515167ffffffffffffffff8111156110e1576110e161256c565b60405190808252806020026020018201604052801561113f57816020015b61112c604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b8152602001906001900390816110ff5790505b5090506000839050600060648860c0015161115a9190612b3a565b905060005b8860400151518110156112945760008960400151828151811061118457611184612ae1565b602002602001015190506000816020015160ff16846111a39190612b4e565b9050600060016111b38388612a00565b6111bd91906129ed565b905060405180606001604052808d6040015186815181106111e0576111e0612ae1565b6020026020010151600001516001600160a01b031681526020018781526020018281525087858151811061121657611216612ae1565b602090810291909101015261122c816001612a00565b9550816008600089878151811061124557611245612ae1565b6020026020010151600001516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546112809190612a00565b90915550506001909301925061115f915050565b5060008781526007602090815260409091209089015181906112b69082612bac565b50606089015180516112d29160028401916020909101906121d9565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff191661010017905561131460018201600061223e565b60005b8451811015611391578160010185828151811061133657611336612ae1565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611317565b508860c00151600a60008282546113a89190612a00565b90915550506009805460018101825560009182527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600b546000906001600160a01b03838116911614806114445750826001600160a01b0316826001600160a01b0316145b9392505050565b611453611522565b6001600160a01b03811661147d57604051631e4fbdf760e01b815260006004820152602401610535565b61148681611ca2565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa9250505080156114e4575060408051601f3d908101601f191682019092526114e191810190612c6b565b60015b6114f057506001919050565b50600092915050565b600061150482611d0b565b506000828152600460205260409020546001600160a01b031661042f565b6006546001600160a01b031633146106f15760405163118cdaa760e01b8152336004820152602401610535565b6115598183611d44565b5050565b611559828233611d5e565b6001600160a01b03821661159257604051633250574960e11b815260006004820152602401610535565b600061159f838333611d6b565b9050836001600160a01b0316816001600160a01b031614610b25576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610535565b600061042f82611d0b565b6000805b6009548110156114f05760006009828154811061161b5761161b612ae1565b906000526020600020015490506000600760008381526020019081526020016000206040518061012001604052908160008201805461165990612956565b80601f016020809104026020016040519081016040528092919081815260200182805461168590612956565b80156116d25780601f106116a7576101008083540402835291602001916116d2565b820191906000526020600020905b8154815290600101906020018083116116b557829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611755576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611700565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156117b657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611798575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c090920191909152810151909150851080159061182757508060c001518511155b801561183557508060e00151155b801561184357508061010001515b1561185057509392505050565b50506001016115fc565b600080831161187b5760405162461bcd60e51b815260040161053590612a55565b60008381526007602081905260409091200154610100900460ff166118b25760405162461bcd60e51b815260040161053590612aa0565b6000838152600760205260409020600501548210156119395760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610535565b6000838152600760205260409020600601548211156119c05760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610535565b600083815260076020526040808220815161012081019092528054829082906119e890612956565b80601f0160208091040260200160405190810160405280929190818152602001828054611a1490612956565b8015611a615780601f10611a3657610100808354040283529160200191611a61565b820191906000526020600020905b815481529060010190602001808311611a4457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611ae4576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611a8f565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611b4557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b27575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b816020015151811015611bfb57600082602001518281518110611bc057611bc0612ae1565b6020026020010151905084816020015111158015611be2575080604001518511155b15611bf25751925061042f915050565b50600101611b9b565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610535565b60006001600160a01b038216611c86576040516322718ad960e21b815260006004820152602401610535565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b611cff848484610568565b610b2584848484611e64565b6000818152600260205260408120546001600160a01b03168061042f57604051637e27328960e01b815260048101849052602401610535565b611559828260405180602001604052806000815250611f8d565b6106048383836001611fa4565b6000828152600260205260408120546001600160a01b0390811690831615611d9857611d988184866120aa565b6001600160a01b03811615611dd657611db5600085600080611fa4565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615611e05576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6001600160a01b0383163b15610b2557604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290611ea6903390889087908790600401612c88565b6020604051808303816000875af1925050508015611ee1575060408051601f3d908101601f19168201909252611ede91810190612cc5565b60015b611f4a573d808015611f0f576040519150601f19603f3d011682016040523d82523d6000602084013e611f14565b606091505b508051600003611f4257604051633250574960e11b81526001600160a01b0385166004820152602401610535565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14611f8657604051633250574960e11b81526001600160a01b0385166004820152602401610535565b5050505050565b611f97838361210e565b6106046000848484611e64565b8080611fb857506001600160a01b03821615155b1561207a576000611fc884611d0b565b90506001600160a01b03831615801590611ff45750826001600160a01b0316816001600160a01b031614155b801561200757506120058184611414565b155b156120305760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610535565b81156120785783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b6120b5838383612173565b610604576001600160a01b0383166120e357604051637e27328960e01b815260048101829052602401610535565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610535565b6001600160a01b03821661213857604051633250574960e11b815260006004820152602401610535565b600061214683836000611d6b565b90506001600160a01b03811615610604576040516339e3563760e11b815260006004820152602401610535565b60006001600160a01b038316158015906121d15750826001600160a01b0316846001600160a01b031614806121ad57506121ad8484611414565b806121d157506000828152600460205260409020546001600160a01b038481169116145b949350505050565b82805482825590600052602060002090810192821561222e579160200282015b8281111561222e57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906121f9565b5061223a92915061225f565b5090565b50805460008255600302906000526020600020908101906114869190612274565b5b8082111561223a5760008155600101612260565b5b8082111561223a5780546001600160a01b03191681556000600182018190556002820155600301612275565b6001600160e01b03198116811461148657600080fd5b6000602082840312156122c957600080fd5b8135611444816122a1565b6000815180845260005b818110156122fa576020818501810151868301820152016122de565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061144460208301846122d4565b60006020828403121561233f57600080fd5b5035919050565b6001600160a01b038116811461148657600080fd5b6000806040838503121561236e57600080fd5b823561237981612346565b946020939093013593505050565b60006020828403121561239957600080fd5b813561144481612346565b6000806000606084860312156123b957600080fd5b83356123c481612346565b925060208401356123d481612346565b929592945050506040919091013590565b600080604083850312156123f857600080fd5b823561240381612346565b91506020830135801515811461241857600080fd5b809150509250929050565b600081518084526020840193506020830160005b8281101561247757815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612437565b5093949350505050565b600081518084526020840193506020830160005b828110156124775781516001600160a01b0316865260209586019590910190600101612495565b602081526000825161012060208401526124da6101408401826122d4565b90506020840151601f198483030160408501526124f78282612423565b9150506040840151601f198483030160608501526125158282612481565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161255461010085018215159052565b50610100840151801515610120850152509392505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125a5576125a561256c565b60405290565b60405160e0810167ffffffffffffffff811182821017156125a5576125a561256c565b604051601f8201601f1916810167ffffffffffffffff811182821017156125f7576125f761256c565b604052919050565b60008067ffffffffffffffff84111561261a5761261a61256c565b50601f8301601f191660200161262f816125ce565b91505082815283838301111561264457600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561267157600080fd5b843561267c81612346565b9350602085013561268c81612346565b925060408501359150606085013567ffffffffffffffff8111156126af57600080fd5b8501601f810187136126c057600080fd5b6126cf878235602084016125ff565b91505092959194509250565b600082601f8301126126ec57600080fd5b611444838335602085016125ff565b600067ffffffffffffffff8211156127155761271561256c565b5060051b60200190565b600082601f83011261273057600080fd5b813561274361273e826126fb565b6125ce565b8082825260208201915060208360061b86010192508583111561276557600080fd5b602085015b838110156127c4576040818803121561278257600080fd5b61278a612582565b813561279581612346565b8152602082013560ff811681146127ab57600080fd5b602082810191909152908452929092019160400161276a565b5095945050505050565b600082601f8301126127df57600080fd5b81356127ed61273e826126fb565b8082825260208201915060208360051b86010192508583111561280f57600080fd5b602085015b838110156127c457803561282781612346565b835260209283019201612814565b60006020828403121561284757600080fd5b813567ffffffffffffffff81111561285e57600080fd5b820160e0818503121561287057600080fd5b6128786125ab565b81358152602082013567ffffffffffffffff81111561289657600080fd5b6128a2868285016126db565b602083015250604082013567ffffffffffffffff8111156128c257600080fd5b6128ce8682850161271f565b604083015250606082013567ffffffffffffffff8111156128ee57600080fd5b6128fa868285016127ce565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561293b57600080fd5b823561294681612346565b9150602083013561241881612346565b600181811c9082168061296a57607f821691505b60208210810361298a57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6040820152666574706c61636560c81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561042f5761042f6129d7565b8082018082111561042f5761042f6129d7565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60ff818116838216019081111561042f5761042f6129d7565b634e487b7160e01b600052601260045260246000fd5b600082612b3557612b35612b10565b500690565b600082612b4957612b49612b10565b500490565b808202811582820484141761042f5761042f6129d7565b601f82111561060457806000526020600020601f840160051c81016020851015612b8c5750805b601f840160051c820191505b81811015611f865760008155600101612b98565b815167ffffffffffffffff811115612bc657612bc661256c565b612bda81612bd48454612956565b84612b65565b6020601f821160018114612c0e5760008315612bf65750848201515b600019600385901b1c1916600184901b178455611f86565b600084815260208120601f198516915b82811015612c3e5787850151825560209485019460019092019101612c1e565b5084821015612c5c5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b600060208284031215612c7d57600080fd5b815161144481612346565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612cbb908301846122d4565b9695505050505050565b600060208284031215612cd757600080fd5b8151611444816122a156fea2646970667358221220196efd2875dfc69ac9dfd4ff176f02be1bac0045cc1d181aea6dc39c48785ae364736f6c634300081c0033", + "bytecode": "0x60806040526000600d55600e80546001600160a01b0319908116909155600f80548216905560108054909116905534801561003957600080fd5b50604051613bdd380380613bdd8339810160408190526100589161014a565b8060405180604001604052806008815260200167111959995c9c995960c21b81525060405180604001604052806008815260200167111151915494915160c21b81525081600090816100aa9190610219565b5060016100b78282610219565b5050506001600160a01b0381166100e857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100f1816100f8565b50506102d7565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006020828403121561015c57600080fd5b81516001600160a01b038116811461017357600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806101a457607f821691505b6020821081036101c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561021457806000526020600020601f840160051c810160208510156101f15750805b601f840160051c820191505b8181101561021157600081556001016101fd565b50505b505050565b81516001600160401b038111156102325761023261017a565b610246816102408454610190565b846101ca565b6020601f82116001811461027a57600083156102625750848201515b600019600385901b1c1916600184901b178455610211565b600084815260208120601f198516915b828110156102aa578785015182556020948501946001909201910161028a565b50848210156102c85786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6138f7806102e66000396000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610455578063d0ce736014610468578063d471cf5d1461047b578063e985e9c51461048e578063f2fde38b146104a157600080fd5b8063a30fb02014610409578063abc8c7af1461041c578063b7e62e5d1461042f578063b88d4fde1461044257600080fd5b80638da5cb5b116100e95780638da5cb5b146103ca57806395d89b41146103db5780639be78f05146103e3578063a22cb465146103f657600080fd5b806370a0823114610389578063715018a61461039c57806375229c55146103a457806382558c2a146103b757600080fd5b806342842e0e116101925780635a6aef60116101615780635a6aef60146103235780636352211e1461034357806366666aa9146103565780636ebc8c861461036957600080fd5b806342842e0e146102c95780634a2a1fb0146102dc578063559de7b8146102fd578063592691221461031057600080fd5b8063095ea7b3116101ce578063095ea7b31461027b5780631892dd9f1461029057806323b872dd146102a35780633a043242146102b657600080fd5b8063017d6f991461020057806301ffc9a71461023057806306fdde0314610253578063081812fc14610268575b600080fd5b601054610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024361023e366004612e76565b6104b4565b6040519015158152602001610227565b61025b610506565b6040516102279190612ed9565b610213610276366004612eec565b610598565b61028e610289366004612f1a565b6105c2565b005b61028e61029e366004612f46565b61060f565b61028e6102b1366004612f63565b610639565b6102136102c4366004612eec565b61068f565b61028e6102d7366004612f63565b61069a565b6102ef6102ea366004612fa4565b6106ba565b604051908152602001610227565b61024361030b366004612eec565b610b83565b6102ef61031e366004612eec565b610dbb565b6102ef610331366004612eec565b6000908152600b602052604090205490565b610213610351366004612eec565b610dd0565b600f54610213906001600160a01b031681565b61037c610377366004612eec565b610dfb565b604051610227919061307f565b6102ef610397366004612f46565b610fff565b61028e61102b565b6102ef6103b2366004612eec565b61103f565b61028e6103c5366004612f46565b61104b565b6006546001600160a01b0316610213565b61025b611075565b61028e6103f1366004612f46565b611084565b61028e61040436600461312f565b6110ae565b61037c610417366004612eec565b611109565b600e54610213906001600160a01b031681565b6102ef61043d36600461316d565b61134c565b61028e610450366004613281565b611632565b61025b610463366004612eec565b61168c565b61028e610476366004612eec565b61169e565b61028e61048936600461345b565b6117e4565b61024361049c36600461354e565b611f9f565b61028e6104af366004612f46565b611fcb565b60006001600160e01b031982166380ac58cd60e01b14806104e557506001600160e01b03198216635b5e139f60e01b145b8061050057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600080546105159061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546105419061357c565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b5050505050905090565b60006105a382612009565b156105b9575050600e546001600160a01b031690565b61050082612079565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b6106176120a2565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610606565b6000610500826120cf565b6106b583838360405180602001604052806000815250611632565b505050565b600e546000906001600160a01b0316331480156106e15750600e546001600160a01b031615155b61073d5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610606565b600084815260076020526040808220815161012081019092528054829082906107659061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546107919061357c565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610861576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161080c565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c09091015290506000610921868561134c565b9050846001600160a01b031661093682610dd0565b6001600160a01b0316146109a15760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610606565b6000805b8360400151518110156109f957836040015181815181106109c8576109c86135b6565b60200260200101516001600160a01b0316866001600160a01b0316036109f157600191506109f9565b6001016109a5565b508015610a89576000878152600960205260408120805460019290610a1f9084906135e2565b90915550506000878152600b60205260408120805460019290610a439084906135e2565b9091555050600087815260096020908152604080832054600a9092529091205411610a8457600087815260096020908152604080832054600a909252909120555b610aae565b6000878152600a60205260408120805460019290610aa89084906135e2565b90915550505b610ab782612009565b15610b3357610ac682866120da565b6001600160a01b03861660009081526008602052604090205415610b13576001600160a01b0386166000908152600860205260408120805460019290610b0d9084906135f5565b90915550505b600e54610b29906001600160a01b0316836120e8565b509150610b7c9050565b600e546001600160a01b0316610b4883612079565b6001600160a01b031614610b6c57600e54610b6c906001600160a01b0316836120e8565b610b778686846120f3565b509150505b9392505050565b6000818152600760205260408082208151610120810190925280548392919082908290610baf9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdb9061357c565b8015610c285780601f10610bfd57610100808354040283529160200191610c28565b820191906000526020600020905b815481529060010190602001808311610c0b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610cab576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610c56565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610d0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cee575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c090920191909152810151909150610d835760405162461bcd60e51b815260040161060690613608565b8060a001518160c00151610d9791906135f5565b610da29060016135e2565b6000938452600b60205260409093205490921492915050565b6000610dc682611109565b6080015192915050565b6000610ddb82612009565b15610df257610500610dec8361217e565b836123e0565b610500826120cf565b610e03612d48565b60008281526007602052604080822081516101208101909252805482908290610e2b9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e579061357c565b8015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610f27576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610ed2565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610f8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6a575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c0909201919091528101519091506105005760405162461bcd60e51b815260040161060690613608565b6001600160a01b038116600090815260086020526040812054611021836127e0565b61050091906135e2565b6110336120a2565b61103d6000612828565b565b6000610500823361134c565b6110536120a2565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180546105159061357c565b61108c6120a2565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610606565b611111612d48565b600061111c8361217e565b90506000811161116e5760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610606565b60008181526007602052604090819020815161012081019092528054829082906111979061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546111c39061357c565b80156112105780601f106111e557610100808354040283529160200191611210565b820191906000526020600020905b8154815290600101906020018083116111f357829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611293576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161123e565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156112f457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112d6575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b60008281526007602052604080822081516101208101909252805483929190829082906113789061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546113a49061357c565b80156113f15780601f106113c6576101008083540402835291602001916113f1565b820191906000526020600020905b8154815290600101906020018083116113d457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611474576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161141f565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156114d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114b7575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c09092019190915281015190915061154c5760405162461bcd60e51b815260040161060690613608565b60008060005b8360400151518110156115a65783604001518181518110611575576115756135b6565b60200260200101516001600160a01b0316866001600160a01b03160361159e57600191506115a6565b600101611552565b5080156115c35760008681526009602052604090205491506115d5565b6000868152600a602052604090205491505b8260c001518211156116295760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610606565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610606565b606061169782611109565b5192915050565b6010546001600160a01b0316331480156116c257506010546001600160a01b031615155b6116de5760405162461bcd60e51b815260040161060690613649565b600081116116fe5760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff166117355760405162461bcd60e51b815260040161060690613608565b60008181526007602081905260409091209081015460ff16156117a65760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610606565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b03163314801561180857506010546001600160a01b031615155b6118245760405162461bcd60e51b815260040161060690613649565b8051806118435760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff16156118b95760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610606565b600f546001600160a01b03166119115760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610606565b60008260c001511161197b5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610606565b6000805b836040015151811015611a465760006001600160a01b0316846040015182815181106119ad576119ad6135b6565b6020026020010151600001516001600160a01b031603611a0f5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610606565b83604001518181518110611a2557611a256135b6565b60200260200101516020015182611a3c91906136d6565b915060010161197f565b508060ff16606414611aa45760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610606565b60008360a0015111611b0f5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610606565b60648360c00151611b209190613705565b15611b855760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610606565b608083015115611bfe57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611c1690846135e2565b611c2091906135f5565b9050600085604001515167ffffffffffffffff811115611c4257611c42613192565b604051908082528060200260200182016040528015611ca057816020015b611c8d604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611c605790505b5090506000839050600060648860c00151611cbb9190613719565b905060005b886040015151811015611df557600089604001518281518110611ce557611ce56135b6565b602002602001015190506000816020015160ff1684611d04919061372d565b905060006001611d1483886135e2565b611d1e91906135f5565b905060405180606001604052808d604001518681518110611d4157611d416135b6565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611d7757611d776135b6565b6020908102919091010152611d8d8160016135e2565b95508160086000898781518110611da657611da66135b6565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611de191906135e2565b909155505060019093019250611cc0915050565b506000878152600760209081526040909120908901518190611e17908261378b565b5060608901518051611e33916002840191602090910190612d98565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff1916610100179055611e75600182016000612dfd565b60005b8451811015611ef25781600101858281518110611e9757611e976135b6565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611e78565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d805491929091611f339084906135e2565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610b7c5750506001600160a01b0390811691161490565b611fd36120a2565b6001600160a01b038116611ffd57604051631e4fbdf760e01b815260006004820152602401610606565b61200681612828565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612064575060408051601f3d908101601f191682019092526120619181019061384a565b60015b61207057506001919050565b50600092915050565b60006120848261287a565b506000828152600460205260409020546001600160a01b0316610500565b6006546001600160a01b0316331461103d5760405163118cdaa760e01b8152336004820152602401610606565b60006105008261287a565b6120e481836128b3565b5050565b6120e48282336128cd565b6001600160a01b03821661211d57604051633250574960e11b815260006004820152602401610606565b600061212a8383336128da565b9050836001600160a01b0316816001600160a01b031614612178576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610606565b50505050565b6000805b600c54811015612070576000600c82815481106121a1576121a16135b6565b90600052602060002001549050600060076000838152602001908152602001600020604051806101200160405290816000820180546121df9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461220b9061357c565b80156122585780601f1061222d57610100808354040283529160200191612258565b820191906000526020600020905b81548152906001019060200180831161223b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156122db576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612286565b5050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561233c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161231e575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c09092019190915281015190915085108015906123ad57508060c001518511155b80156123bb57508060e00151155b80156123c957508061010001515b156123d657509392505050565b5050600101612182565b60008083116124015760405162461bcd60e51b81526004016106069061368b565b60008381526007602081905260409091200154610100900460ff166124385760405162461bcd60e51b815260040161060690613608565b6000838152600760205260409020600501548210156124bf5760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610606565b6000838152600760205260409020600601548211156125465760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610606565b6000838152600760205260408082208151610120810190925280548290829061256e9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461259a9061357c565b80156125e75780601f106125bc576101008083540402835291602001916125e7565b820191906000526020600020905b8154815290600101906020018083116125ca57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b8282101561266a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612615565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156126cb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126ad575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b81602001515181101561278157600082602001518281518110612746576127466135b6565b6020026020010151905084816020015111158015612768575080604001518511155b1561277857519250610500915050565b50600101612721565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610606565b60006001600160a01b03821661280c576040516322718ad960e21b815260006004820152602401610606565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050057604051637e27328960e01b815260048101849052602401610606565b6120e48282604051806020016040528060008152506129d3565b6106b583838360016129ea565b6000828152600260205260408120546001600160a01b039081169083161561290757612907818486612af0565b6001600160a01b03811615612945576129246000856000806129ea565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612974576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6129dd8383612b54565b6106b56000848484612bb9565b80806129fe57506001600160a01b03821615155b15612ac0576000612a0e8461287a565b90506001600160a01b03831615801590612a3a5750826001600160a01b0316816001600160a01b031614155b8015612a4d5750612a4b8184611f9f565b155b15612a765760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610606565b8115612abe5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612afb838383612ce2565b6106b5576001600160a01b038316612b2957604051637e27328960e01b815260048101829052602401610606565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610606565b6001600160a01b038216612b7e57604051633250574960e11b815260006004820152602401610606565b6000612b8c838360006128da565b90506001600160a01b038116156106b5576040516339e3563760e11b815260006004820152602401610606565b6001600160a01b0383163b1561217857604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612bfb903390889087908790600401613867565b6020604051808303816000875af1925050508015612c36575060408051601f3d908101601f19168201909252612c33918101906138a4565b60015b612c9f573d808015612c64576040519150601f19603f3d011682016040523d82523d6000602084013e612c69565b606091505b508051600003612c9757604051633250574960e11b81526001600160a01b0385166004820152602401610606565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612cdb57604051633250574960e11b81526001600160a01b0385166004820152602401610606565b5050505050565b60006001600160a01b03831615801590612d405750826001600160a01b0316846001600160a01b03161480612d1c5750612d1c8484611f9f565b80612d4057506000828152600460205260409020546001600160a01b038481169116145b949350505050565b604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612ded579160200282015b82811115612ded57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612db8565b50612df9929150612e1e565b5090565b50805460008255600302906000526020600020908101906120069190612e33565b5b80821115612df95760008155600101612e1f565b5b80821115612df95780546001600160a01b03191681556000600182018190556002820155600301612e34565b6001600160e01b03198116811461200657600080fd5b600060208284031215612e8857600080fd5b8135610b7c81612e60565b6000815180845260005b81811015612eb957602081850181015186830182015201612e9d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b7c6020830184612e93565b600060208284031215612efe57600080fd5b5035919050565b6001600160a01b038116811461200657600080fd5b60008060408385031215612f2d57600080fd5b8235612f3881612f05565b946020939093013593505050565b600060208284031215612f5857600080fd5b8135610b7c81612f05565b600080600060608486031215612f7857600080fd5b8335612f8381612f05565b92506020840135612f9381612f05565b929592945050506040919091013590565b600080600060608486031215612fb957600080fd5b833592506020840135612fcb81612f05565b91506040840135612fdb81612f05565b809150509250925092565b600081518084526020840193506020830160005b8281101561303a57815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612ffa565b5093949350505050565b600081518084526020840193506020830160005b8281101561303a5781516001600160a01b0316865260209586019590910190600101613058565b6020815260008251610120602084015261309d610140840182612e93565b90506020840151601f198483030160408501526130ba8282612fe6565b9150506040840151601f198483030160608501526130d88282613044565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161311761010085018215159052565b50610100840151801515610120850152509392505050565b6000806040838503121561314257600080fd5b823561314d81612f05565b91506020830135801515811461316257600080fd5b809150509250929050565b6000806040838503121561318057600080fd5b82359150602083013561316281612f05565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156131cb576131cb613192565b60405290565b60405160e0810167ffffffffffffffff811182821017156131cb576131cb613192565b604051601f8201601f1916810167ffffffffffffffff8111828210171561321d5761321d613192565b604052919050565b60008067ffffffffffffffff84111561324057613240613192565b50601f8301601f1916602001613255816131f4565b91505082815283838301111561326a57600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561329757600080fd5b84356132a281612f05565b935060208501356132b281612f05565b925060408501359150606085013567ffffffffffffffff8111156132d557600080fd5b8501601f810187136132e657600080fd5b6132f587823560208401613225565b91505092959194509250565b600082601f83011261331257600080fd5b610b7c83833560208501613225565b600067ffffffffffffffff82111561333b5761333b613192565b5060051b60200190565b600082601f83011261335657600080fd5b813561336961336482613321565b6131f4565b8082825260208201915060208360061b86010192508583111561338b57600080fd5b602085015b838110156133ea57604081880312156133a857600080fd5b6133b06131a8565b81356133bb81612f05565b8152602082013560ff811681146133d157600080fd5b6020828101919091529084529290920191604001613390565b5095945050505050565b600082601f83011261340557600080fd5b813561341361336482613321565b8082825260208201915060208360051b86010192508583111561343557600080fd5b602085015b838110156133ea57803561344d81612f05565b83526020928301920161343a565b60006020828403121561346d57600080fd5b813567ffffffffffffffff81111561348457600080fd5b820160e0818503121561349657600080fd5b61349e6131d1565b81358152602082013567ffffffffffffffff8111156134bc57600080fd5b6134c886828501613301565b602083015250604082013567ffffffffffffffff8111156134e857600080fd5b6134f486828501613345565b604083015250606082013567ffffffffffffffff81111561351457600080fd5b613520868285016133f4565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561356157600080fd5b823561356c81612f05565b9150602083013561316281612f05565b600181811c9082168061359057607f821691505b6020821081036135b057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610500576105006135cc565b81810381811115610500576105006135cc565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff8181168382160190811115610500576105006135cc565b634e487b7160e01b600052601260045260246000fd5b600082613714576137146136ef565b500690565b600082613728576137286136ef565b500490565b8082028115828204841417610500576105006135cc565b601f8211156106b557806000526020600020601f840160051c8101602085101561376b5750805b601f840160051c820191505b81811015612cdb5760008155600101613777565b815167ffffffffffffffff8111156137a5576137a5613192565b6137b9816137b3845461357c565b84613744565b6020601f8211600181146137ed57600083156137d55750848201515b600019600385901b1c1916600184901b178455612cdb565b600084815260208120601f198516915b8281101561381d57878501518255602094850194600190920191016137fd565b508482101561383b5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561385c57600080fd5b8151610b7c81612f05565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061389a90830184612e93565b9695505050505050565b6000602082840312156138b657600080fd5b8151610b7c81612e6056fea264697066735822122081d142e672a5c1bd713bf7f477cbdbaf8b7a5a31564697b13fcbb666bbbc162c64736f6c634300081c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610455578063d0ce736014610468578063d471cf5d1461047b578063e985e9c51461048e578063f2fde38b146104a157600080fd5b8063a30fb02014610409578063abc8c7af1461041c578063b7e62e5d1461042f578063b88d4fde1461044257600080fd5b80638da5cb5b116100e95780638da5cb5b146103ca57806395d89b41146103db5780639be78f05146103e3578063a22cb465146103f657600080fd5b806370a0823114610389578063715018a61461039c57806375229c55146103a457806382558c2a146103b757600080fd5b806342842e0e116101925780635a6aef60116101615780635a6aef60146103235780636352211e1461034357806366666aa9146103565780636ebc8c861461036957600080fd5b806342842e0e146102c95780634a2a1fb0146102dc578063559de7b8146102fd578063592691221461031057600080fd5b8063095ea7b3116101ce578063095ea7b31461027b5780631892dd9f1461029057806323b872dd146102a35780633a043242146102b657600080fd5b8063017d6f991461020057806301ffc9a71461023057806306fdde0314610253578063081812fc14610268575b600080fd5b601054610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024361023e366004612e76565b6104b4565b6040519015158152602001610227565b61025b610506565b6040516102279190612ed9565b610213610276366004612eec565b610598565b61028e610289366004612f1a565b6105c2565b005b61028e61029e366004612f46565b61060f565b61028e6102b1366004612f63565b610639565b6102136102c4366004612eec565b61068f565b61028e6102d7366004612f63565b61069a565b6102ef6102ea366004612fa4565b6106ba565b604051908152602001610227565b61024361030b366004612eec565b610b83565b6102ef61031e366004612eec565b610dbb565b6102ef610331366004612eec565b6000908152600b602052604090205490565b610213610351366004612eec565b610dd0565b600f54610213906001600160a01b031681565b61037c610377366004612eec565b610dfb565b604051610227919061307f565b6102ef610397366004612f46565b610fff565b61028e61102b565b6102ef6103b2366004612eec565b61103f565b61028e6103c5366004612f46565b61104b565b6006546001600160a01b0316610213565b61025b611075565b61028e6103f1366004612f46565b611084565b61028e61040436600461312f565b6110ae565b61037c610417366004612eec565b611109565b600e54610213906001600160a01b031681565b6102ef61043d36600461316d565b61134c565b61028e610450366004613281565b611632565b61025b610463366004612eec565b61168c565b61028e610476366004612eec565b61169e565b61028e61048936600461345b565b6117e4565b61024361049c36600461354e565b611f9f565b61028e6104af366004612f46565b611fcb565b60006001600160e01b031982166380ac58cd60e01b14806104e557506001600160e01b03198216635b5e139f60e01b145b8061050057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600080546105159061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546105419061357c565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b5050505050905090565b60006105a382612009565b156105b9575050600e546001600160a01b031690565b61050082612079565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b6106176120a2565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610606565b6000610500826120cf565b6106b583838360405180602001604052806000815250611632565b505050565b600e546000906001600160a01b0316331480156106e15750600e546001600160a01b031615155b61073d5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610606565b600084815260076020526040808220815161012081019092528054829082906107659061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546107919061357c565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610861576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161080c565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c09091015290506000610921868561134c565b9050846001600160a01b031661093682610dd0565b6001600160a01b0316146109a15760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610606565b6000805b8360400151518110156109f957836040015181815181106109c8576109c86135b6565b60200260200101516001600160a01b0316866001600160a01b0316036109f157600191506109f9565b6001016109a5565b508015610a89576000878152600960205260408120805460019290610a1f9084906135e2565b90915550506000878152600b60205260408120805460019290610a439084906135e2565b9091555050600087815260096020908152604080832054600a9092529091205411610a8457600087815260096020908152604080832054600a909252909120555b610aae565b6000878152600a60205260408120805460019290610aa89084906135e2565b90915550505b610ab782612009565b15610b3357610ac682866120da565b6001600160a01b03861660009081526008602052604090205415610b13576001600160a01b0386166000908152600860205260408120805460019290610b0d9084906135f5565b90915550505b600e54610b29906001600160a01b0316836120e8565b509150610b7c9050565b600e546001600160a01b0316610b4883612079565b6001600160a01b031614610b6c57600e54610b6c906001600160a01b0316836120e8565b610b778686846120f3565b509150505b9392505050565b6000818152600760205260408082208151610120810190925280548392919082908290610baf9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdb9061357c565b8015610c285780601f10610bfd57610100808354040283529160200191610c28565b820191906000526020600020905b815481529060010190602001808311610c0b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610cab576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610c56565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610d0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cee575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c090920191909152810151909150610d835760405162461bcd60e51b815260040161060690613608565b8060a001518160c00151610d9791906135f5565b610da29060016135e2565b6000938452600b60205260409093205490921492915050565b6000610dc682611109565b6080015192915050565b6000610ddb82612009565b15610df257610500610dec8361217e565b836123e0565b610500826120cf565b610e03612d48565b60008281526007602052604080822081516101208101909252805482908290610e2b9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e579061357c565b8015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610f27576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610ed2565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610f8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6a575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c0909201919091528101519091506105005760405162461bcd60e51b815260040161060690613608565b6001600160a01b038116600090815260086020526040812054611021836127e0565b61050091906135e2565b6110336120a2565b61103d6000612828565b565b6000610500823361134c565b6110536120a2565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180546105159061357c565b61108c6120a2565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610606565b611111612d48565b600061111c8361217e565b90506000811161116e5760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610606565b60008181526007602052604090819020815161012081019092528054829082906111979061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546111c39061357c565b80156112105780601f106111e557610100808354040283529160200191611210565b820191906000526020600020905b8154815290600101906020018083116111f357829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611293576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161123e565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156112f457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112d6575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b60008281526007602052604080822081516101208101909252805483929190829082906113789061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546113a49061357c565b80156113f15780601f106113c6576101008083540402835291602001916113f1565b820191906000526020600020905b8154815290600101906020018083116113d457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611474576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161141f565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156114d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114b7575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c09092019190915281015190915061154c5760405162461bcd60e51b815260040161060690613608565b60008060005b8360400151518110156115a65783604001518181518110611575576115756135b6565b60200260200101516001600160a01b0316866001600160a01b03160361159e57600191506115a6565b600101611552565b5080156115c35760008681526009602052604090205491506115d5565b6000868152600a602052604090205491505b8260c001518211156116295760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610606565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610606565b606061169782611109565b5192915050565b6010546001600160a01b0316331480156116c257506010546001600160a01b031615155b6116de5760405162461bcd60e51b815260040161060690613649565b600081116116fe5760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff166117355760405162461bcd60e51b815260040161060690613608565b60008181526007602081905260409091209081015460ff16156117a65760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610606565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b03163314801561180857506010546001600160a01b031615155b6118245760405162461bcd60e51b815260040161060690613649565b8051806118435760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff16156118b95760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610606565b600f546001600160a01b03166119115760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610606565b60008260c001511161197b5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610606565b6000805b836040015151811015611a465760006001600160a01b0316846040015182815181106119ad576119ad6135b6565b6020026020010151600001516001600160a01b031603611a0f5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610606565b83604001518181518110611a2557611a256135b6565b60200260200101516020015182611a3c91906136d6565b915060010161197f565b508060ff16606414611aa45760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610606565b60008360a0015111611b0f5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610606565b60648360c00151611b209190613705565b15611b855760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610606565b608083015115611bfe57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611c1690846135e2565b611c2091906135f5565b9050600085604001515167ffffffffffffffff811115611c4257611c42613192565b604051908082528060200260200182016040528015611ca057816020015b611c8d604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611c605790505b5090506000839050600060648860c00151611cbb9190613719565b905060005b886040015151811015611df557600089604001518281518110611ce557611ce56135b6565b602002602001015190506000816020015160ff1684611d04919061372d565b905060006001611d1483886135e2565b611d1e91906135f5565b905060405180606001604052808d604001518681518110611d4157611d416135b6565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611d7757611d776135b6565b6020908102919091010152611d8d8160016135e2565b95508160086000898781518110611da657611da66135b6565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611de191906135e2565b909155505060019093019250611cc0915050565b506000878152600760209081526040909120908901518190611e17908261378b565b5060608901518051611e33916002840191602090910190612d98565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff1916610100179055611e75600182016000612dfd565b60005b8451811015611ef25781600101858281518110611e9757611e976135b6565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611e78565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d805491929091611f339084906135e2565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610b7c5750506001600160a01b0390811691161490565b611fd36120a2565b6001600160a01b038116611ffd57604051631e4fbdf760e01b815260006004820152602401610606565b61200681612828565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612064575060408051601f3d908101601f191682019092526120619181019061384a565b60015b61207057506001919050565b50600092915050565b60006120848261287a565b506000828152600460205260409020546001600160a01b0316610500565b6006546001600160a01b0316331461103d5760405163118cdaa760e01b8152336004820152602401610606565b60006105008261287a565b6120e481836128b3565b5050565b6120e48282336128cd565b6001600160a01b03821661211d57604051633250574960e11b815260006004820152602401610606565b600061212a8383336128da565b9050836001600160a01b0316816001600160a01b031614612178576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610606565b50505050565b6000805b600c54811015612070576000600c82815481106121a1576121a16135b6565b90600052602060002001549050600060076000838152602001908152602001600020604051806101200160405290816000820180546121df9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461220b9061357c565b80156122585780601f1061222d57610100808354040283529160200191612258565b820191906000526020600020905b81548152906001019060200180831161223b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156122db576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612286565b5050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561233c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161231e575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c09092019190915281015190915085108015906123ad57508060c001518511155b80156123bb57508060e00151155b80156123c957508061010001515b156123d657509392505050565b5050600101612182565b60008083116124015760405162461bcd60e51b81526004016106069061368b565b60008381526007602081905260409091200154610100900460ff166124385760405162461bcd60e51b815260040161060690613608565b6000838152600760205260409020600501548210156124bf5760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610606565b6000838152600760205260409020600601548211156125465760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610606565b6000838152600760205260408082208151610120810190925280548290829061256e9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461259a9061357c565b80156125e75780601f106125bc576101008083540402835291602001916125e7565b820191906000526020600020905b8154815290600101906020018083116125ca57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b8282101561266a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612615565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156126cb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126ad575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b81602001515181101561278157600082602001518281518110612746576127466135b6565b6020026020010151905084816020015111158015612768575080604001518511155b1561277857519250610500915050565b50600101612721565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610606565b60006001600160a01b03821661280c576040516322718ad960e21b815260006004820152602401610606565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050057604051637e27328960e01b815260048101849052602401610606565b6120e48282604051806020016040528060008152506129d3565b6106b583838360016129ea565b6000828152600260205260408120546001600160a01b039081169083161561290757612907818486612af0565b6001600160a01b03811615612945576129246000856000806129ea565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612974576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6129dd8383612b54565b6106b56000848484612bb9565b80806129fe57506001600160a01b03821615155b15612ac0576000612a0e8461287a565b90506001600160a01b03831615801590612a3a5750826001600160a01b0316816001600160a01b031614155b8015612a4d5750612a4b8184611f9f565b155b15612a765760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610606565b8115612abe5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612afb838383612ce2565b6106b5576001600160a01b038316612b2957604051637e27328960e01b815260048101829052602401610606565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610606565b6001600160a01b038216612b7e57604051633250574960e11b815260006004820152602401610606565b6000612b8c838360006128da565b90506001600160a01b038116156106b5576040516339e3563760e11b815260006004820152602401610606565b6001600160a01b0383163b1561217857604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612bfb903390889087908790600401613867565b6020604051808303816000875af1925050508015612c36575060408051601f3d908101601f19168201909252612c33918101906138a4565b60015b612c9f573d808015612c64576040519150601f19603f3d011682016040523d82523d6000602084013e612c69565b606091505b508051600003612c9757604051633250574960e11b81526001600160a01b0385166004820152602401610606565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612cdb57604051633250574960e11b81526001600160a01b0385166004820152602401610606565b5050505050565b60006001600160a01b03831615801590612d405750826001600160a01b0316846001600160a01b03161480612d1c5750612d1c8484611f9f565b80612d4057506000828152600460205260409020546001600160a01b038481169116145b949350505050565b604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612ded579160200282015b82811115612ded57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612db8565b50612df9929150612e1e565b5090565b50805460008255600302906000526020600020908101906120069190612e33565b5b80821115612df95760008155600101612e1f565b5b80821115612df95780546001600160a01b03191681556000600182018190556002820155600301612e34565b6001600160e01b03198116811461200657600080fd5b600060208284031215612e8857600080fd5b8135610b7c81612e60565b6000815180845260005b81811015612eb957602081850181015186830182015201612e9d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b7c6020830184612e93565b600060208284031215612efe57600080fd5b5035919050565b6001600160a01b038116811461200657600080fd5b60008060408385031215612f2d57600080fd5b8235612f3881612f05565b946020939093013593505050565b600060208284031215612f5857600080fd5b8135610b7c81612f05565b600080600060608486031215612f7857600080fd5b8335612f8381612f05565b92506020840135612f9381612f05565b929592945050506040919091013590565b600080600060608486031215612fb957600080fd5b833592506020840135612fcb81612f05565b91506040840135612fdb81612f05565b809150509250925092565b600081518084526020840193506020830160005b8281101561303a57815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612ffa565b5093949350505050565b600081518084526020840193506020830160005b8281101561303a5781516001600160a01b0316865260209586019590910190600101613058565b6020815260008251610120602084015261309d610140840182612e93565b90506020840151601f198483030160408501526130ba8282612fe6565b9150506040840151601f198483030160608501526130d88282613044565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161311761010085018215159052565b50610100840151801515610120850152509392505050565b6000806040838503121561314257600080fd5b823561314d81612f05565b91506020830135801515811461316257600080fd5b809150509250929050565b6000806040838503121561318057600080fd5b82359150602083013561316281612f05565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156131cb576131cb613192565b60405290565b60405160e0810167ffffffffffffffff811182821017156131cb576131cb613192565b604051601f8201601f1916810167ffffffffffffffff8111828210171561321d5761321d613192565b604052919050565b60008067ffffffffffffffff84111561324057613240613192565b50601f8301601f1916602001613255816131f4565b91505082815283838301111561326a57600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561329757600080fd5b84356132a281612f05565b935060208501356132b281612f05565b925060408501359150606085013567ffffffffffffffff8111156132d557600080fd5b8501601f810187136132e657600080fd5b6132f587823560208401613225565b91505092959194509250565b600082601f83011261331257600080fd5b610b7c83833560208501613225565b600067ffffffffffffffff82111561333b5761333b613192565b5060051b60200190565b600082601f83011261335657600080fd5b813561336961336482613321565b6131f4565b8082825260208201915060208360061b86010192508583111561338b57600080fd5b602085015b838110156133ea57604081880312156133a857600080fd5b6133b06131a8565b81356133bb81612f05565b8152602082013560ff811681146133d157600080fd5b6020828101919091529084529290920191604001613390565b5095945050505050565b600082601f83011261340557600080fd5b813561341361336482613321565b8082825260208201915060208360051b86010192508583111561343557600080fd5b602085015b838110156133ea57803561344d81612f05565b83526020928301920161343a565b60006020828403121561346d57600080fd5b813567ffffffffffffffff81111561348457600080fd5b820160e0818503121561349657600080fd5b61349e6131d1565b81358152602082013567ffffffffffffffff8111156134bc57600080fd5b6134c886828501613301565b602083015250604082013567ffffffffffffffff8111156134e857600080fd5b6134f486828501613345565b604083015250606082013567ffffffffffffffff81111561351457600080fd5b613520868285016133f4565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561356157600080fd5b823561356c81612f05565b9150602083013561316281612f05565b600181811c9082168061359057607f821691505b6020821081036135b057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610500576105006135cc565b81810381811115610500576105006135cc565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff8181168382160190811115610500576105006135cc565b634e487b7160e01b600052601260045260246000fd5b600082613714576137146136ef565b500690565b600082613728576137286136ef565b500490565b8082028115828204841417610500576105006135cc565b601f8211156106b557806000526020600020601f840160051c8101602085101561376b5750805b601f840160051c820191505b81811015612cdb5760008155600101613777565b815167ffffffffffffffff8111156137a5576137a5613192565b6137b9816137b3845461357c565b84613744565b6020601f8211600181146137ed57600083156137d55750848201515b600019600385901b1c1916600184901b178455612cdb565b600084815260208120601f198516915b8281101561381d57878501518255602094850194600190920191016137fd565b508482101561383b5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561385c57600080fd5b8151610b7c81612f05565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061389a90830184612e93565b9695505050505050565b6000602082840312156138b657600080fd5b8151610b7c81612e6056fea264697066735822122081d142e672a5c1bd713bf7f477cbdbaf8b7a5a31564697b13fcbb666bbbc162c64736f6c634300081c0033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/integration-tests/src/abi/Marketplace.json b/integration-tests/src/abi/Marketplace.json index 05bf79e..c5a2fa2 100644 --- a/integration-tests/src/abi/Marketplace.json +++ b/integration-tests/src/abi/Marketplace.json @@ -85,6 +85,12 @@ "name": "seller", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "contractId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -137,12 +143,18 @@ "inputs": [ { "internalType": "uint256", - "name": "_tokenId", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "buyNextToken", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", "type": "uint256" } ], - "name": "buyToken", - "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -179,6 +191,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_contractId", + "type": "uint256" + } + ], + "name": "tokenPriceForCaller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -206,8 +237,8 @@ "type": "function" } ], - "bytecode": "0x60806040526004805460ff60a01b1916600560a11b17905534801561002357600080fd5b50604051610ffb380380610ffb833981016040819052610042916101f4565b836001600160a01b03811661007257604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61007b81610188565b506001600160a01b0383166100e15760405162461bcd60e51b815260206004820152602660248201527f4d61726b6574706c6163653a205553442045524332302061646472657373206960448201526573207a65726f60d01b6064820152608401610069565b6001600160a01b0381166101455760405162461bcd60e51b815260206004820152602560248201527f4d61726b6574706c6163653a2044656665727265642061646472657373206973604482015264207a65726f60d81b6064820152608401610069565b600180546001600160a01b039485166001600160a01b03199182161790915560028054938516938216939093179092556003805491909316911617905550610248565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146101ef57600080fd5b919050565b6000806000806080858703121561020a57600080fd5b610213856101d8565b9350610221602086016101d8565b925061022f604086016101d8565b915061023d606086016101d8565b905092959194509250565b610da4806102576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806382558c2a1161005b57806382558c2a146101005780638da5cb5b14610113578063b7b2e45414610124578063f2fde38b1461013757600080fd5b80632d296bf11461008d5780634bd9760f146100a2578063715018a6146100d25780637c3a00fd146100da575b600080fd5b6100a061009b3660046108ba565b61014a565b005b6001546100b5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a0610692565b6004546100ee90600160a01b900460ff1681565b60405160ff90911681526020016100c9565b6100a061010e3660046108e8565b6106a6565b6000546001600160a01b03166100b5565b6100a061013236600461090c565b6106d0565b6100a06101453660046108e8565b6107d2565b6004546001600160a01b03166101a75760405162461bcd60e51b815260206004820181905260248201527f4d61726b6574706c6163653a2052657761726420706f6f6c206e6f742073657460448201526064015b60405180910390fd5b6003546040516305187d8160e51b8152600481018390526001600160a01b0390911690600090829063a30fb02090602401600060405180830381865afa1580156101f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261021d9190810190610b8f565b9050336000805b83604001515181101561027857826001600160a01b03168460400151828151811061025157610251610ca5565b60200260200101516001600160a01b0316036102705760019150610278565b600101610224565b506040516331a9108f60e11b8152600481018690526000906001600160a01b03861690636352211e90602401602060405180830381865afa1580156102c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e59190610cbb565b6000878152600560205260408120549192509060ff1615801561030c575060008560600151115b6001549091506001600160a01b031660008461032c578660800151610348565b6103398760800151610810565b87608001516103489190610cee565b604051636eb1769f60e11b815233600482015230602482015290915081906001600160a01b0384169063dd62ed3e90604401602060405180830381865afa158015610397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bb9190610d01565b10156104155760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574706c6163653a20496e73756666696369656e7420616c6c6f77616044820152626e636560e81b606482015260840161019e565b60808701516040516323b872dd60e01b81526001600160a01b03888116600483015286811660248301526044820192909252908316906323b872dd906064016020604051808303816000875af1158015610473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104979190610d1a565b50841561053657816001600160a01b03166323b872dd87306104bc8b60800151610810565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af1158015610510573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105349190610d1a565b505b6003546040516323b872dd60e01b81526001600160a01b0386811660048301528881166024830152604482018c9052909116906323b872dd90606401600060405180830381600087803b15801561058c57600080fd5b505af11580156105a0573d6000803e3d6000fd5b505050508215610619576004805460608901516040516307420a4160e01b81526001600160a01b038a81169482019490945260248101919091529116906307420a4190604401600060405180830381600087803b15801561060057600080fd5b505af1158015610614573d6000803e3d6000fd5b505050505b600089815260056020908152604091829020805460ff19166001179055608089015182518c8152918201529081018290526001600160a01b0385811691908816907f8692cf5ba66abd64f88cdc1ffa0ee9d9c21ee2d999322a20445ae32393394e3e9060600160405180910390a3505050505050505050565b61069a61083d565b6106a4600061086a565b565b6106ae61083d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6106d861083d565b60008160ff16116107455760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d75737420604482015270062652067726561746572207468616e203607c1b606482015260840161019e565b60648160ff1611156107b25760405162461bcd60e51b815260206004820152603060248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d7573742060448201526f06265206c657373207468616e203130360841b606482015260840161019e565b6004805460ff909216600160a01b0260ff60a01b19909216919091179055565b6107da61083d565b6001600160a01b03811661080457604051631e4fbdf760e01b81526000600482015260240161019e565b61080d8161086a565b50565b60045460009060649061082d90600160a01b900460ff1684610d35565b6108379190610d4c565b92915050565b6000546001600160a01b031633146106a45760405163118cdaa760e01b815233600482015260240161019e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156108cc57600080fd5b5035919050565b6001600160a01b038116811461080d57600080fd5b6000602082840312156108fa57600080fd5b8135610905816108d3565b9392505050565b60006020828403121561091e57600080fd5b813560ff8116811461090557600080fd5b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156109685761096861092f565b60405290565b604051610120810167ffffffffffffffff811182821017156109685761096861092f565b604051601f8201601f1916810167ffffffffffffffff811182821017156109bb576109bb61092f565b604052919050565b600082601f8301126109d457600080fd5b815167ffffffffffffffff8111156109ee576109ee61092f565b610a01601f8201601f1916602001610992565b818152846020838601011115610a1657600080fd5b60005b82811015610a3557602081860181015183830182015201610a19565b506000918101602001919091529392505050565b600067ffffffffffffffff821115610a6357610a6361092f565b5060051b60200190565b600082601f830112610a7e57600080fd5b8151610a91610a8c82610a49565b610992565b80828252602082019150602060608402860101925085831115610ab357600080fd5b602085015b83811015610b095760608188031215610ad057600080fd5b610ad8610945565b8151610ae3816108d3565b815260208281015181830152604080840151908301529084529290920191606001610ab8565b5095945050505050565b600082601f830112610b2457600080fd5b8151610b32610a8c82610a49565b8082825260208201915060208360051b860101925085831115610b5457600080fd5b602085015b83811015610b09578051610b6c816108d3565b835260209283019201610b59565b80518015158114610b8a57600080fd5b919050565b600060208284031215610ba157600080fd5b815167ffffffffffffffff811115610bb857600080fd5b82016101208185031215610bcb57600080fd5b610bd361096e565b815167ffffffffffffffff811115610bea57600080fd5b610bf6868285016109c3565b825250602082015167ffffffffffffffff811115610c1357600080fd5b610c1f86828501610a6d565b602083015250604082015167ffffffffffffffff811115610c3f57600080fd5b610c4b86828501610b13565b604083015250606082810151908201526080808301519082015260a0808301519082015260c08083015190820152610c8560e08301610b7a565b60e0820152610c976101008301610b7a565b610100820152949350505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610ccd57600080fd5b8151610905816108d3565b634e487b7160e01b600052601160045260246000fd5b8082018082111561083757610837610cd8565b600060208284031215610d1357600080fd5b5051919050565b600060208284031215610d2c57600080fd5b61090582610b7a565b808202811582820484141761083757610837610cd8565b600082610d6957634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220dab3e62c6e21985e054bde3b954768c0e4c5c15bef413ff2013b9047dea5dbcf64736f6c634300081c0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c806382558c2a1161005b57806382558c2a146101005780638da5cb5b14610113578063b7b2e45414610124578063f2fde38b1461013757600080fd5b80632d296bf11461008d5780634bd9760f146100a2578063715018a6146100d25780637c3a00fd146100da575b600080fd5b6100a061009b3660046108ba565b61014a565b005b6001546100b5906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a0610692565b6004546100ee90600160a01b900460ff1681565b60405160ff90911681526020016100c9565b6100a061010e3660046108e8565b6106a6565b6000546001600160a01b03166100b5565b6100a061013236600461090c565b6106d0565b6100a06101453660046108e8565b6107d2565b6004546001600160a01b03166101a75760405162461bcd60e51b815260206004820181905260248201527f4d61726b6574706c6163653a2052657761726420706f6f6c206e6f742073657460448201526064015b60405180910390fd5b6003546040516305187d8160e51b8152600481018390526001600160a01b0390911690600090829063a30fb02090602401600060405180830381865afa1580156101f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261021d9190810190610b8f565b9050336000805b83604001515181101561027857826001600160a01b03168460400151828151811061025157610251610ca5565b60200260200101516001600160a01b0316036102705760019150610278565b600101610224565b506040516331a9108f60e11b8152600481018690526000906001600160a01b03861690636352211e90602401602060405180830381865afa1580156102c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e59190610cbb565b6000878152600560205260408120549192509060ff1615801561030c575060008560600151115b6001549091506001600160a01b031660008461032c578660800151610348565b6103398760800151610810565b87608001516103489190610cee565b604051636eb1769f60e11b815233600482015230602482015290915081906001600160a01b0384169063dd62ed3e90604401602060405180830381865afa158015610397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bb9190610d01565b10156104155760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574706c6163653a20496e73756666696369656e7420616c6c6f77616044820152626e636560e81b606482015260840161019e565b60808701516040516323b872dd60e01b81526001600160a01b03888116600483015286811660248301526044820192909252908316906323b872dd906064016020604051808303816000875af1158015610473573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104979190610d1a565b50841561053657816001600160a01b03166323b872dd87306104bc8b60800151610810565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af1158015610510573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105349190610d1a565b505b6003546040516323b872dd60e01b81526001600160a01b0386811660048301528881166024830152604482018c9052909116906323b872dd90606401600060405180830381600087803b15801561058c57600080fd5b505af11580156105a0573d6000803e3d6000fd5b505050508215610619576004805460608901516040516307420a4160e01b81526001600160a01b038a81169482019490945260248101919091529116906307420a4190604401600060405180830381600087803b15801561060057600080fd5b505af1158015610614573d6000803e3d6000fd5b505050505b600089815260056020908152604091829020805460ff19166001179055608089015182518c8152918201529081018290526001600160a01b0385811691908816907f8692cf5ba66abd64f88cdc1ffa0ee9d9c21ee2d999322a20445ae32393394e3e9060600160405180910390a3505050505050505050565b61069a61083d565b6106a4600061086a565b565b6106ae61083d565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6106d861083d565b60008160ff16116107455760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d75737420604482015270062652067726561746572207468616e203607c1b606482015260840161019e565b60648160ff1611156107b25760405162461bcd60e51b815260206004820152603060248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d7573742060448201526f06265206c657373207468616e203130360841b606482015260840161019e565b6004805460ff909216600160a01b0260ff60a01b19909216919091179055565b6107da61083d565b6001600160a01b03811661080457604051631e4fbdf760e01b81526000600482015260240161019e565b61080d8161086a565b50565b60045460009060649061082d90600160a01b900460ff1684610d35565b6108379190610d4c565b92915050565b6000546001600160a01b031633146106a45760405163118cdaa760e01b815233600482015260240161019e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156108cc57600080fd5b5035919050565b6001600160a01b038116811461080d57600080fd5b6000602082840312156108fa57600080fd5b8135610905816108d3565b9392505050565b60006020828403121561091e57600080fd5b813560ff8116811461090557600080fd5b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156109685761096861092f565b60405290565b604051610120810167ffffffffffffffff811182821017156109685761096861092f565b604051601f8201601f1916810167ffffffffffffffff811182821017156109bb576109bb61092f565b604052919050565b600082601f8301126109d457600080fd5b815167ffffffffffffffff8111156109ee576109ee61092f565b610a01601f8201601f1916602001610992565b818152846020838601011115610a1657600080fd5b60005b82811015610a3557602081860181015183830182015201610a19565b506000918101602001919091529392505050565b600067ffffffffffffffff821115610a6357610a6361092f565b5060051b60200190565b600082601f830112610a7e57600080fd5b8151610a91610a8c82610a49565b610992565b80828252602082019150602060608402860101925085831115610ab357600080fd5b602085015b83811015610b095760608188031215610ad057600080fd5b610ad8610945565b8151610ae3816108d3565b815260208281015181830152604080840151908301529084529290920191606001610ab8565b5095945050505050565b600082601f830112610b2457600080fd5b8151610b32610a8c82610a49565b8082825260208201915060208360051b860101925085831115610b5457600080fd5b602085015b83811015610b09578051610b6c816108d3565b835260209283019201610b59565b80518015158114610b8a57600080fd5b919050565b600060208284031215610ba157600080fd5b815167ffffffffffffffff811115610bb857600080fd5b82016101208185031215610bcb57600080fd5b610bd361096e565b815167ffffffffffffffff811115610bea57600080fd5b610bf6868285016109c3565b825250602082015167ffffffffffffffff811115610c1357600080fd5b610c1f86828501610a6d565b602083015250604082015167ffffffffffffffff811115610c3f57600080fd5b610c4b86828501610b13565b604083015250606082810151908201526080808301519082015260a0808301519082015260c08083015190820152610c8560e08301610b7a565b60e0820152610c976101008301610b7a565b610100820152949350505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610ccd57600080fd5b8151610905816108d3565b634e487b7160e01b600052601160045260246000fd5b8082018082111561083757610837610cd8565b600060208284031215610d1357600080fd5b5051919050565b600060208284031215610d2c57600080fd5b61090582610b7a565b808202811582820484141761083757610837610cd8565b600082610d6957634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220dab3e62c6e21985e054bde3b954768c0e4c5c15bef413ff2013b9047dea5dbcf64736f6c634300081c0033", + "bytecode": "0x60806040526004805460ff60a01b1916600560a11b17905534801561002357600080fd5b506040516113423803806113428339810160408190526100429161026e565b836001600160a01b03811661007257604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b61007b81610202565b506001600160a01b0383166100e15760405162461bcd60e51b815260206004820152602660248201527f4d61726b6574706c6163653a205553442045524332302061646472657373206960448201526573207a65726f60d01b6064820152608401610069565b6001600160a01b0381166101455760405162461bcd60e51b815260206004820152602560248201527f4d61726b6574706c6163653a2044656665727265642061646472657373206973604482015264207a65726f60d81b6064820152608401610069565b600180546001600160a01b038086166001600160a01b031992831681179093556002805486831690841617905560038054918516919092161790556040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa1580156101bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101df91906102c2565b600160146101000a81548160ff021916908360ff160217905550505050506102ec565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461026957600080fd5b919050565b6000806000806080858703121561028457600080fd5b61028d85610252565b935061029b60208601610252565b92506102a960408601610252565b91506102b760608601610252565b905092959194509250565b6000602082840312156102d457600080fd5b815160ff811681146102e557600080fd5b9392505050565b611047806102fb6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80637f4065c6116100665780637f4065c61461011957806382558c2a1461012c5780638da5cb5b1461013f578063b7b2e45414610150578063f2fde38b1461016357600080fd5b806345e41a54146100985780634bd9760f146100be578063715018a6146100e95780637c3a00fd146100f3575b600080fd5b6100ab6100a6366004610a67565b610176565b6040519081526020015b60405180910390f35b6001546100d1906001600160a01b031681565b6040516001600160a01b0390911681526020016100b5565b6100f16106ed565b005b60045461010790600160a01b900460ff1681565b60405160ff90911681526020016100b5565b6100ab610127366004610a67565b610701565b6100f161013a366004610a95565b610799565b6000546001600160a01b03166100d1565b6100f161015e366004610ab9565b6107c3565b6100f1610171366004610a95565b6108c5565b6004546000906001600160a01b03166101d65760405162461bcd60e51b815260206004820181905260248201527f4d61726b6574706c6163653a2052657761726420706f6f6c206e6f742073657460448201526064015b60405180910390fd5b60035460405163375e464360e11b8152600481018490526001600160a01b03909116906000908290636ebc8c8690602401600060405180830381865afa158015610224573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261024c9190810190610d3c565b60405163b7e62e5d60e01b8152600481018690523360248201529091506000906001600160a01b0384169063b7e62e5d90604401602060405180830381865afa15801561029d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c19190610e52565b90503360006102cf84610903565b6040516331a9108f60e11b8152600481018590529091506000906001600160a01b03871690636352211e90602401602060405180830381865afa15801561031a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033e9190610e6b565b6000858152600560205260408120549192509060ff16158015610365575060008660600151115b6001549091506001600160a01b031660006103808886610964565b90506000610391896080015161099e565b604051636eb1769f60e11b815233600482015230602482015290915082906001600160a01b0385169063dd62ed3e90604401602060405180830381865afa1580156103e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104049190610e52565b101561045e5760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574706c6163653a20496e73756666696369656e7420616c6c6f77616044820152626e636560e81b60648201526084016101cd565b6040516323b872dd60e01b81526001600160a01b0388811660048301528681166024830152604482018390528416906323b872dd906064016020604051808303816000875af11580156104b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d99190610e88565b50851561057457826001600160a01b03166323b872dd88306104fa856109c3565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801561054e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105729190610e88565b505b6003546040516304a2a1fb60e41b8152600481018e90526001600160a01b03878116602483015289811660448301526000921690634a2a1fb0906064016020604051808303816000875af11580156105d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f49190610e52565b9050841561066b576004805460608c01516040516307420a4160e01b81526001600160a01b038c81169482019490945260248101919091529116906307420a4190604401600060405180830381600087803b15801561065257600080fd5b505af1158015610666573d6000803e3d6000fd5b505050505b600081815260056020908152604091829020805460ff1916600117905581518f8152908101839052908101839052606081018490526001600160a01b0380881691908a16907f86cb2bc7fc62e19d4a6d7ef45af3a556d854e27140cd36afe5e9911d7db8017a9060800160405180910390a39c9b505050505050505050505050565b6106f56109ea565b6106ff6000610a17565b565b60035460405163375e464360e11b8152600481018390526000916001600160a01b03169082908290636ebc8c8690602401600060405180830381865afa15801561074f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107779190810190610d3c565b9050600061078482610903565b90506107908282610964565b95945050505050565b6107a16109ea565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6107cb6109ea565b60008160ff16116108385760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d75737420604482015270062652067726561746572207468616e203607c1b60648201526084016101cd565b60648160ff1611156108a55760405162461bcd60e51b815260206004820152603060248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d7573742060448201526f06265206c657373207468616e203130360841b60648201526084016101cd565b6004805460ff909216600160a01b0260ff60a01b19909216919091179055565b6108cd6109ea565b6001600160a01b0381166108f757604051631e4fbdf760e01b8152600060048201526024016101cd565b61090081610a17565b50565b6000805b82604001515181101561095b57336001600160a01b03168360400151828151811061093457610934610ea3565b60200260200101516001600160a01b0316036109535750600192915050565b600101610907565b50600092915050565b600080610974846080015161099e565b9050826109815780610994565b61098a816109c3565b6109949082610ecf565b9150505b92915050565b6001546000906109b990600160a01b900460ff16600a610fc9565b6109989083610fd8565b6004546000906064906109e090600160a01b900460ff1684610fd8565b6109989190610fef565b6000546001600160a01b031633146106ff5760405163118cdaa760e01b81523360048201526024016101cd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610a7957600080fd5b5035919050565b6001600160a01b038116811461090057600080fd5b600060208284031215610aa757600080fd5b8135610ab281610a80565b9392505050565b600060208284031215610acb57600080fd5b813560ff81168114610ab257600080fd5b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715610b1557610b15610adc565b60405290565b604051610120810167ffffffffffffffff81118282101715610b1557610b15610adc565b604051601f8201601f1916810167ffffffffffffffff81118282101715610b6857610b68610adc565b604052919050565b600082601f830112610b8157600080fd5b815167ffffffffffffffff811115610b9b57610b9b610adc565b610bae601f8201601f1916602001610b3f565b818152846020838601011115610bc357600080fd5b60005b82811015610be257602081860181015183830182015201610bc6565b506000918101602001919091529392505050565b600067ffffffffffffffff821115610c1057610c10610adc565b5060051b60200190565b600082601f830112610c2b57600080fd5b8151610c3e610c3982610bf6565b610b3f565b80828252602082019150602060608402860101925085831115610c6057600080fd5b602085015b83811015610cb65760608188031215610c7d57600080fd5b610c85610af2565b8151610c9081610a80565b815260208281015181830152604080840151908301529084529290920191606001610c65565b5095945050505050565b600082601f830112610cd157600080fd5b8151610cdf610c3982610bf6565b8082825260208201915060208360051b860101925085831115610d0157600080fd5b602085015b83811015610cb6578051610d1981610a80565b835260209283019201610d06565b80518015158114610d3757600080fd5b919050565b600060208284031215610d4e57600080fd5b815167ffffffffffffffff811115610d6557600080fd5b82016101208185031215610d7857600080fd5b610d80610b1b565b815167ffffffffffffffff811115610d9757600080fd5b610da386828501610b70565b825250602082015167ffffffffffffffff811115610dc057600080fd5b610dcc86828501610c1a565b602083015250604082015167ffffffffffffffff811115610dec57600080fd5b610df886828501610cc0565b604083015250606082810151908201526080808301519082015260a0808301519082015260c08083015190820152610e3260e08301610d27565b60e0820152610e446101008301610d27565b610100820152949350505050565b600060208284031215610e6457600080fd5b5051919050565b600060208284031215610e7d57600080fd5b8151610ab281610a80565b600060208284031215610e9a57600080fd5b610ab282610d27565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561099857610998610eb9565b6001815b6001841115610f1d57808504811115610f0157610f01610eb9565b6001841615610f0f57908102905b60019390931c928002610ee6565b935093915050565b600082610f3457506001610998565b81610f4157506000610998565b8160018114610f575760028114610f6157610f7d565b6001915050610998565b60ff841115610f7257610f72610eb9565b50506001821b610998565b5060208310610133831016604e8410600b8410161715610fa0575081810a610998565b610fad6000198484610ee2565b8060001904821115610fc157610fc1610eb9565b029392505050565b6000610ab260ff841683610f25565b808202811582820484141761099857610998610eb9565b60008261100c57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212202c8bad854a0fbf2b43bc6c0ef7cb97b78d299fc8dfba17aef1c690abc807d17464736f6c634300081c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c80637f4065c6116100665780637f4065c61461011957806382558c2a1461012c5780638da5cb5b1461013f578063b7b2e45414610150578063f2fde38b1461016357600080fd5b806345e41a54146100985780634bd9760f146100be578063715018a6146100e95780637c3a00fd146100f3575b600080fd5b6100ab6100a6366004610a67565b610176565b6040519081526020015b60405180910390f35b6001546100d1906001600160a01b031681565b6040516001600160a01b0390911681526020016100b5565b6100f16106ed565b005b60045461010790600160a01b900460ff1681565b60405160ff90911681526020016100b5565b6100ab610127366004610a67565b610701565b6100f161013a366004610a95565b610799565b6000546001600160a01b03166100d1565b6100f161015e366004610ab9565b6107c3565b6100f1610171366004610a95565b6108c5565b6004546000906001600160a01b03166101d65760405162461bcd60e51b815260206004820181905260248201527f4d61726b6574706c6163653a2052657761726420706f6f6c206e6f742073657460448201526064015b60405180910390fd5b60035460405163375e464360e11b8152600481018490526001600160a01b03909116906000908290636ebc8c8690602401600060405180830381865afa158015610224573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261024c9190810190610d3c565b60405163b7e62e5d60e01b8152600481018690523360248201529091506000906001600160a01b0384169063b7e62e5d90604401602060405180830381865afa15801561029d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c19190610e52565b90503360006102cf84610903565b6040516331a9108f60e11b8152600481018590529091506000906001600160a01b03871690636352211e90602401602060405180830381865afa15801561031a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033e9190610e6b565b6000858152600560205260408120549192509060ff16158015610365575060008660600151115b6001549091506001600160a01b031660006103808886610964565b90506000610391896080015161099e565b604051636eb1769f60e11b815233600482015230602482015290915082906001600160a01b0385169063dd62ed3e90604401602060405180830381865afa1580156103e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104049190610e52565b101561045e5760405162461bcd60e51b815260206004820152602360248201527f4d61726b6574706c6163653a20496e73756666696369656e7420616c6c6f77616044820152626e636560e81b60648201526084016101cd565b6040516323b872dd60e01b81526001600160a01b0388811660048301528681166024830152604482018390528416906323b872dd906064016020604051808303816000875af11580156104b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d99190610e88565b50851561057457826001600160a01b03166323b872dd88306104fa856109c3565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af115801561054e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105729190610e88565b505b6003546040516304a2a1fb60e41b8152600481018e90526001600160a01b03878116602483015289811660448301526000921690634a2a1fb0906064016020604051808303816000875af11580156105d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f49190610e52565b9050841561066b576004805460608c01516040516307420a4160e01b81526001600160a01b038c81169482019490945260248101919091529116906307420a4190604401600060405180830381600087803b15801561065257600080fd5b505af1158015610666573d6000803e3d6000fd5b505050505b600081815260056020908152604091829020805460ff1916600117905581518f8152908101839052908101839052606081018490526001600160a01b0380881691908a16907f86cb2bc7fc62e19d4a6d7ef45af3a556d854e27140cd36afe5e9911d7db8017a9060800160405180910390a39c9b505050505050505050505050565b6106f56109ea565b6106ff6000610a17565b565b60035460405163375e464360e11b8152600481018390526000916001600160a01b03169082908290636ebc8c8690602401600060405180830381865afa15801561074f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107779190810190610d3c565b9050600061078482610903565b90506107908282610964565b95945050505050565b6107a16109ea565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6107cb6109ea565b60008160ff16116108385760405162461bcd60e51b815260206004820152603160248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d75737420604482015270062652067726561746572207468616e203607c1b60648201526084016101cd565b60648160ff1611156108a55760405162461bcd60e51b815260206004820152603060248201527f4d61726b6574706c6163653a20496e7465726573742072617465206d7573742060448201526f06265206c657373207468616e203130360841b60648201526084016101cd565b6004805460ff909216600160a01b0260ff60a01b19909216919091179055565b6108cd6109ea565b6001600160a01b0381166108f757604051631e4fbdf760e01b8152600060048201526024016101cd565b61090081610a17565b50565b6000805b82604001515181101561095b57336001600160a01b03168360400151828151811061093457610934610ea3565b60200260200101516001600160a01b0316036109535750600192915050565b600101610907565b50600092915050565b600080610974846080015161099e565b9050826109815780610994565b61098a816109c3565b6109949082610ecf565b9150505b92915050565b6001546000906109b990600160a01b900460ff16600a610fc9565b6109989083610fd8565b6004546000906064906109e090600160a01b900460ff1684610fd8565b6109989190610fef565b6000546001600160a01b031633146106ff5760405163118cdaa760e01b81523360048201526024016101cd565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215610a7957600080fd5b5035919050565b6001600160a01b038116811461090057600080fd5b600060208284031215610aa757600080fd5b8135610ab281610a80565b9392505050565b600060208284031215610acb57600080fd5b813560ff81168114610ab257600080fd5b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715610b1557610b15610adc565b60405290565b604051610120810167ffffffffffffffff81118282101715610b1557610b15610adc565b604051601f8201601f1916810167ffffffffffffffff81118282101715610b6857610b68610adc565b604052919050565b600082601f830112610b8157600080fd5b815167ffffffffffffffff811115610b9b57610b9b610adc565b610bae601f8201601f1916602001610b3f565b818152846020838601011115610bc357600080fd5b60005b82811015610be257602081860181015183830182015201610bc6565b506000918101602001919091529392505050565b600067ffffffffffffffff821115610c1057610c10610adc565b5060051b60200190565b600082601f830112610c2b57600080fd5b8151610c3e610c3982610bf6565b610b3f565b80828252602082019150602060608402860101925085831115610c6057600080fd5b602085015b83811015610cb65760608188031215610c7d57600080fd5b610c85610af2565b8151610c9081610a80565b815260208281015181830152604080840151908301529084529290920191606001610c65565b5095945050505050565b600082601f830112610cd157600080fd5b8151610cdf610c3982610bf6565b8082825260208201915060208360051b860101925085831115610d0157600080fd5b602085015b83811015610cb6578051610d1981610a80565b835260209283019201610d06565b80518015158114610d3757600080fd5b919050565b600060208284031215610d4e57600080fd5b815167ffffffffffffffff811115610d6557600080fd5b82016101208185031215610d7857600080fd5b610d80610b1b565b815167ffffffffffffffff811115610d9757600080fd5b610da386828501610b70565b825250602082015167ffffffffffffffff811115610dc057600080fd5b610dcc86828501610c1a565b602083015250604082015167ffffffffffffffff811115610dec57600080fd5b610df886828501610cc0565b604083015250606082810151908201526080808301519082015260a0808301519082015260c08083015190820152610e3260e08301610d27565b60e0820152610e446101008301610d27565b610100820152949350505050565b600060208284031215610e6457600080fd5b5051919050565b600060208284031215610e7d57600080fd5b8151610ab281610a80565b600060208284031215610e9a57600080fd5b610ab282610d27565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561099857610998610eb9565b6001815b6001841115610f1d57808504811115610f0157610f01610eb9565b6001841615610f0f57908102905b60019390931c928002610ee6565b935093915050565b600082610f3457506001610998565b81610f4157506000610998565b8160018114610f575760028114610f6157610f7d565b6001915050610998565b60ff841115610f7257610f72610eb9565b50506001821b610998565b5060208310610133831016604e8410600b8410161715610fa0575081810a610998565b610fad6000198484610ee2565b8060001904821115610fc157610fc1610eb9565b029392505050565b6000610ab260ff841683610f25565b808202811582820484141761099857610998610eb9565b60008261100c57634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212202c8bad854a0fbf2b43bc6c0ef7cb97b78d299fc8dfba17aef1c690abc807d17464736f6c634300081c0033", "linkReferences": {}, "deployedLinkReferences": {} }