diff --git a/packages/server/tests/acceptance/htsPrecompile_v1.spec.ts b/packages/server/tests/acceptance/htsPrecompile_v1.spec.ts new file mode 100644 index 0000000000..ef2e07d208 --- /dev/null +++ b/packages/server/tests/acceptance/htsPrecompile_v1.spec.ts @@ -0,0 +1,148 @@ +/*- + * + * Hedera JSON RPC Relay + * + * Copyright (C) 2022 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// external resources +import { solidity } from 'ethereum-waffle'; +import chai, { expect } from 'chai'; + +chai.use(solidity); + +import { AliasAccount } from '../clients/servicesClient'; +import { ethers } from 'ethers'; +import ERC20MockJson from '../contracts/contracts_v1/ERC20Mock.json'; +import BaseHTSJson from '../contracts/contracts_v1/BaseHTS.json'; + + +describe('HTS Precompile V1 Acceptance Tests', async function () { + this.timeout(240 * 1000); // 240 seconds + const { servicesNode, relay } = global; + + const TX_SUCCESS_CODE = 22; + + const accounts: AliasAccount[] = []; + let BaseHTSContractAddress; + let HTSTokenContractAddress; + let NftHTSTokenContractAddress; + let baseHTSContract; + let baseHTSContractOwner; + let baseHTSContractReceiverWalletFirst; + let baseHTSContractReceiverWalletSecond; + let HTSTokenWithCustomFeesContractAddress; + + this.beforeAll(async () => { + accounts[0] = await servicesNode.createAliasAccount(60, relay.provider); + accounts[1] = await servicesNode.createAliasAccount(15, relay.provider); + accounts[2] = await servicesNode.createAliasAccount(15, relay.provider); + + // alow mirror node a 2 full record stream write windows (2 sec) and a buffer to persist setup details + await new Promise(r => setTimeout(r, 5000)); + + BaseHTSContractAddress = await deployBaseHTSContract(); + baseHTSContract = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[0].wallet); + + baseHTSContractOwner = baseHTSContract; + baseHTSContractReceiverWalletFirst = baseHTSContract.connect(accounts[1].wallet); + baseHTSContractReceiverWalletSecond = baseHTSContract.connect(accounts[2].wallet); + }); + + async function deployBaseHTSContract() { + const baseHTSFactory = new ethers.ContractFactory(BaseHTSJson.abi, BaseHTSJson.bytecode, accounts[0].wallet); + const baseHTS = await baseHTSFactory.deploy({gasLimit: 10_000_000}); + const { contractAddress } = await baseHTS.deployTransaction.wait(); + + return contractAddress; + } + + async function createHTSToken() { + const baseHTSContract = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[0].wallet); + const tx = await baseHTSContract.createFungibleTokenPublic(accounts[0].wallet.address, { + value: ethers.BigNumber.from('10000000000000000000'), + gasLimit: 1_000_000 + }); + const { tokenAddress } = (await tx.wait()).events.filter(e => e.event = 'CreatedToken')[0].args; + + return tokenAddress; + } + + async function createNftHTSToken() { + const baseHTSContract = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[0].wallet); + const tx = await baseHTSContract.createNonFungibleTokenPublic(accounts[0].wallet.address, { + value: ethers.BigNumber.from('10000000000000000000'), + gasLimit: 1_000_000 + }); + const { tokenAddress } = (await tx.wait()).events.filter(e => e.event = 'CreatedToken')[0].args; + + return tokenAddress; + } + + async function createHTSTokenWithCustomFees() { + const baseHTSContract = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[0].wallet); + const tx = await baseHTSContract.createFungibleTokenWithCustomFeesPublic(accounts[0].wallet.address, HTSTokenContractAddress, { + value: ethers.BigNumber.from('20000000000000000000'), + gasLimit: 1_000_000 + }); + const txReceipt = await tx.wait(); + const { tokenAddress } = txReceipt.events.filter(e => e.event === 'CreatedToken')[0].args; + + return tokenAddress; + } + + it('should create associate to a fungible token', async function() { + HTSTokenContractAddress = await createHTSToken(); + + const txCO = await baseHTSContractOwner.associateTokenPublic(BaseHTSContractAddress, HTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txCO.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const txRWF = await baseHTSContractReceiverWalletFirst.associateTokenPublic(accounts[1].wallet.address, HTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWF.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const txRWS = await baseHTSContractReceiverWalletSecond.associateTokenPublic(accounts[2].wallet.address, HTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWS.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + }); + + it('should create and associate to an nft', async function() { + NftHTSTokenContractAddress = await createNftHTSToken(); + + const txCO = await baseHTSContractOwner.associateTokenPublic(BaseHTSContractAddress, NftHTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txCO.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const txRWF = await baseHTSContractReceiverWalletFirst.associateTokenPublic(accounts[1].wallet.address, NftHTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWF.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const txRWS = await baseHTSContractReceiverWalletSecond.associateTokenPublic(accounts[2].wallet.address, NftHTSTokenContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWS.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + }); + + it('should create and associate to a fungible token with custom fees', async function() { + HTSTokenWithCustomFeesContractAddress = await createHTSTokenWithCustomFees(); + + const baseHTSContractOwner = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[0].wallet); + const txCO = await baseHTSContractOwner.associateTokenPublic(BaseHTSContractAddress, HTSTokenWithCustomFeesContractAddress, { gasLimit: 1_000_000 }); + expect((await txCO.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const baseHTSContractReceiverWalletFirst = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[1].wallet); + const txRWF = await baseHTSContractReceiverWalletFirst.associateTokenPublic(accounts[1].wallet.address, HTSTokenWithCustomFeesContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWF.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + + const baseHTSContractReceiverWalletSecond = new ethers.Contract(BaseHTSContractAddress, BaseHTSJson.abi, accounts[2].wallet); + const txRWS = await baseHTSContractReceiverWalletSecond.associateTokenPublic(accounts[2].wallet.address, HTSTokenWithCustomFeesContractAddress, { gasLimit: 1_000_000 }); + expect((await txRWS.wait()).events.filter(e => e.event === 'ResponseCode')[0].args.responseCode).to.equal(TX_SUCCESS_CODE); + }); +}); diff --git a/packages/server/tests/contracts/BaseHTS.json b/packages/server/tests/contracts/BaseHTS.json index 6f278cf47b..711d943282 100644 --- a/packages/server/tests/contracts/BaseHTS.json +++ b/packages/server/tests/contracts/BaseHTS.json @@ -116,9 +116,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -414,9 +414,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -896,9 +896,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -1474,9 +1474,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -1756,9 +1756,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -2306,9 +2306,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -3133,8 +3133,8 @@ "type": "function" } ], - "bytecode": "0x60c06040526009608081905268746f6b656e4e616d6560b81b60a09081526200002c9160019190620000cb565b5060408051808201909152600b8082526a1d1bdad95b94de5b589bdb60aa1b60209092019182526200006191600291620000cb565b50604080518082019091526004808252636d656d6f60e01b60209092019182526200008f91600391620000cb565b506103e860048190556005805463ffffffff1916909117905560086006556007805460ff19169055348015620000c457600080fd5b50620001ae565b828054620000d99062000171565b90600052602060002090601f016020900481019282620000fd576000855562000148565b82601f106200011857805160ff191683800117855562000148565b8280016001018555821562000148579182015b82811115620001485782518255916020019190600101906200012b565b50620001569291506200015a565b5090565b5b808211156200015657600081556001016200015b565b600181811c908216806200018657607f821691505b60208210811415620001a857634e487b7160e01b600052602260045260246000fd5b50919050565b615af180620001be6000396000f3fe6080604052600436106102c65760003560e01c80638070905f11610179578063d85f74c1116100d6578063f2f38a741161008a578063f848fec411610064578063f848fec414610844578063f9e978bd14610864578063fdc8321e1461088457600080fd5b8063f2f38a74146107d6578063f4a01e5b14610804578063f7be34251461082457600080fd5b8063eee55ac8116100bb578063eee55ac814610776578063f25b120014610796578063f2c31ff4146107b657600080fd5b8063d85f74c114610743578063d92ac2481461075657600080fd5b8063a345f7bd1161012d578063af99c63311610112578063af99c633146106d5578063c0b19b6d146106f5578063d614cdb81461072357600080fd5b8063a345f7bd1461067b578063a3ad5b551461069b57600080fd5b80638ba74da01161015e5780638ba74da0146106285780638f8d7f991461063b5780639604ca651461065b57600080fd5b80638070905f146105d957806386f88d881461060857600080fd5b80634cbdb37b1161022757806369837dc2116101db5780636da6b1f0116101c05780636da6b1f0146105795780637c41ad2c146105995780637d3e5da8146105b957600080fd5b806369837dc21461052b5780636a4dde211461055957600080fd5b8063593d6e821161020c578063593d6e82146104a65780635a5e6c31146104c65780635b9076b7146104fb57600080fd5b80634cbdb37b1461045857806356af84031461048657600080fd5b80632eecbca31161027e5780633eed2c39116102635780633eed2c39146104035780634b5c6687146104235780634ba670351461043857600080fd5b80632eecbca3146103c35780633b3bff0f146103e357600080fd5b806319db44b6116102af57806319db44b6146103385780632b256ec8146103755780632d73bb2e146103a357600080fd5b80630fd2601e146102cb57806313c05dd814610303575b600080fd5b3480156102d757600080fd5b506102eb6102e6366004613bbd565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561030f57600080fd5b5061032361031e366004613bf6565b610968565b604080519283529015156020830152016102fa565b34801561034457600080fd5b50610358610353366004613c41565b6109e6565b604080519283526001600160a01b039091166020830152016102fa565b34801561038157600080fd5b50610395610390366004613c6d565b610a6a565b6040519081526020016102fa565b3480156103af57600080fd5b506103956103be366004613bbd565b610b56565b3480156103cf57600080fd5b506102eb6103de366004613bbd565b610b9b565b3480156103ef57600080fd5b506103956103fe366004613c6d565b610bd2565b34801561040f57600080fd5b5061032361041e366004613c6d565b610cac565b610436610431366004613c6d565b610d26565b005b34801561044457600080fd5b50610395610453366004613c99565b6110e6565b34801561046457600080fd5b50610478610473366004613cf5565b611132565b6040516102fa92919061421b565b34801561049257600080fd5b506103956104a1366004614355565b6111a8565b3480156104b257600080fd5b506103956104c136600461442d565b6111f2565b3480156104d257600080fd5b506104e66104e1366004613bf6565b6112cf565b604080519283526020830191909152016102fa565b34801561050757600080fd5b5061051b610516366004613c6d565b611340565b6040516102fa94939291906144aa565b34801561053757600080fd5b5061054b610546366004613c6d565b6113d2565b6040516102fa929190614526565b34801561056557600080fd5b50610323610574366004613bbd565b611447565b34801561058557600080fd5b50610395610594366004613c99565b6114be565b3480156105a557600080fd5b506103956105b4366004613c6d565b6114cc565b3480156105c557600080fd5b506103956105d4366004613bbd565b6114fa565b3480156105e557600080fd5b506105f96105f436600461457d565b611506565b6040516102fa939291906146c6565b34801561061457600080fd5b50610323610623366004613c6d565b61158e565b610436610636366004613bbd565b6115ff565b34801561064757600080fd5b506102eb610656366004613bbd565b611a91565b34801561066757600080fd5b506103956106763660046146f8565b611ac7565b34801561068757600080fd5b50610395610696366004613c6d565b611afc565b3480156106a757600080fd5b506106bb6106b6366004613bbd565b611b42565b6040805160079390930b83529015156020830152016102fa565b3480156106e157600080fd5b506102eb6106f0366004613bbd565b611c34565b34801561070157600080fd5b50610715610710366004613c6d565b611c6a565b6040516102fa92919061476d565b34801561072f57600080fd5b5061071561073e366004613c6d565b611d61565b610436610751366004613c6d565b611e6b565b34801561076257600080fd5b506103956107713660046147a7565b612203565b34801561078257600080fd5b5061039561079136600461442d565b612210565b3480156107a257600080fd5b506103956107b13660046147f5565b6122a3565b3480156107c257600080fd5b506106bb6107d1366004613bbd565b6122b0565b3480156107e257600080fd5b506107f66107f1366004613c6d565b61238b565b6040516102fa929190614835565b34801561081057600080fd5b5061039561081f366004613bbd565b612400565b34801561083057600080fd5b5061039561083f366004613c6d565b61240c565b34801561085057600080fd5b5061039561085f36600461484e565b6124ef565b34801561087057600080fd5b5061043661087f36600461488f565b6124fc565b34801561089057600080fd5b5061039561089f3660046148ac565b612549565b604051638f8d7f9960e01b81526001600160a01b038084166004830152821660248201526000903090638f8d7f99906044015b602060405180830381600087803b1580156108f157600080fd5b505af1158015610905573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092991906148f7565b604051600782900b8152909150600080516020615a9c8339815191529060200160405180910390a1600781900b60161461096257600080fd5b92915050565b600080610976858585612720565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146109a957600080fd5b60405181151581527e1c2e72360171244b3bb8cc8ddd767820edf37138ad6f129fb3574b407c307d906020015b60405180910390a1935093915050565b6000806109f3848461281f565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214610a2657600080fd5b6040516001600160a01b03821681527fc2c78c7c31baf14949e75c51df12be56edb9af523cf82839c2869bbcf13b3ecb906020015b60405180910390a19250929050565b604051631f106b4b60e21b81526001600160a01b03821660048201526000903090637c41ad2c90602401602060405180830381600087803b158015610aae57600080fd5b505af1158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae69190614914565b9050600080516020615a9c83398151915281604051610b0791815260200190565b60405180910390a160168114610b1c57600080fd5b604051600181527f0c9c765845f4d139956bb8fc8decb2eec6093c9c608b809641b16054b29f0e13906020015b60405180910390a1919050565b6000610b6283836128ff565b60070b9050600080516020615a9c83398151915281604051610b8691815260200190565b60405180910390a16016811461096257600080fd5b60405163af99c63360e01b81526001600160a01b03808416600483015282166024820152600090309063af99c633906044016108d7565b6040516001600160a01b03821660248201526000908190819061016790633b3bff0f60e01b906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610c3a919061492d565b6000604051808303816000865af19150503d8060008114610c77576040519150601f19603f3d011682016040523d82523d6000602084013e610c7c565b606091505b509150915081610c8d576015610ca1565b80806020019051810190610ca1919061495b565b60030b949350505050565b600080610cb88361294e565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214610ceb57600080fd5b60405181151581527f6b7f3306751292f85ab4161ee2b0ac16dfc8ded13e6446ce6bd859d0a2f4c78e906020015b60405180910390a1915091565b60408051600480825260a08201909252600091816020015b610d46613a2f565b815260200190600190039081610d3e579050509050610d7960006006600160405180602001604052806000815250612a4b565b81600081518110610d8c57610d8c614976565b6020026020010181905250610db260018060405180602001604052806000815250612a82565b81600181518110610dc557610dc5614976565b6020026020010181905250610dec6002600160405180602001604052806000815250612a82565b81600281518110610dff57610dff614976565b6020026020010181905250610e266003600160405180602001604052806000815250612a82565b81600381518110610e3957610e39614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff168152509050600060405180610120016040528060018054610e979061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec39061498c565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050815260200160028054610f279061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610f539061498c565b8015610fa05780601f10610f7557610100808354040283529160200191610fa0565b820191906000526020600020905b815481529060010190602001808311610f8357829003601f168201915b50505050508152602001856001600160a01b0316815260200160038054610fc69061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff29061498c565b801561103f5780601f106110145761010080835404028352916020019161103f565b820191906000526020600020905b81548152906001019060200180831161102257829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a001839052600454600654919250600091829161109091859190612ab7565b9092509050601682146110a257600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b60006110f485858585612be5565b9050600080516020615a9c8339815191528160405161111591815260200190565b60405180910390a16016811461112a57600080fd5b949350505050565b600061113c613a8c565b6111468484612cf5565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461117957600080fd5b7fa516f81c528634d0fc1e993bba1d227231b4bd6d1beb72d33b056a6199c0f98881604051610a5b91906149c7565b60006111b5848484612de8565b9050600080516020615a9c833981519152816040516111d691815260200190565b60405180910390a1601681146111eb57600080fd5b9392505050565b60008060006101676001600160a01b031663593d6e8260e01b868660405160240161121e9291906149da565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161125c919061492d565b6000604051808303816000865af19150503d8060008114611299576040519150601f19603f3d011682016040523d82523d6000602084013e61129e565b606091505b5091509150816112af5760156112c3565b808060200190518101906112c3919061495b565b60030b95945050505050565b6000806112dd858585612ec8565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461131057600080fd5b6040518181527f25b6684a7e8fe1b676e9c39c8dd65034fbafea906d3bdfd97bf748b7b55e14c8906020016109d6565b6000606080606061135085612fb4565b604051600785900b815293975091955093509150600080516020615a9c8339815191529060200160405180910390a1600784900b60161461139057600080fd5b7f2efc8334b040613a552197fe34283d6ca2909c8ffae393e128424931f20c69b38383836040516113c393929190614a1d565b60405180910390a19193509193565b60006113dc613ac7565b6113e5836130b4565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461141857600080fd5b7f476a9a9b28e2717d55288b2ae3c48a72aac52b11f8bd855017c9d41d9fc1896481604051610d199190614a56565b600080611454848461319d565b60405160079290920b80835293509150600080516020615a9c8339815191529060200160405180910390a16016821461148c57600080fd5b60405181151581527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e90602001610a5b565b60006110f4858585856131ee565b6040516001600160a01b03821660248201526000908190819061016790631f106b4b60e21b90604401610bfc565b6000610b62838361324f565b600080606061151686868661329e565b6040518381529295509093509150600080516020615a9c8339815191529060200160405180910390a16016831461154c57600080fd5b7feff23992f47b3c101679f8b4dc9d3e242c903909dba4a453f2b2341ad463b0e2828260405161157d929190614a69565b60405180910390a193509350939050565b60008061159a8361339c565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146115cd57600080fd5b60405181151581527f9ee19e13dfa1ba8db2502e15ff56dbecdeb0e0473323fb195473ce648030a2cd90602001610d19565b604080516001808252818301909252600091816020015b61161e613a2f565b815260200190600190039081611616579050509050611650600080600160405180602001604052806000815250612a4b565b8160008151811061166357611663614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546116c19061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546116ed9061498c565b801561173a5780601f1061170f5761010080835404028352916020019161173a565b820191906000526020600020905b81548152906001019060200180831161171d57829003601f168201915b50505050508152602001600280546117519061498c565b80601f016020809104026020016040519081016040528092919081815260200182805461177d9061498c565b80156117ca5780601f1061179f576101008083540402835291602001916117ca565b820191906000526020600020905b8154815290600101906020018083116117ad57829003601f168201915b50505050508152602001866001600160a01b03168152602001600380546117f09061498c565b80601f016020809104026020016040519081016040528092919081815260200182805461181c9061498c565b80156118695780601f1061183e57610100808354040283529160200191611869565b820191906000526020600020905b81548152906001019060200180831161184c57829003601f168201915b505050918352505060016020820181905260055463ffffffff166040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816118ba5750506040805160a081018252600181526001600160a01b0388811660208301526000928201839052606082018390528916608082015282519293509183919061193d5761193d614976565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a0820152825260001990920191018161195f5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a0830152825192935090918391906119f3576119f3614976565b6020026020010181905250600080611a128560045460065487876133e5565b91509150600080516020615a9c83398151915282604051611a3591815260200190565b60405180910390a160168214611a4a57600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b038381166024830152821660448201526000908190819061016790638f8d7f9960e01b9060640161121e565b6000611adb611ad68385614b3b565b613519565b9050600080516020615a9c83398151915281604051610b8691815260200190565b6000611b0782613543565b9050600080516020615a9c83398151915281604051611b2891815260200190565b60405180910390a160168114611b3d57600080fd5b919050565b604051633cb0c7fd60e21b81526001600160a01b038084166004830152821660248201526000908190309063f2c31ff4906044016040805180830381600087803b158015611b8f57600080fd5b505af1158015611ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc79190614cb3565b604051600783900b81529193509150600080516020615a9c8339815191529060200160405180910390a1600782900b601614611c0257600080fd5b60405181151581527fd24dda6928587354b65aa1a18c2eaf249bef7e5bafd2a71fac71d286f76f957f90602001610a5b565b6040516001600160a01b03838116602483015282166044820152600090819081906101679063af99c63360e01b9060640161121e565b60408051606081018252600080825260208201819052918101829052604051631ac299b760e31b81526001600160a01b0384166004820152309063d614cdb890602401608060405180830381600087803b158015611cc757600080fd5b505af1158015611cdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cff9190614d4d565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214611d3257600080fd5b7fa0a16bf9db2c17796faeca5af5aaeef8523f9d4c350c512cb00062ad89604f8881604051610d199190614d7a565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b0316631ac299b760e31b179052925190928391829161016791611dd3919061492d565b6000604051808303816000865af19150503d8060008114611e10576040519150601f19603f3d011682016040523d82523d6000602084013e611e15565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082611e4557601581611e59565b81806020019051810190611e599190614dae565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b611e8b613a2f565b815260200190600190039081611e83579050509050611ebe60006006600160405180602001604052806000815250612a4b565b81600081518110611ed157611ed1614976565b6020026020010181905250611ef760018060405180602001604052806000815250612a82565b81600181518110611f0a57611f0a614976565b6020026020010181905250611f316002600160405180602001604052806000815250612a82565b81600281518110611f4457611f44614976565b6020026020010181905250611f6b6004600160405180602001604052806000815250612a82565b81600381518110611f7e57611f7e614976565b6020026020010181905250611fa56003600160405180602001604052806000815250612a82565b81600481518110611fb857611fb8614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546120169061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546120429061498c565b801561208f5780601f106120645761010080835404028352916020019161208f565b820191906000526020600020905b81548152906001019060200180831161207257829003601f168201915b50505050508152602001600280546120a69061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546120d29061498c565b801561211f5780601f106120f45761010080835404028352916020019161211f565b820191906000526020600020905b81548152906001019060200180831161210257829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546121459061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546121719061498c565b80156121be5780601f10612193576101008083540402835291602001916121be565b820191906000526020600020905b8154815290600101906020018083116121a157829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905290506000806110908361358a565b60006111b5848484613674565b6040517f593d6e82000000000000000000000000000000000000000000000000000000008152600090309063593d6e829061225190869086906004016149da565b602060405180830381600087803b15801561226b57600080fd5b505af115801561227f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adb9190614914565b60006111b58484846136cf565b6040516001600160a01b0383811660248301528216604482015260009081908190819061016790633cb0c7fd60e21b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612322919061492d565b6000604051808303816000865af19150503d806000811461235f576040519150601f19603f3d011682016040523d82523d6000602084013e612364565b606091505b5091509150816123775760156000611e59565b80806020019051810190611e599190614dd9565b6000612395613ae7565b61239e83613726565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146123d157600080fd5b7f528c7dcea75f0c9e110a038e50647cd6a70ac06d331399b77dd9a80f903ebc1681604051610d199190614e05565b6000611adb838361380f565b604051633b3bff0f60e01b81526001600160a01b03821660048201526000903090633b3bff0f90602401602060405180830381600087803b15801561245057600080fd5b505af1158015612464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124889190614914565b9050600080516020615a9c833981519152816040516124a991815260200190565b60405180910390a1601681146124be57600080fd5b604051600181527f319ab7084208e4afa38c6e6ff7aea9587439f2e4700746f4c7d425fea17426d290602001610b49565b60006111b584848461385e565b6007805460ff191682151590811790915560405160ff909116151581527f457c3a16a0ebdc38e3675609957ca3fcc4490e220bd15d85d34f58e2e145cb089060200160405180910390a150565b6040805160008082526020820190925281908161258e565b60408051606081018252600080825260208083018290529282015282526000199092019101816125615790505b50905060006040518060400160405280336001600160a01b03168152602001856125b790614e18565b600790810b9091526040805180820182526001600160a01b038a1681529187900b602083015280516002808252606082019092529293509091600091816020015b60408051808201909152600080825260208201528152602001906001900390816125f8579050509050828160008151811061263557612635614976565b6020026020010181905250818160018151811061265457612654614976565b602090810291909101810191909152604080516060810182526001600160a01b038a16815291820183905281810186905280516001808252818301909252600091816020015b6126c7604051806060016040528060006001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161269a57905050905081816000815181106126f0576126f0614976565b602002602001018190525061270481613519565b96506016871461271357600080fd5b5050505050509392505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167ff49f40db000000000000000000000000000000000000000000000000000000001790529051600091829182918291610167916127a39161492d565b6000604051808303816000865af19150503d80600081146127e0576040519150601f19603f3d011682016040523d82523d6000602084013e6127e5565b606091505b5091509150816127f8576015600061280c565b8080602001905181019061280c9190614dd9565b60039190910b9890975095505050505050565b604080516001600160a01b0384166024820152604480820184905282518083039091018152606490910182526020810180516001600160e01b03167f098f2366000000000000000000000000000000000000000000000000000000001790529051600091829182918291610167916128969161492d565b6000604051808303816000865af19150503d80600081146128d3576040519150601f19603f3d011682016040523d82523d6000602084013e6128d8565b606091505b5091509150816128eb5760156000611e59565b80806020019051810190611e599190614e4e565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f52f91387000000000000000000000000000000000000000000000000000000009060640161121e565b6040516001600160a01b0382166024820152600090819081908190610167907fa7daa18d00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129d1919061492d565b6000604051808303816000865af19150503d8060008114612a0e576040519150601f19603f3d011682016040523d82523d6000602084013e612a13565b606091505b509150915081612a265760156000612a3a565b80806020019051810190612a3a9190614dd9565b60039190910b969095509350505050565b612a53613a2f565b6040518060400160405280612a6887876138b4565b8152602001612a7785856138cd565b905295945050505050565b612a8a613a2f565b6040518060400160405280612a9e8661399d565b8152602001612aad85856138cd565b9052949350505050565b600080848061010001516000015163ffffffff166000148015612ae757506101008101516040015163ffffffff16155b15612afd576101008101516276a7006040909101525b6000806101676001600160a01b031634637812a04b60e01b8a8a8a604051602401612b2a93929190614e7a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612b68919061492d565b60006040518083038185875af1925050503d8060008114612ba5576040519150601f19603f3d011682016040523d82523d6000602084013e612baa565b606091505b509150915081612bbd5760156000612bd1565b80806020019051810190612bd19190614e4e565b60039190910b999098509650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907feca36917000000000000000000000000000000000000000000000000000000009060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c80919061492d565b6000604051808303816000865af19150503d8060008114612cbd576040519150601f19603f3d011682016040523d82523d6000602084013e612cc2565b606091505b509150915081612cd3576015612ce7565b80806020019051810190612ce7919061495b565b60030b979650505050505050565b6000612cff613a8c565b604080516001600160a01b0386166024820152600785900b60448083019190915282518083039091018152606490910182526020810180516001600160e01b03167f287e1da8000000000000000000000000000000000000000000000000000000001790529051600091829161016791612d789161492d565b6000604051808303816000865af19150503d8060008114612db5576040519150601f19603f3d011682016040523d82523d6000602084013e612dba565b606091505b5091509150612dc7613a8c565b82612dd45760158161280c565b8180602001905181019061280c9190615504565b60008060006101676001600160a01b031663f7f38e2660e01b878787604051602401612e16939291906155ec565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612e54919061492d565b6000604051808303816000865af19150503d8060008114612e91576040519150601f19603f3d011682016040523d82523d6000602084013e612e96565b606091505b509150915081612ea7576015612ebb565b80806020019051810190612ebb919061495b565b60030b9695505050505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167f927da10500000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612f4b9161492d565b6000604051808303816000865af19150503d8060008114612f88576040519150601f19603f3d011682016040523d82523d6000602084013e612f8d565b606091505b509150915081612fa0576015600061280c565b8080602001905181019061280c9190615618565b604080516001600160a01b03831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167fae7611a000000000000000000000000000000000000000000000000000000000179052905160009160609182918291859182916101679161302c9161492d565b6000604051808303816000865af19150503d8060008114613069576040519150601f19603f3d011682016040523d82523d6000602084013e61306e565b606091505b509150915060608060608461308757601583838361309b565b8380602001905181019061309b9190615644565b60039390930b9d919c509a509098509650505050505050565b60006130be613ac7565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f3f28a19b00000000000000000000000000000000000000000000000000000000179052905160009182916101679161312d9161492d565b6000604051808303816000865af19150503d806000811461316a576040519150601f19603f3d011682016040523d82523d6000602084013e61316f565b606091505b509150915061317c613ac7565b8261318957601581611e59565b81806020019051810190611e5991906156dd565b6040516001600160a01b03838116602483015282166044820152600090819081908190610167907f46de0fb100000000000000000000000000000000000000000000000000000000906064016122e4565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907f5cfc9011000000000000000000000000000000000000000000000000000000009060a401612c42565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f5b8f8584000000000000000000000000000000000000000000000000000000009060640161121e565b60008060606000806101676001600160a01b031663278e0b8860e01b8989896040516024016132cf93929190615789565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161330d919061492d565b6000604051808303816000865af19150503d806000811461334a576040519150601f19603f3d011682016040523d82523d6000602084013e61334f565b606091505b509150915081613372576040805160008082526020820190925260159190613386565b80806020019051810190613386919061580d565b60039290920b9a90995090975095505050505050565b6040516001600160a01b0382166024820152600090819081908190610167907f335e04c10000000000000000000000000000000000000000000000000000000090604401612993565b600080868061010001516000015163ffffffff16600014801561341557506101008101516040015163ffffffff16155b1561342b576101008101516276a7006040909101525b6000806101676001600160a01b031634634c381ae760e01b8c8c8c8c8c60405160240161345c9594939291906158be565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161349a919061492d565b60006040518083038185875af1925050503d80600081146134d7576040519150601f19603f3d011682016040523d82523d6000602084013e6134dc565b606091505b5091509150816134ef5760156000613503565b808060200190518101906135039190614e4e565b60039190910b9b909a5098505050505050505050565b60008060006101676001600160a01b031663189a554c60e01b85604051602401610bfc9190615964565b6040516001600160a01b038216602482015260009081908190610167907ff069f7120000000000000000000000000000000000000000000000000000000090604401610bfc565b600080828061010001516000015163ffffffff1660001480156135ba57506101008101516040015163ffffffff16155b156135d0576101008101516276a7006040909101525b6000806101676001600160a01b031634639dc711e060e01b886040516024016135f99190615a3a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613637919061492d565b60006040518083038185875af1925050503d80600081146128d3576040519150601f19603f3d011682016040523d82523d6000602084013e6128d8565b6040516001600160a01b0384811660248301528316604482015263ffffffff8216606482015260009081908190610167907f9790686d0000000000000000000000000000000000000000000000000000000090608401612e16565b6040516001600160a01b03848116602483015283166044820152811515606482015260009081908190610167907f367605ca0000000000000000000000000000000000000000000000000000000090608401612e16565b6000613730613ae7565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f1f69565f00000000000000000000000000000000000000000000000000000000179052905160009182916101679161379f9161492d565b6000604051808303816000865af19150503d80600081146137dc576040519150601f19603f3d011682016040523d82523d6000602084013e6137e1565b606091505b50915091506137ee613ae7565b826137fb57601581611e59565b81806020019051810190611e599190615a4d565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde000000000000000000000000000000000000000000000000000000009060640161121e565b6040516001600160a01b038481166024830152831660448201526064810182905260009081908190610167907fe1f21c670000000000000000000000000000000000000000000000000000000090608401612e16565b6000600160ff84161b9050600160ff83161b81176111eb565b6139136040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156139285760018152610962565b8260ff166002141561394a576000546001600160a01b03166020820152610962565b8260ff16600314156139625760408101829052610962565b8260ff166004141561397a5760608101829052610962565b8260ff1660051415610962576000546001600160a01b0316608082015292915050565b600060ff82166139af57506001919050565b8160ff16600114156139c357506002919050565b8160ff16600214156139d757506004919050565b8160ff16600314156139eb57506008919050565b8160ff16600414156139ff57506010919050565b8160ff1660051415613a1357506020919050565b8160ff1660061415613a2757506040919050565b506000919050565b604051806040016040528060008152602001613a876040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6040518060c00160405280613a9f613ae7565b8152600060208201819052604082018190526060808301829052608083015260a09091015290565b6040518060400160405280613ada613ae7565b8152600060209091015290565b60408051610240810182526060610120820181815261014083018290526000610160840181905261018084018390526101a084018190526101c084018190526101e0840181905261020084018390528451928301855280835260208301819052938201939093526102208201529081908152602001600067ffffffffffffffff168152602001600015158152602001600015158152602001600015158152602001606081526020016060815260200160608152602001606081525090565b6001600160a01b0381168114613bba57600080fd5b50565b60008060408385031215613bd057600080fd5b8235613bdb81613ba5565b91506020830135613beb81613ba5565b809150509250929050565b600080600060608486031215613c0b57600080fd5b8335613c1681613ba5565b92506020840135613c2681613ba5565b91506040840135613c3681613ba5565b809150509250925092565b60008060408385031215613c5457600080fd5b8235613c5f81613ba5565b946020939093013593505050565b600060208284031215613c7f57600080fd5b81356111eb81613ba5565b8060070b8114613bba57600080fd5b60008060008060808587031215613caf57600080fd5b8435613cba81613ba5565b93506020850135613cca81613ba5565b92506040850135613cda81613ba5565b91506060850135613cea81613c8a565b939692955090935050565b60008060408385031215613d0857600080fd5b8235613d1381613ba5565b91506020830135613beb81613c8a565b60005b83811015613d3e578181015183820152602001613d26565b83811115613d4d576000848401525b50505050565b60008151808452613d6b816020860160208601613d23565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015613e365782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152613df860e08b0186613d53565b928601518a8403603f1901858c0152929450613e148584613d53565b9501511660c09890980197909752505098850198935090840190600101613d9d565b5091979650505050505050565b60006101608251818552613e5982860182613d53565b91505060208301518482036020860152613e738282613d53565b9150506040830151613e9060408601826001600160a01b03169052565b5060608301518482036060860152613ea88282613d53565b9150506080830151613ebe608086018215159052565b5060a0830151613ed660a086018263ffffffff169052565b5060c0830151613eea60c086018215159052565b5060e083015184820360e0860152613f028282613d7f565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff168852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613f5a565b509495945050505050565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101613fd5565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff9081168952848201518116858a0152604080830151909116908901526060808201516001600160a01b03908116918a01919091526080808301511515908a015260a091820151169088015260c09096019590820190600101614053565b600061012082518185526140d782860182613e43565b91505060208301516140f5602086018267ffffffffffffffff169052565b506040830151614109604086018215159052565b50606083015161411d606086018215159052565b506080830151614131608086018215159052565b5060a083015184820360a08601526141498282613f46565b91505060c083015184820360c08601526141638282613fc1565b91505060e083015184820360e086015261417d828261403f565b91505061010080840151858303828701526141988382613d53565b9695505050505050565b6000815160c084526141b760c08501826140c1565b9050602083015160070b602085015260408301516001600160a01b038082166040870152606085015160070b60608701526080850151915085830360808701526142018383613d53565b92508060a08601511660a087015250508091505092915050565b82815260406020820152600061112a60408301846141a2565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561426d5761426d614234565b60405290565b6040805190810167ffffffffffffffff8111828210171561426d5761426d614234565b60405160a0810167ffffffffffffffff8111828210171561426d5761426d614234565b604051610120810167ffffffffffffffff8111828210171561426d5761426d614234565b60405160c0810167ffffffffffffffff8111828210171561426d5761426d614234565b604051601f8201601f1916810167ffffffffffffffff8111828210171561432957614329614234565b604052919050565b600067ffffffffffffffff82111561434b5761434b614234565b5060051b60200190565b60008060006060848603121561436a57600080fd5b833561437581613ba5565b925060208481013561438681613ba5565b9250604085013567ffffffffffffffff8111156143a257600080fd5b8501601f810187136143b357600080fd5b80356143c66143c182614331565b614300565b81815260059190911b820183019083810190898311156143e557600080fd5b928401925b8284101561440c5783356143fd81613c8a565b825292840192908401906143ea565b80955050505050509250925092565b63ffffffff81168114613bba57600080fd5b600080828403608081121561444157600080fd5b833561444c81613ba5565b92506060601f198201121561446057600080fd5b5061446961424a565b60208401356144778161441b565b8152604084013561448781613ba5565b6020820152606084013561449a8161441b565b6040820152919491935090915050565b8460070b81526080602082015260006144c66080830186613f46565b82810360408401526144d88186613fc1565b905082810360608401526144ec818561403f565b979650505050505050565b600081516040845261450c60408501826140c1565b60209384015163ffffffff16949093019390935250919050565b82815260406020820152600061112a60408301846144f7565b67ffffffffffffffff81168114613bba57600080fd5b600067ffffffffffffffff82111561456f5761456f614234565b50601f01601f191660200190565b60008060006060848603121561459257600080fd5b833561459d81613ba5565b92506020848101356145ae8161453f565b925060408581013567ffffffffffffffff808211156145cc57600080fd5b818801915088601f8301126145e057600080fd5b81356145ee6143c182614331565b81815260059190911b8301850190858101908b83111561460d57600080fd5b8685015b83811015614681578035858111156146295760008081fd5b8601603f81018e1361463b5760008081fd5b8881013561464b6143c182614555565b8181528f8a8385010111156146605760008081fd5b818a84018c83013760009181018b0191909152845250918701918701614611565b50809750505050505050509250925092565b600081518084526020808501945080840160005b83811015613fb657815160070b875295820195908201906001016146a7565b83815267ffffffffffffffff831660208201526060604082015260006146ef6060830184614693565b95945050505050565b6000806020838503121561470b57600080fd5b823567ffffffffffffffff8082111561472357600080fd5b818501915085601f83011261473757600080fd5b81358181111561474657600080fd5b8660208260051b850101111561475b57600080fd5b60209290920196919550909350505050565b828152608081016111eb6020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b6000806000606084860312156147bc57600080fd5b83356147c781613ba5565b925060208401356147d781613ba5565b91506040840135613c368161441b565b8015158114613bba57600080fd5b60008060006060848603121561480a57600080fd5b833561481581613ba5565b9250602084013561482581613ba5565b91506040840135613c36816147e7565b82815260406020820152600061112a60408301846140c1565b60008060006060848603121561486357600080fd5b833561486e81613ba5565b9250602084013561487e81613ba5565b929592945050506040919091013590565b6000602082840312156148a157600080fd5b81356111eb816147e7565b6000806000606084860312156148c157600080fd5b83356148cc81613ba5565b925060208401356148dc81613ba5565b91506040840135613c3681613c8a565b8051611b3d81613c8a565b60006020828403121561490957600080fd5b81516111eb81613c8a565b60006020828403121561492657600080fd5b5051919050565b6000825161493f818460208701613d23565b9190910192915050565b8051600381900b8114611b3d57600080fd5b60006020828403121561496d57600080fd5b6111eb82614949565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806149a057607f821691505b602082108114156149c157634e487b7160e01b600052602260045260246000fd5b50919050565b6020815260006111eb60208301846141a2565b6001600160a01b0383168152608081016111eb6020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b606081526000614a306060830186613f46565b8281036020840152614a428186613fc1565b90508281036040840152614198818561403f565b6020815260006111eb60208301846144f7565b67ffffffffffffffff8316815260406020820152600061112a6040830184614693565b600082601f830112614a9d57600080fd5b81356020614aad6143c183614331565b82815260609283028501820192828201919087851115614acc57600080fd5b8387015b85811015614b2e5781818a031215614ae85760008081fd5b614af061424a565b8135614afb81613ba5565b815281860135614b0a81613ba5565b81870152604082810135614b1d81613c8a565b908201528452928401928101614ad0565b5090979650505050505050565b6000614b496143c184614331565b80848252602080830192508560051b850136811115614b6757600080fd5b855b81811015614c9c57803567ffffffffffffffff80821115614b8a5760008081fd5b818901915060608236031215614ba05760008081fd5b614ba861424a565b8235614bb381613ba5565b81528286013582811115614bc75760008081fd5b830136601f820112614bd95760008081fd5b8035614be76143c182614331565b81815260069190911b82018801908881019036831115614c075760008081fd5b928901925b82841015614c5d5760408436031215614c255760008081fd5b614c2d614273565b8435614c3881613ba5565b8152848b0135614c4781613c8a565b818c015282526040939093019290890190614c0c565b848a01525060409150508381013583811115614c795760008081fd5b614c8536828701614a8c565b918301919091525087525050938201938201614b69565b50919695505050505050565b8051611b3d816147e7565b60008060408385031215614cc657600080fd5b8251614cd181613c8a565b6020840151909250613beb816147e7565b8051611b3d8161441b565b8051611b3d81613ba5565b600060608284031215614d0a57600080fd5b614d1261424a565b90508151614d1f8161441b565b81526020820151614d2f81613ba5565b60208201526040820151614d428161441b565b604082015292915050565b60008060808385031215614d6057600080fd5b82519150614d718460208501614cf8565b90509250929050565b606081016109628284805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060808385031215614dc157600080fd5b614dca83614949565b9150614d718460208501614cf8565b60008060408385031215614dec57600080fd5b614df583614949565b91506020830151613beb816147e7565b6020815260006111eb60208301846140c1565b60008160070b677fffffffffffffff19811415614e4557634e487b7160e01b600052601160045260246000fd5b60000392915050565b60008060408385031215614e6157600080fd5b614e6a83614949565b91506020830151613beb81613ba5565b606081526000614e8d6060830186613e43565b60208301949094525060400152919050565b600082601f830112614eb057600080fd5b8151614ebe6143c182614555565b818152846020838601011115614ed357600080fd5b61112a826020830160208701613d23565b600082601f830112614ef557600080fd5b81516020614f056143c183614331565b82815260059290921b84018101918181019086841115614f2457600080fd5b8286015b8481101561503a57805167ffffffffffffffff80821115614f4857600080fd5b908801906040601f19838c038101821315614f6257600080fd5b614f6a614273565b8885015181528285015184811115614f8157600080fd5b949094019360a0858e0383011215614f995760008081fd5b614fa1614296565b915088850151614fb0816147e7565b825284830151614fbf81613ba5565b828a015260608581015185811115614fd75760008081fd5b614fe58f8c838a0101614e9f565b85850152506080935083860151858111156150005760008081fd5b61500e8f8c838a0101614e9f565b82850152505061502060a08601614ced565b928201929092528188015285525050918301918301614f28565b509695505050505050565b6000610160828403121561505857600080fd5b6150606142b9565b9050815167ffffffffffffffff8082111561507a57600080fd5b61508685838601614e9f565b8352602084015191508082111561509c57600080fd5b6150a885838601614e9f565b60208401526150b960408501614ced565b604084015260608401519150808211156150d257600080fd5b6150de85838601614e9f565b60608401526150ef60808501614ca8565b608084015261510060a08501614ce2565b60a084015261511160c08501614ca8565b60c084015260e084015191508082111561512a57600080fd5b5061513784828501614ee4565b60e08301525061010061514c84828501614cf8565b9082015292915050565b8051611b3d8161453f565b600082601f83011261517257600080fd5b815160206151826143c183614331565b82815260a092830285018201928282019190878511156151a157600080fd5b8387015b85811015614b2e5781818a0312156151bd5760008081fd5b6151c5614296565b81516151d08161441b565b8152818601516151df81613ba5565b818701526040828101516151f2816147e7565b90820152606082810151615205816147e7565b9082015260808281015161521881613ba5565b9082015284529284019281016151a5565b600082601f83011261523a57600080fd5b8151602061524a6143c183614331565b82815260c0928302850182019282820191908785111561526957600080fd5b8387015b85811015614b2e5781818a0312156152855760008081fd5b61528d6142dd565b81516152988161441b565b8152818601516152a78161441b565b818701526040828101516152ba8161441b565b908201526060828101516152cd8161441b565b908201526080828101516152e0816147e7565b9082015260a0828101516152f381613ba5565b90820152845292840192810161526d565b600082601f83011261531557600080fd5b815160206153256143c183614331565b82815260c0928302850182019282820191908785111561534457600080fd5b8387015b85811015614b2e5781818a0312156153605760008081fd5b6153686142dd565b81516153738161441b565b8152818601516153828161441b565b818701526040828101516153958161441b565b908201526060828101516153a881613ba5565b908201526080828101516153bb816147e7565b9082015260a0828101516153ce81613ba5565b908201528452928401928101615348565b600061012082840312156153f257600080fd5b6153fa6142b9565b9050815167ffffffffffffffff8082111561541457600080fd5b61542085838601615045565b835261542e60208501615156565b602084015261543f60408501614ca8565b604084015261545060608501614ca8565b606084015261546160808501614ca8565b608084015260a084015191508082111561547a57600080fd5b61548685838601615161565b60a084015260c084015191508082111561549f57600080fd5b6154ab85838601615229565b60c084015260e08401519150808211156154c457600080fd5b6154d085838601615304565b60e0840152610100915081840151818111156154eb57600080fd5b6154f786828701614e9f565b8385015250505092915050565b6000806040838503121561551757600080fd5b61552083614949565b9150602083015167ffffffffffffffff8082111561553d57600080fd5b9084019060c0828703121561555157600080fd5b6155596142dd565b82518281111561556857600080fd5b615574888286016153df565b825250615583602084016148ec565b602082015261559460408401614ced565b60408201526155a5606084016148ec565b60608201526080830151828111156155bc57600080fd5b6155c888828601614e9f565b6080830152506155da60a08401614ced565b60a08201528093505050509250929050565b60006001600160a01b038086168352808516602084015250606060408301526146ef6060830184614693565b6000806040838503121561562b57600080fd5b61563483614949565b9150602083015190509250929050565b6000806000806080858703121561565a57600080fd5b61566385614949565b9350602085015167ffffffffffffffff8082111561568057600080fd5b61568c88838901615161565b945060408701519150808211156156a257600080fd5b6156ae88838901615229565b935060608701519150808211156156c457600080fd5b506156d187828801615304565b91505092959194509250565b600080604083850312156156f057600080fd5b6156f983614949565b9150602083015167ffffffffffffffff8082111561571657600080fd5b908401906040828703121561572a57600080fd5b60405160408101818110838211171561574557615745614234565b60405282518281111561575757600080fd5b615763888286016153df565b825250602083015192506157768361441b565b8260208201528093505050509250929050565b6000606082016001600160a01b0386168352602067ffffffffffffffff8616818501526060604085015281855180845260808601915060808160051b870101935082870160005b828110156157fe57607f198887030184526157ec868351613d53565b955092840192908401906001016157d0565b50939998505050505050505050565b60008060006060848603121561582257600080fd5b61582b84614949565b925060208085015161583c8161453f565b604086015190935067ffffffffffffffff81111561585957600080fd5b8501601f8101871361586a57600080fd5b80516158786143c182614331565b81815260059190911b8201830190838101908983111561589757600080fd5b928401925b8284101561440c5783516158af81613c8a565b8252928401929084019061589c565b60a0815260006158d160a0830188613e43565b86602084015285604084015282810360608401526158ef8186613f46565b905082810360808401526159038185613fc1565b98975050505050505050565b600081518084526020808501945080840160005b83811015613fb657815180516001600160a01b03908116895284820151168489015260409081015160070b9088015260609096019590820190600101615923565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015615a2b57898403603f19018652825180516001600160a01b0390811686528982015160608b880181905281519088018190526080880192918c01919086905b808210156159fd5783518051841686528e015160070b8e860152938c0193928d0192600191909101906159cf565b5050505090880151858203868a015290615a17818361590f565b978a0197955050509187019160010161598c565b50919998505050505050505050565b6020815260006111eb6020830184613e43565b60008060408385031215615a6057600080fd5b615a6983614949565b9150602083015167ffffffffffffffff811115615a8557600080fd5b615a91858286016153df565b915050925092905056fe90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aaa26469706673582212200e78f269d9e7b70c329341bf2e8cd11c83b1b8affe71ae06bf9922e36f1a7a9764736f6c63430008090033", - "deployedBytecode": "0x6080604052600436106102c65760003560e01c80638070905f11610179578063d85f74c1116100d6578063f2f38a741161008a578063f848fec411610064578063f848fec414610844578063f9e978bd14610864578063fdc8321e1461088457600080fd5b8063f2f38a74146107d6578063f4a01e5b14610804578063f7be34251461082457600080fd5b8063eee55ac8116100bb578063eee55ac814610776578063f25b120014610796578063f2c31ff4146107b657600080fd5b8063d85f74c114610743578063d92ac2481461075657600080fd5b8063a345f7bd1161012d578063af99c63311610112578063af99c633146106d5578063c0b19b6d146106f5578063d614cdb81461072357600080fd5b8063a345f7bd1461067b578063a3ad5b551461069b57600080fd5b80638ba74da01161015e5780638ba74da0146106285780638f8d7f991461063b5780639604ca651461065b57600080fd5b80638070905f146105d957806386f88d881461060857600080fd5b80634cbdb37b1161022757806369837dc2116101db5780636da6b1f0116101c05780636da6b1f0146105795780637c41ad2c146105995780637d3e5da8146105b957600080fd5b806369837dc21461052b5780636a4dde211461055957600080fd5b8063593d6e821161020c578063593d6e82146104a65780635a5e6c31146104c65780635b9076b7146104fb57600080fd5b80634cbdb37b1461045857806356af84031461048657600080fd5b80632eecbca31161027e5780633eed2c39116102635780633eed2c39146104035780634b5c6687146104235780634ba670351461043857600080fd5b80632eecbca3146103c35780633b3bff0f146103e357600080fd5b806319db44b6116102af57806319db44b6146103385780632b256ec8146103755780632d73bb2e146103a357600080fd5b80630fd2601e146102cb57806313c05dd814610303575b600080fd5b3480156102d757600080fd5b506102eb6102e6366004613bbd565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561030f57600080fd5b5061032361031e366004613bf6565b610968565b604080519283529015156020830152016102fa565b34801561034457600080fd5b50610358610353366004613c41565b6109e6565b604080519283526001600160a01b039091166020830152016102fa565b34801561038157600080fd5b50610395610390366004613c6d565b610a6a565b6040519081526020016102fa565b3480156103af57600080fd5b506103956103be366004613bbd565b610b56565b3480156103cf57600080fd5b506102eb6103de366004613bbd565b610b9b565b3480156103ef57600080fd5b506103956103fe366004613c6d565b610bd2565b34801561040f57600080fd5b5061032361041e366004613c6d565b610cac565b610436610431366004613c6d565b610d26565b005b34801561044457600080fd5b50610395610453366004613c99565b6110e6565b34801561046457600080fd5b50610478610473366004613cf5565b611132565b6040516102fa92919061421b565b34801561049257600080fd5b506103956104a1366004614355565b6111a8565b3480156104b257600080fd5b506103956104c136600461442d565b6111f2565b3480156104d257600080fd5b506104e66104e1366004613bf6565b6112cf565b604080519283526020830191909152016102fa565b34801561050757600080fd5b5061051b610516366004613c6d565b611340565b6040516102fa94939291906144aa565b34801561053757600080fd5b5061054b610546366004613c6d565b6113d2565b6040516102fa929190614526565b34801561056557600080fd5b50610323610574366004613bbd565b611447565b34801561058557600080fd5b50610395610594366004613c99565b6114be565b3480156105a557600080fd5b506103956105b4366004613c6d565b6114cc565b3480156105c557600080fd5b506103956105d4366004613bbd565b6114fa565b3480156105e557600080fd5b506105f96105f436600461457d565b611506565b6040516102fa939291906146c6565b34801561061457600080fd5b50610323610623366004613c6d565b61158e565b610436610636366004613bbd565b6115ff565b34801561064757600080fd5b506102eb610656366004613bbd565b611a91565b34801561066757600080fd5b506103956106763660046146f8565b611ac7565b34801561068757600080fd5b50610395610696366004613c6d565b611afc565b3480156106a757600080fd5b506106bb6106b6366004613bbd565b611b42565b6040805160079390930b83529015156020830152016102fa565b3480156106e157600080fd5b506102eb6106f0366004613bbd565b611c34565b34801561070157600080fd5b50610715610710366004613c6d565b611c6a565b6040516102fa92919061476d565b34801561072f57600080fd5b5061071561073e366004613c6d565b611d61565b610436610751366004613c6d565b611e6b565b34801561076257600080fd5b506103956107713660046147a7565b612203565b34801561078257600080fd5b5061039561079136600461442d565b612210565b3480156107a257600080fd5b506103956107b13660046147f5565b6122a3565b3480156107c257600080fd5b506106bb6107d1366004613bbd565b6122b0565b3480156107e257600080fd5b506107f66107f1366004613c6d565b61238b565b6040516102fa929190614835565b34801561081057600080fd5b5061039561081f366004613bbd565b612400565b34801561083057600080fd5b5061039561083f366004613c6d565b61240c565b34801561085057600080fd5b5061039561085f36600461484e565b6124ef565b34801561087057600080fd5b5061043661087f36600461488f565b6124fc565b34801561089057600080fd5b5061039561089f3660046148ac565b612549565b604051638f8d7f9960e01b81526001600160a01b038084166004830152821660248201526000903090638f8d7f99906044015b602060405180830381600087803b1580156108f157600080fd5b505af1158015610905573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092991906148f7565b604051600782900b8152909150600080516020615a9c8339815191529060200160405180910390a1600781900b60161461096257600080fd5b92915050565b600080610976858585612720565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146109a957600080fd5b60405181151581527e1c2e72360171244b3bb8cc8ddd767820edf37138ad6f129fb3574b407c307d906020015b60405180910390a1935093915050565b6000806109f3848461281f565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214610a2657600080fd5b6040516001600160a01b03821681527fc2c78c7c31baf14949e75c51df12be56edb9af523cf82839c2869bbcf13b3ecb906020015b60405180910390a19250929050565b604051631f106b4b60e21b81526001600160a01b03821660048201526000903090637c41ad2c90602401602060405180830381600087803b158015610aae57600080fd5b505af1158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae69190614914565b9050600080516020615a9c83398151915281604051610b0791815260200190565b60405180910390a160168114610b1c57600080fd5b604051600181527f0c9c765845f4d139956bb8fc8decb2eec6093c9c608b809641b16054b29f0e13906020015b60405180910390a1919050565b6000610b6283836128ff565b60070b9050600080516020615a9c83398151915281604051610b8691815260200190565b60405180910390a16016811461096257600080fd5b60405163af99c63360e01b81526001600160a01b03808416600483015282166024820152600090309063af99c633906044016108d7565b6040516001600160a01b03821660248201526000908190819061016790633b3bff0f60e01b906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610c3a919061492d565b6000604051808303816000865af19150503d8060008114610c77576040519150601f19603f3d011682016040523d82523d6000602084013e610c7c565b606091505b509150915081610c8d576015610ca1565b80806020019051810190610ca1919061495b565b60030b949350505050565b600080610cb88361294e565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214610ceb57600080fd5b60405181151581527f6b7f3306751292f85ab4161ee2b0ac16dfc8ded13e6446ce6bd859d0a2f4c78e906020015b60405180910390a1915091565b60408051600480825260a08201909252600091816020015b610d46613a2f565b815260200190600190039081610d3e579050509050610d7960006006600160405180602001604052806000815250612a4b565b81600081518110610d8c57610d8c614976565b6020026020010181905250610db260018060405180602001604052806000815250612a82565b81600181518110610dc557610dc5614976565b6020026020010181905250610dec6002600160405180602001604052806000815250612a82565b81600281518110610dff57610dff614976565b6020026020010181905250610e266003600160405180602001604052806000815250612a82565b81600381518110610e3957610e39614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff168152509050600060405180610120016040528060018054610e979061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec39061498c565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050815260200160028054610f279061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610f539061498c565b8015610fa05780601f10610f7557610100808354040283529160200191610fa0565b820191906000526020600020905b815481529060010190602001808311610f8357829003601f168201915b50505050508152602001856001600160a01b0316815260200160038054610fc69061498c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff29061498c565b801561103f5780601f106110145761010080835404028352916020019161103f565b820191906000526020600020905b81548152906001019060200180831161102257829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a001839052600454600654919250600091829161109091859190612ab7565b9092509050601682146110a257600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b60006110f485858585612be5565b9050600080516020615a9c8339815191528160405161111591815260200190565b60405180910390a16016811461112a57600080fd5b949350505050565b600061113c613a8c565b6111468484612cf5565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461117957600080fd5b7fa516f81c528634d0fc1e993bba1d227231b4bd6d1beb72d33b056a6199c0f98881604051610a5b91906149c7565b60006111b5848484612de8565b9050600080516020615a9c833981519152816040516111d691815260200190565b60405180910390a1601681146111eb57600080fd5b9392505050565b60008060006101676001600160a01b031663593d6e8260e01b868660405160240161121e9291906149da565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161125c919061492d565b6000604051808303816000865af19150503d8060008114611299576040519150601f19603f3d011682016040523d82523d6000602084013e61129e565b606091505b5091509150816112af5760156112c3565b808060200190518101906112c3919061495b565b60030b95945050505050565b6000806112dd858585612ec8565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461131057600080fd5b6040518181527f25b6684a7e8fe1b676e9c39c8dd65034fbafea906d3bdfd97bf748b7b55e14c8906020016109d6565b6000606080606061135085612fb4565b604051600785900b815293975091955093509150600080516020615a9c8339815191529060200160405180910390a1600784900b60161461139057600080fd5b7f2efc8334b040613a552197fe34283d6ca2909c8ffae393e128424931f20c69b38383836040516113c393929190614a1d565b60405180910390a19193509193565b60006113dc613ac7565b6113e5836130b4565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a16016821461141857600080fd5b7f476a9a9b28e2717d55288b2ae3c48a72aac52b11f8bd855017c9d41d9fc1896481604051610d199190614a56565b600080611454848461319d565b60405160079290920b80835293509150600080516020615a9c8339815191529060200160405180910390a16016821461148c57600080fd5b60405181151581527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e90602001610a5b565b60006110f4858585856131ee565b6040516001600160a01b03821660248201526000908190819061016790631f106b4b60e21b90604401610bfc565b6000610b62838361324f565b600080606061151686868661329e565b6040518381529295509093509150600080516020615a9c8339815191529060200160405180910390a16016831461154c57600080fd5b7feff23992f47b3c101679f8b4dc9d3e242c903909dba4a453f2b2341ad463b0e2828260405161157d929190614a69565b60405180910390a193509350939050565b60008061159a8361339c565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146115cd57600080fd5b60405181151581527f9ee19e13dfa1ba8db2502e15ff56dbecdeb0e0473323fb195473ce648030a2cd90602001610d19565b604080516001808252818301909252600091816020015b61161e613a2f565b815260200190600190039081611616579050509050611650600080600160405180602001604052806000815250612a4b565b8160008151811061166357611663614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546116c19061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546116ed9061498c565b801561173a5780601f1061170f5761010080835404028352916020019161173a565b820191906000526020600020905b81548152906001019060200180831161171d57829003601f168201915b50505050508152602001600280546117519061498c565b80601f016020809104026020016040519081016040528092919081815260200182805461177d9061498c565b80156117ca5780601f1061179f576101008083540402835291602001916117ca565b820191906000526020600020905b8154815290600101906020018083116117ad57829003601f168201915b50505050508152602001866001600160a01b03168152602001600380546117f09061498c565b80601f016020809104026020016040519081016040528092919081815260200182805461181c9061498c565b80156118695780601f1061183e57610100808354040283529160200191611869565b820191906000526020600020905b81548152906001019060200180831161184c57829003601f168201915b505050918352505060016020820181905260055463ffffffff166040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816118ba5750506040805160a081018252600181526001600160a01b0388811660208301526000928201839052606082018390528916608082015282519293509183919061193d5761193d614976565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a0820152825260001990920191018161195f5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a0830152825192935090918391906119f3576119f3614976565b6020026020010181905250600080611a128560045460065487876133e5565b91509150600080516020615a9c83398151915282604051611a3591815260200190565b60405180910390a160168214611a4a57600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b038381166024830152821660448201526000908190819061016790638f8d7f9960e01b9060640161121e565b6000611adb611ad68385614b3b565b613519565b9050600080516020615a9c83398151915281604051610b8691815260200190565b6000611b0782613543565b9050600080516020615a9c83398151915281604051611b2891815260200190565b60405180910390a160168114611b3d57600080fd5b919050565b604051633cb0c7fd60e21b81526001600160a01b038084166004830152821660248201526000908190309063f2c31ff4906044016040805180830381600087803b158015611b8f57600080fd5b505af1158015611ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc79190614cb3565b604051600783900b81529193509150600080516020615a9c8339815191529060200160405180910390a1600782900b601614611c0257600080fd5b60405181151581527fd24dda6928587354b65aa1a18c2eaf249bef7e5bafd2a71fac71d286f76f957f90602001610a5b565b6040516001600160a01b03838116602483015282166044820152600090819081906101679063af99c63360e01b9060640161121e565b60408051606081018252600080825260208201819052918101829052604051631ac299b760e31b81526001600160a01b0384166004820152309063d614cdb890602401608060405180830381600087803b158015611cc757600080fd5b505af1158015611cdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cff9190614d4d565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a160168214611d3257600080fd5b7fa0a16bf9db2c17796faeca5af5aaeef8523f9d4c350c512cb00062ad89604f8881604051610d199190614d7a565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b0316631ac299b760e31b179052925190928391829161016791611dd3919061492d565b6000604051808303816000865af19150503d8060008114611e10576040519150601f19603f3d011682016040523d82523d6000602084013e611e15565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082611e4557601581611e59565b81806020019051810190611e599190614dae565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b611e8b613a2f565b815260200190600190039081611e83579050509050611ebe60006006600160405180602001604052806000815250612a4b565b81600081518110611ed157611ed1614976565b6020026020010181905250611ef760018060405180602001604052806000815250612a82565b81600181518110611f0a57611f0a614976565b6020026020010181905250611f316002600160405180602001604052806000815250612a82565b81600281518110611f4457611f44614976565b6020026020010181905250611f6b6004600160405180602001604052806000815250612a82565b81600381518110611f7e57611f7e614976565b6020026020010181905250611fa56003600160405180602001604052806000815250612a82565b81600481518110611fb857611fb8614976565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546120169061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546120429061498c565b801561208f5780601f106120645761010080835404028352916020019161208f565b820191906000526020600020905b81548152906001019060200180831161207257829003601f168201915b50505050508152602001600280546120a69061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546120d29061498c565b801561211f5780601f106120f45761010080835404028352916020019161211f565b820191906000526020600020905b81548152906001019060200180831161210257829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546121459061498c565b80601f01602080910402602001604051908101604052809291908181526020018280546121719061498c565b80156121be5780601f10612193576101008083540402835291602001916121be565b820191906000526020600020905b8154815290600101906020018083116121a157829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905290506000806110908361358a565b60006111b5848484613674565b6040517f593d6e82000000000000000000000000000000000000000000000000000000008152600090309063593d6e829061225190869086906004016149da565b602060405180830381600087803b15801561226b57600080fd5b505af115801561227f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adb9190614914565b60006111b58484846136cf565b6040516001600160a01b0383811660248301528216604482015260009081908190819061016790633cb0c7fd60e21b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612322919061492d565b6000604051808303816000865af19150503d806000811461235f576040519150601f19603f3d011682016040523d82523d6000602084013e612364565b606091505b5091509150816123775760156000611e59565b80806020019051810190611e599190614dd9565b6000612395613ae7565b61239e83613726565b6040518281529193509150600080516020615a9c8339815191529060200160405180910390a1601682146123d157600080fd5b7f528c7dcea75f0c9e110a038e50647cd6a70ac06d331399b77dd9a80f903ebc1681604051610d199190614e05565b6000611adb838361380f565b604051633b3bff0f60e01b81526001600160a01b03821660048201526000903090633b3bff0f90602401602060405180830381600087803b15801561245057600080fd5b505af1158015612464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124889190614914565b9050600080516020615a9c833981519152816040516124a991815260200190565b60405180910390a1601681146124be57600080fd5b604051600181527f319ab7084208e4afa38c6e6ff7aea9587439f2e4700746f4c7d425fea17426d290602001610b49565b60006111b584848461385e565b6007805460ff191682151590811790915560405160ff909116151581527f457c3a16a0ebdc38e3675609957ca3fcc4490e220bd15d85d34f58e2e145cb089060200160405180910390a150565b6040805160008082526020820190925281908161258e565b60408051606081018252600080825260208083018290529282015282526000199092019101816125615790505b50905060006040518060400160405280336001600160a01b03168152602001856125b790614e18565b600790810b9091526040805180820182526001600160a01b038a1681529187900b602083015280516002808252606082019092529293509091600091816020015b60408051808201909152600080825260208201528152602001906001900390816125f8579050509050828160008151811061263557612635614976565b6020026020010181905250818160018151811061265457612654614976565b602090810291909101810191909152604080516060810182526001600160a01b038a16815291820183905281810186905280516001808252818301909252600091816020015b6126c7604051806060016040528060006001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161269a57905050905081816000815181106126f0576126f0614976565b602002602001018190525061270481613519565b96506016871461271357600080fd5b5050505050509392505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167ff49f40db000000000000000000000000000000000000000000000000000000001790529051600091829182918291610167916127a39161492d565b6000604051808303816000865af19150503d80600081146127e0576040519150601f19603f3d011682016040523d82523d6000602084013e6127e5565b606091505b5091509150816127f8576015600061280c565b8080602001905181019061280c9190614dd9565b60039190910b9890975095505050505050565b604080516001600160a01b0384166024820152604480820184905282518083039091018152606490910182526020810180516001600160e01b03167f098f2366000000000000000000000000000000000000000000000000000000001790529051600091829182918291610167916128969161492d565b6000604051808303816000865af19150503d80600081146128d3576040519150601f19603f3d011682016040523d82523d6000602084013e6128d8565b606091505b5091509150816128eb5760156000611e59565b80806020019051810190611e599190614e4e565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f52f91387000000000000000000000000000000000000000000000000000000009060640161121e565b6040516001600160a01b0382166024820152600090819081908190610167907fa7daa18d00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129d1919061492d565b6000604051808303816000865af19150503d8060008114612a0e576040519150601f19603f3d011682016040523d82523d6000602084013e612a13565b606091505b509150915081612a265760156000612a3a565b80806020019051810190612a3a9190614dd9565b60039190910b969095509350505050565b612a53613a2f565b6040518060400160405280612a6887876138b4565b8152602001612a7785856138cd565b905295945050505050565b612a8a613a2f565b6040518060400160405280612a9e8661399d565b8152602001612aad85856138cd565b9052949350505050565b600080848061010001516000015163ffffffff166000148015612ae757506101008101516040015163ffffffff16155b15612afd576101008101516276a7006040909101525b6000806101676001600160a01b031634637812a04b60e01b8a8a8a604051602401612b2a93929190614e7a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612b68919061492d565b60006040518083038185875af1925050503d8060008114612ba5576040519150601f19603f3d011682016040523d82523d6000602084013e612baa565b606091505b509150915081612bbd5760156000612bd1565b80806020019051810190612bd19190614e4e565b60039190910b999098509650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907feca36917000000000000000000000000000000000000000000000000000000009060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c80919061492d565b6000604051808303816000865af19150503d8060008114612cbd576040519150601f19603f3d011682016040523d82523d6000602084013e612cc2565b606091505b509150915081612cd3576015612ce7565b80806020019051810190612ce7919061495b565b60030b979650505050505050565b6000612cff613a8c565b604080516001600160a01b0386166024820152600785900b60448083019190915282518083039091018152606490910182526020810180516001600160e01b03167f287e1da8000000000000000000000000000000000000000000000000000000001790529051600091829161016791612d789161492d565b6000604051808303816000865af19150503d8060008114612db5576040519150601f19603f3d011682016040523d82523d6000602084013e612dba565b606091505b5091509150612dc7613a8c565b82612dd45760158161280c565b8180602001905181019061280c9190615504565b60008060006101676001600160a01b031663f7f38e2660e01b878787604051602401612e16939291906155ec565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612e54919061492d565b6000604051808303816000865af19150503d8060008114612e91576040519150601f19603f3d011682016040523d82523d6000602084013e612e96565b606091505b509150915081612ea7576015612ebb565b80806020019051810190612ebb919061495b565b60030b9695505050505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167f927da10500000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612f4b9161492d565b6000604051808303816000865af19150503d8060008114612f88576040519150601f19603f3d011682016040523d82523d6000602084013e612f8d565b606091505b509150915081612fa0576015600061280c565b8080602001905181019061280c9190615618565b604080516001600160a01b03831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167fae7611a000000000000000000000000000000000000000000000000000000000179052905160009160609182918291859182916101679161302c9161492d565b6000604051808303816000865af19150503d8060008114613069576040519150601f19603f3d011682016040523d82523d6000602084013e61306e565b606091505b509150915060608060608461308757601583838361309b565b8380602001905181019061309b9190615644565b60039390930b9d919c509a509098509650505050505050565b60006130be613ac7565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f3f28a19b00000000000000000000000000000000000000000000000000000000179052905160009182916101679161312d9161492d565b6000604051808303816000865af19150503d806000811461316a576040519150601f19603f3d011682016040523d82523d6000602084013e61316f565b606091505b509150915061317c613ac7565b8261318957601581611e59565b81806020019051810190611e5991906156dd565b6040516001600160a01b03838116602483015282166044820152600090819081908190610167907f46de0fb100000000000000000000000000000000000000000000000000000000906064016122e4565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907f5cfc9011000000000000000000000000000000000000000000000000000000009060a401612c42565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f5b8f8584000000000000000000000000000000000000000000000000000000009060640161121e565b60008060606000806101676001600160a01b031663278e0b8860e01b8989896040516024016132cf93929190615789565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161330d919061492d565b6000604051808303816000865af19150503d806000811461334a576040519150601f19603f3d011682016040523d82523d6000602084013e61334f565b606091505b509150915081613372576040805160008082526020820190925260159190613386565b80806020019051810190613386919061580d565b60039290920b9a90995090975095505050505050565b6040516001600160a01b0382166024820152600090819081908190610167907f335e04c10000000000000000000000000000000000000000000000000000000090604401612993565b600080868061010001516000015163ffffffff16600014801561341557506101008101516040015163ffffffff16155b1561342b576101008101516276a7006040909101525b6000806101676001600160a01b031634634c381ae760e01b8c8c8c8c8c60405160240161345c9594939291906158be565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161349a919061492d565b60006040518083038185875af1925050503d80600081146134d7576040519150601f19603f3d011682016040523d82523d6000602084013e6134dc565b606091505b5091509150816134ef5760156000613503565b808060200190518101906135039190614e4e565b60039190910b9b909a5098505050505050505050565b60008060006101676001600160a01b031663189a554c60e01b85604051602401610bfc9190615964565b6040516001600160a01b038216602482015260009081908190610167907ff069f7120000000000000000000000000000000000000000000000000000000090604401610bfc565b600080828061010001516000015163ffffffff1660001480156135ba57506101008101516040015163ffffffff16155b156135d0576101008101516276a7006040909101525b6000806101676001600160a01b031634639dc711e060e01b886040516024016135f99190615a3a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613637919061492d565b60006040518083038185875af1925050503d80600081146128d3576040519150601f19603f3d011682016040523d82523d6000602084013e6128d8565b6040516001600160a01b0384811660248301528316604482015263ffffffff8216606482015260009081908190610167907f9790686d0000000000000000000000000000000000000000000000000000000090608401612e16565b6040516001600160a01b03848116602483015283166044820152811515606482015260009081908190610167907f367605ca0000000000000000000000000000000000000000000000000000000090608401612e16565b6000613730613ae7565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f1f69565f00000000000000000000000000000000000000000000000000000000179052905160009182916101679161379f9161492d565b6000604051808303816000865af19150503d80600081146137dc576040519150601f19603f3d011682016040523d82523d6000602084013e6137e1565b606091505b50915091506137ee613ae7565b826137fb57601581611e59565b81806020019051810190611e599190615a4d565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde000000000000000000000000000000000000000000000000000000009060640161121e565b6040516001600160a01b038481166024830152831660448201526064810182905260009081908190610167907fe1f21c670000000000000000000000000000000000000000000000000000000090608401612e16565b6000600160ff84161b9050600160ff83161b81176111eb565b6139136040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156139285760018152610962565b8260ff166002141561394a576000546001600160a01b03166020820152610962565b8260ff16600314156139625760408101829052610962565b8260ff166004141561397a5760608101829052610962565b8260ff1660051415610962576000546001600160a01b0316608082015292915050565b600060ff82166139af57506001919050565b8160ff16600114156139c357506002919050565b8160ff16600214156139d757506004919050565b8160ff16600314156139eb57506008919050565b8160ff16600414156139ff57506010919050565b8160ff1660051415613a1357506020919050565b8160ff1660061415613a2757506040919050565b506000919050565b604051806040016040528060008152602001613a876040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6040518060c00160405280613a9f613ae7565b8152600060208201819052604082018190526060808301829052608083015260a09091015290565b6040518060400160405280613ada613ae7565b8152600060209091015290565b60408051610240810182526060610120820181815261014083018290526000610160840181905261018084018390526101a084018190526101c084018190526101e0840181905261020084018390528451928301855280835260208301819052938201939093526102208201529081908152602001600067ffffffffffffffff168152602001600015158152602001600015158152602001600015158152602001606081526020016060815260200160608152602001606081525090565b6001600160a01b0381168114613bba57600080fd5b50565b60008060408385031215613bd057600080fd5b8235613bdb81613ba5565b91506020830135613beb81613ba5565b809150509250929050565b600080600060608486031215613c0b57600080fd5b8335613c1681613ba5565b92506020840135613c2681613ba5565b91506040840135613c3681613ba5565b809150509250925092565b60008060408385031215613c5457600080fd5b8235613c5f81613ba5565b946020939093013593505050565b600060208284031215613c7f57600080fd5b81356111eb81613ba5565b8060070b8114613bba57600080fd5b60008060008060808587031215613caf57600080fd5b8435613cba81613ba5565b93506020850135613cca81613ba5565b92506040850135613cda81613ba5565b91506060850135613cea81613c8a565b939692955090935050565b60008060408385031215613d0857600080fd5b8235613d1381613ba5565b91506020830135613beb81613c8a565b60005b83811015613d3e578181015183820152602001613d26565b83811115613d4d576000848401525b50505050565b60008151808452613d6b816020860160208601613d23565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015613e365782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152613df860e08b0186613d53565b928601518a8403603f1901858c0152929450613e148584613d53565b9501511660c09890980197909752505098850198935090840190600101613d9d565b5091979650505050505050565b60006101608251818552613e5982860182613d53565b91505060208301518482036020860152613e738282613d53565b9150506040830151613e9060408601826001600160a01b03169052565b5060608301518482036060860152613ea88282613d53565b9150506080830151613ebe608086018215159052565b5060a0830151613ed660a086018263ffffffff169052565b5060c0830151613eea60c086018215159052565b5060e083015184820360e0860152613f028282613d7f565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff168852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613f5a565b509495945050505050565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101613fd5565b600081518084526020808501945080840160005b83811015613fb6578151805163ffffffff9081168952848201518116858a0152604080830151909116908901526060808201516001600160a01b03908116918a01919091526080808301511515908a015260a091820151169088015260c09096019590820190600101614053565b600061012082518185526140d782860182613e43565b91505060208301516140f5602086018267ffffffffffffffff169052565b506040830151614109604086018215159052565b50606083015161411d606086018215159052565b506080830151614131608086018215159052565b5060a083015184820360a08601526141498282613f46565b91505060c083015184820360c08601526141638282613fc1565b91505060e083015184820360e086015261417d828261403f565b91505061010080840151858303828701526141988382613d53565b9695505050505050565b6000815160c084526141b760c08501826140c1565b9050602083015160070b602085015260408301516001600160a01b038082166040870152606085015160070b60608701526080850151915085830360808701526142018383613d53565b92508060a08601511660a087015250508091505092915050565b82815260406020820152600061112a60408301846141a2565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561426d5761426d614234565b60405290565b6040805190810167ffffffffffffffff8111828210171561426d5761426d614234565b60405160a0810167ffffffffffffffff8111828210171561426d5761426d614234565b604051610120810167ffffffffffffffff8111828210171561426d5761426d614234565b60405160c0810167ffffffffffffffff8111828210171561426d5761426d614234565b604051601f8201601f1916810167ffffffffffffffff8111828210171561432957614329614234565b604052919050565b600067ffffffffffffffff82111561434b5761434b614234565b5060051b60200190565b60008060006060848603121561436a57600080fd5b833561437581613ba5565b925060208481013561438681613ba5565b9250604085013567ffffffffffffffff8111156143a257600080fd5b8501601f810187136143b357600080fd5b80356143c66143c182614331565b614300565b81815260059190911b820183019083810190898311156143e557600080fd5b928401925b8284101561440c5783356143fd81613c8a565b825292840192908401906143ea565b80955050505050509250925092565b63ffffffff81168114613bba57600080fd5b600080828403608081121561444157600080fd5b833561444c81613ba5565b92506060601f198201121561446057600080fd5b5061446961424a565b60208401356144778161441b565b8152604084013561448781613ba5565b6020820152606084013561449a8161441b565b6040820152919491935090915050565b8460070b81526080602082015260006144c66080830186613f46565b82810360408401526144d88186613fc1565b905082810360608401526144ec818561403f565b979650505050505050565b600081516040845261450c60408501826140c1565b60209384015163ffffffff16949093019390935250919050565b82815260406020820152600061112a60408301846144f7565b67ffffffffffffffff81168114613bba57600080fd5b600067ffffffffffffffff82111561456f5761456f614234565b50601f01601f191660200190565b60008060006060848603121561459257600080fd5b833561459d81613ba5565b92506020848101356145ae8161453f565b925060408581013567ffffffffffffffff808211156145cc57600080fd5b818801915088601f8301126145e057600080fd5b81356145ee6143c182614331565b81815260059190911b8301850190858101908b83111561460d57600080fd5b8685015b83811015614681578035858111156146295760008081fd5b8601603f81018e1361463b5760008081fd5b8881013561464b6143c182614555565b8181528f8a8385010111156146605760008081fd5b818a84018c83013760009181018b0191909152845250918701918701614611565b50809750505050505050509250925092565b600081518084526020808501945080840160005b83811015613fb657815160070b875295820195908201906001016146a7565b83815267ffffffffffffffff831660208201526060604082015260006146ef6060830184614693565b95945050505050565b6000806020838503121561470b57600080fd5b823567ffffffffffffffff8082111561472357600080fd5b818501915085601f83011261473757600080fd5b81358181111561474657600080fd5b8660208260051b850101111561475b57600080fd5b60209290920196919550909350505050565b828152608081016111eb6020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b6000806000606084860312156147bc57600080fd5b83356147c781613ba5565b925060208401356147d781613ba5565b91506040840135613c368161441b565b8015158114613bba57600080fd5b60008060006060848603121561480a57600080fd5b833561481581613ba5565b9250602084013561482581613ba5565b91506040840135613c36816147e7565b82815260406020820152600061112a60408301846140c1565b60008060006060848603121561486357600080fd5b833561486e81613ba5565b9250602084013561487e81613ba5565b929592945050506040919091013590565b6000602082840312156148a157600080fd5b81356111eb816147e7565b6000806000606084860312156148c157600080fd5b83356148cc81613ba5565b925060208401356148dc81613ba5565b91506040840135613c3681613c8a565b8051611b3d81613c8a565b60006020828403121561490957600080fd5b81516111eb81613c8a565b60006020828403121561492657600080fd5b5051919050565b6000825161493f818460208701613d23565b9190910192915050565b8051600381900b8114611b3d57600080fd5b60006020828403121561496d57600080fd5b6111eb82614949565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806149a057607f821691505b602082108114156149c157634e487b7160e01b600052602260045260246000fd5b50919050565b6020815260006111eb60208301846141a2565b6001600160a01b0383168152608081016111eb6020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b606081526000614a306060830186613f46565b8281036020840152614a428186613fc1565b90508281036040840152614198818561403f565b6020815260006111eb60208301846144f7565b67ffffffffffffffff8316815260406020820152600061112a6040830184614693565b600082601f830112614a9d57600080fd5b81356020614aad6143c183614331565b82815260609283028501820192828201919087851115614acc57600080fd5b8387015b85811015614b2e5781818a031215614ae85760008081fd5b614af061424a565b8135614afb81613ba5565b815281860135614b0a81613ba5565b81870152604082810135614b1d81613c8a565b908201528452928401928101614ad0565b5090979650505050505050565b6000614b496143c184614331565b80848252602080830192508560051b850136811115614b6757600080fd5b855b81811015614c9c57803567ffffffffffffffff80821115614b8a5760008081fd5b818901915060608236031215614ba05760008081fd5b614ba861424a565b8235614bb381613ba5565b81528286013582811115614bc75760008081fd5b830136601f820112614bd95760008081fd5b8035614be76143c182614331565b81815260069190911b82018801908881019036831115614c075760008081fd5b928901925b82841015614c5d5760408436031215614c255760008081fd5b614c2d614273565b8435614c3881613ba5565b8152848b0135614c4781613c8a565b818c015282526040939093019290890190614c0c565b848a01525060409150508381013583811115614c795760008081fd5b614c8536828701614a8c565b918301919091525087525050938201938201614b69565b50919695505050505050565b8051611b3d816147e7565b60008060408385031215614cc657600080fd5b8251614cd181613c8a565b6020840151909250613beb816147e7565b8051611b3d8161441b565b8051611b3d81613ba5565b600060608284031215614d0a57600080fd5b614d1261424a565b90508151614d1f8161441b565b81526020820151614d2f81613ba5565b60208201526040820151614d428161441b565b604082015292915050565b60008060808385031215614d6057600080fd5b82519150614d718460208501614cf8565b90509250929050565b606081016109628284805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060808385031215614dc157600080fd5b614dca83614949565b9150614d718460208501614cf8565b60008060408385031215614dec57600080fd5b614df583614949565b91506020830151613beb816147e7565b6020815260006111eb60208301846140c1565b60008160070b677fffffffffffffff19811415614e4557634e487b7160e01b600052601160045260246000fd5b60000392915050565b60008060408385031215614e6157600080fd5b614e6a83614949565b91506020830151613beb81613ba5565b606081526000614e8d6060830186613e43565b60208301949094525060400152919050565b600082601f830112614eb057600080fd5b8151614ebe6143c182614555565b818152846020838601011115614ed357600080fd5b61112a826020830160208701613d23565b600082601f830112614ef557600080fd5b81516020614f056143c183614331565b82815260059290921b84018101918181019086841115614f2457600080fd5b8286015b8481101561503a57805167ffffffffffffffff80821115614f4857600080fd5b908801906040601f19838c038101821315614f6257600080fd5b614f6a614273565b8885015181528285015184811115614f8157600080fd5b949094019360a0858e0383011215614f995760008081fd5b614fa1614296565b915088850151614fb0816147e7565b825284830151614fbf81613ba5565b828a015260608581015185811115614fd75760008081fd5b614fe58f8c838a0101614e9f565b85850152506080935083860151858111156150005760008081fd5b61500e8f8c838a0101614e9f565b82850152505061502060a08601614ced565b928201929092528188015285525050918301918301614f28565b509695505050505050565b6000610160828403121561505857600080fd5b6150606142b9565b9050815167ffffffffffffffff8082111561507a57600080fd5b61508685838601614e9f565b8352602084015191508082111561509c57600080fd5b6150a885838601614e9f565b60208401526150b960408501614ced565b604084015260608401519150808211156150d257600080fd5b6150de85838601614e9f565b60608401526150ef60808501614ca8565b608084015261510060a08501614ce2565b60a084015261511160c08501614ca8565b60c084015260e084015191508082111561512a57600080fd5b5061513784828501614ee4565b60e08301525061010061514c84828501614cf8565b9082015292915050565b8051611b3d8161453f565b600082601f83011261517257600080fd5b815160206151826143c183614331565b82815260a092830285018201928282019190878511156151a157600080fd5b8387015b85811015614b2e5781818a0312156151bd5760008081fd5b6151c5614296565b81516151d08161441b565b8152818601516151df81613ba5565b818701526040828101516151f2816147e7565b90820152606082810151615205816147e7565b9082015260808281015161521881613ba5565b9082015284529284019281016151a5565b600082601f83011261523a57600080fd5b8151602061524a6143c183614331565b82815260c0928302850182019282820191908785111561526957600080fd5b8387015b85811015614b2e5781818a0312156152855760008081fd5b61528d6142dd565b81516152988161441b565b8152818601516152a78161441b565b818701526040828101516152ba8161441b565b908201526060828101516152cd8161441b565b908201526080828101516152e0816147e7565b9082015260a0828101516152f381613ba5565b90820152845292840192810161526d565b600082601f83011261531557600080fd5b815160206153256143c183614331565b82815260c0928302850182019282820191908785111561534457600080fd5b8387015b85811015614b2e5781818a0312156153605760008081fd5b6153686142dd565b81516153738161441b565b8152818601516153828161441b565b818701526040828101516153958161441b565b908201526060828101516153a881613ba5565b908201526080828101516153bb816147e7565b9082015260a0828101516153ce81613ba5565b908201528452928401928101615348565b600061012082840312156153f257600080fd5b6153fa6142b9565b9050815167ffffffffffffffff8082111561541457600080fd5b61542085838601615045565b835261542e60208501615156565b602084015261543f60408501614ca8565b604084015261545060608501614ca8565b606084015261546160808501614ca8565b608084015260a084015191508082111561547a57600080fd5b61548685838601615161565b60a084015260c084015191508082111561549f57600080fd5b6154ab85838601615229565b60c084015260e08401519150808211156154c457600080fd5b6154d085838601615304565b60e0840152610100915081840151818111156154eb57600080fd5b6154f786828701614e9f565b8385015250505092915050565b6000806040838503121561551757600080fd5b61552083614949565b9150602083015167ffffffffffffffff8082111561553d57600080fd5b9084019060c0828703121561555157600080fd5b6155596142dd565b82518281111561556857600080fd5b615574888286016153df565b825250615583602084016148ec565b602082015261559460408401614ced565b60408201526155a5606084016148ec565b60608201526080830151828111156155bc57600080fd5b6155c888828601614e9f565b6080830152506155da60a08401614ced565b60a08201528093505050509250929050565b60006001600160a01b038086168352808516602084015250606060408301526146ef6060830184614693565b6000806040838503121561562b57600080fd5b61563483614949565b9150602083015190509250929050565b6000806000806080858703121561565a57600080fd5b61566385614949565b9350602085015167ffffffffffffffff8082111561568057600080fd5b61568c88838901615161565b945060408701519150808211156156a257600080fd5b6156ae88838901615229565b935060608701519150808211156156c457600080fd5b506156d187828801615304565b91505092959194509250565b600080604083850312156156f057600080fd5b6156f983614949565b9150602083015167ffffffffffffffff8082111561571657600080fd5b908401906040828703121561572a57600080fd5b60405160408101818110838211171561574557615745614234565b60405282518281111561575757600080fd5b615763888286016153df565b825250602083015192506157768361441b565b8260208201528093505050509250929050565b6000606082016001600160a01b0386168352602067ffffffffffffffff8616818501526060604085015281855180845260808601915060808160051b870101935082870160005b828110156157fe57607f198887030184526157ec868351613d53565b955092840192908401906001016157d0565b50939998505050505050505050565b60008060006060848603121561582257600080fd5b61582b84614949565b925060208085015161583c8161453f565b604086015190935067ffffffffffffffff81111561585957600080fd5b8501601f8101871361586a57600080fd5b80516158786143c182614331565b81815260059190911b8201830190838101908983111561589757600080fd5b928401925b8284101561440c5783516158af81613c8a565b8252928401929084019061589c565b60a0815260006158d160a0830188613e43565b86602084015285604084015282810360608401526158ef8186613f46565b905082810360808401526159038185613fc1565b98975050505050505050565b600081518084526020808501945080840160005b83811015613fb657815180516001600160a01b03908116895284820151168489015260409081015160070b9088015260609096019590820190600101615923565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015615a2b57898403603f19018652825180516001600160a01b0390811686528982015160608b880181905281519088018190526080880192918c01919086905b808210156159fd5783518051841686528e015160070b8e860152938c0193928d0192600191909101906159cf565b5050505090880151858203868a015290615a17818361590f565b978a0197955050509187019160010161598c565b50919998505050505050505050565b6020815260006111eb6020830184613e43565b60008060408385031215615a6057600080fd5b615a6983614949565b9150602083015167ffffffffffffffff811115615a8557600080fd5b615a91858286016153df565b915050925092905056fe90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aaa26469706673582212200e78f269d9e7b70c329341bf2e8cd11c83b1b8affe71ae06bf9922e36f1a7a9764736f6c63430008090033", + "bytecode": "0x60c06040526009608081905268746f6b656e4e616d6560b81b60a09081526200002c9160019190620000c7565b5060408051808201909152600b8082526a1d1bdad95b94de5b589bdb60aa1b60209092019182526200006191600291620000c7565b50604080518082019091526004808252636d656d6f60e01b60209092019182526200008f91600391620000c7565b50600480546001600160a81b031916700800000000000003e800000000000003e8179055348015620000c057600080fd5b50620001aa565b828054620000d5906200016d565b90600052602060002090601f016020900481019282620000f9576000855562000144565b82601f106200011457805160ff191683800117855562000144565b8280016001018555821562000144579182015b828111156200014457825182559160200191906001019062000127565b506200015292915062000156565b5090565b5b8082111562000152576000815560010162000157565b600181811c908216806200018257607f821691505b60208210811415620001a457634e487b7160e01b600052602260045260246000fd5b50919050565b615b9b80620001ba6000396000f3fe6080604052600436106102c65760003560e01c80638070905f11610179578063d85f74c1116100d6578063f2f38a741161008a578063f848fec411610064578063f848fec414610844578063f9e978bd14610864578063fdc8321e1461088457600080fd5b8063f2f38a74146107d6578063f4a01e5b14610804578063f7be34251461082457600080fd5b8063eee55ac8116100bb578063eee55ac814610776578063f25b120014610796578063f2c31ff4146107b657600080fd5b8063d85f74c114610743578063d92ac2481461075657600080fd5b8063a345f7bd1161012d578063af99c63311610112578063af99c633146106d5578063c0b19b6d146106f5578063d614cdb81461072357600080fd5b8063a345f7bd1461067b578063a3ad5b551461069b57600080fd5b80638ba74da01161015e5780638ba74da0146106285780638f8d7f991461063b5780639604ca651461065b57600080fd5b80638070905f146105d957806386f88d881461060857600080fd5b80634cbdb37b1161022757806369837dc2116101db5780636da6b1f0116101c05780636da6b1f0146105795780637c41ad2c146105995780637d3e5da8146105b957600080fd5b806369837dc21461052b5780636a4dde211461055957600080fd5b8063593d6e821161020c578063593d6e82146104a65780635a5e6c31146104c65780635b9076b7146104fb57600080fd5b80634cbdb37b1461045857806356af84031461048657600080fd5b80632eecbca31161027e5780633eed2c39116102635780633eed2c39146104035780634b5c6687146104235780634ba670351461043857600080fd5b80632eecbca3146103c35780633b3bff0f146103e357600080fd5b806319db44b6116102af57806319db44b6146103385780632b256ec8146103755780632d73bb2e146103a357600080fd5b80630fd2601e146102cb57806313c05dd814610303575b600080fd5b3480156102d757600080fd5b506102eb6102e6366004613c51565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561030f57600080fd5b5061032361031e366004613c8a565b610968565b604080519283529015156020830152016102fa565b34801561034457600080fd5b50610358610353366004613cd5565b6109e6565b604080519283526001600160a01b039091166020830152016102fa565b34801561038157600080fd5b50610395610390366004613d01565b610a6a565b6040519081526020016102fa565b3480156103af57600080fd5b506103956103be366004613c51565b610b56565b3480156103cf57600080fd5b506102eb6103de366004613c51565b610b9b565b3480156103ef57600080fd5b506103956103fe366004613d01565b610bd2565b34801561040f57600080fd5b5061032361041e366004613d01565b610cac565b610436610431366004613d01565b610d26565b005b34801561044457600080fd5b50610395610453366004613d2d565b611114565b34801561046457600080fd5b50610478610473366004613d89565b611160565b6040516102fa9291906142ac565b34801561049257600080fd5b506103956104a13660046143e6565b6111d6565b3480156104b257600080fd5b506103956104c13660046144be565b611220565b3480156104d257600080fd5b506104e66104e1366004613c8a565b6112fd565b604080519283526020830191909152016102fa565b34801561050757600080fd5b5061051b610516366004613d01565b61136e565b6040516102fa949392919061453b565b34801561053757600080fd5b5061054b610546366004613d01565b611400565b6040516102fa9291906145b7565b34801561056557600080fd5b50610323610574366004613c51565b611475565b34801561058557600080fd5b50610395610594366004613d2d565b6114ec565b3480156105a557600080fd5b506103956105b4366004613d01565b6114fa565b3480156105c557600080fd5b506103956105d4366004613c51565b611528565b3480156105e557600080fd5b506105f96105f436600461460e565b611534565b6040516102fa93929190614757565b34801561061457600080fd5b50610323610623366004613d01565b6115bc565b610436610636366004613c51565b61162d565b34801561064757600080fd5b506102eb610656366004613c51565b611aef565b34801561066757600080fd5b50610395610676366004614789565b611b25565b34801561068757600080fd5b50610395610696366004613d01565b611b5a565b3480156106a757600080fd5b506106bb6106b6366004613c51565b611ba0565b6040805160079390930b83529015156020830152016102fa565b3480156106e157600080fd5b506102eb6106f0366004613c51565b611c92565b34801561070157600080fd5b50610715610710366004613d01565b611cc8565b6040516102fa9291906147fe565b34801561072f57600080fd5b5061071561073e366004613d01565b611dbf565b610436610751366004613d01565b611ec9565b34801561076257600080fd5b50610395610771366004614838565b61226e565b34801561078257600080fd5b506103956107913660046144be565b61227b565b3480156107a257600080fd5b506103956107b1366004614886565b61230e565b3480156107c257600080fd5b506106bb6107d1366004613c51565b61231b565b3480156107e257600080fd5b506107f66107f1366004613d01565b6123f6565b6040516102fa9291906148c6565b34801561081057600080fd5b5061039561081f366004613c51565b61246b565b34801561083057600080fd5b5061039561083f366004613d01565b612477565b34801561085057600080fd5b5061039561085f3660046148df565b61255a565b34801561087057600080fd5b5061043661087f366004614920565b612567565b34801561089057600080fd5b5061039561089f36600461493d565b6125dd565b604051638f8d7f9960e01b81526001600160a01b038084166004830152821660248201526000903090638f8d7f99906044015b602060405180830381600087803b1580156108f157600080fd5b505af1158015610905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109299190614988565b604051600782900b8152909150600080516020615b468339815191529060200160405180910390a1600781900b60161461096257600080fd5b92915050565b6000806109768585856127b4565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146109a957600080fd5b60405181151581527e1c2e72360171244b3bb8cc8ddd767820edf37138ad6f129fb3574b407c307d906020015b60405180910390a1935093915050565b6000806109f384846128b3565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214610a2657600080fd5b6040516001600160a01b03821681527fc2c78c7c31baf14949e75c51df12be56edb9af523cf82839c2869bbcf13b3ecb906020015b60405180910390a19250929050565b604051631f106b4b60e21b81526001600160a01b03821660048201526000903090637c41ad2c90602401602060405180830381600087803b158015610aae57600080fd5b505af1158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae691906149a5565b9050600080516020615b4683398151915281604051610b0791815260200190565b60405180910390a160168114610b1c57600080fd5b604051600181527f0c9c765845f4d139956bb8fc8decb2eec6093c9c608b809641b16054b29f0e13906020015b60405180910390a1919050565b6000610b628383612993565b60070b9050600080516020615b4683398151915281604051610b8691815260200190565b60405180910390a16016811461096257600080fd5b60405163af99c63360e01b81526001600160a01b03808416600483015282166024820152600090309063af99c633906044016108d7565b6040516001600160a01b03821660248201526000908190819061016790633b3bff0f60e01b906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610c3a91906149be565b6000604051808303816000865af19150503d8060008114610c77576040519150601f19603f3d011682016040523d82523d6000602084013e610c7c565b606091505b509150915081610c8d576015610ca1565b80806020019051810190610ca191906149ec565b60030b949350505050565b600080610cb8836129e2565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214610ceb57600080fd5b60405181151581527f6b7f3306751292f85ab4161ee2b0ac16dfc8ded13e6446ce6bd859d0a2f4c78e906020015b60405180910390a1915091565b60408051600480825260a08201909252600091816020015b610d46613ac3565b815260200190600190039081610d3e579050509050610d7960006006600160405180602001604052806000815250612adf565b81600081518110610d8c57610d8c614a07565b6020026020010181905250610db260018060405180602001604052806000815250612b16565b81600181518110610dc557610dc5614a07565b6020026020010181905250610dec6002600160405180602001604052806000815250612b16565b81600281518110610dff57610dff614a07565b6020026020010181905250610e266003600160405180602001604052806000815250612b16565b81600381518110610e3957610e39614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff168152509050600060405180610120016040528060018054610e9790614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec390614a1d565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050815260200160028054610f2790614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5390614a1d565b8015610fa05780601f10610f7557610100808354040283529160200191610fa0565b820191906000526020600020905b815481529060010190602001808311610f8357829003601f168201915b50505050508152602001856001600160a01b0316815260200160038054610fc690614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff290614a1d565b801561103f5780601f106110145761010080835404028352916020019161103f565b820191906000526020600020905b81548152906001019060200180831161102257829003601f168201915b50505091835250506001602082015260045468010000000000000000810460070b6040830152600160a01b810460ff16151560608301526080820186905260a090910184905290915060009081906110be90849067ffffffffffffffff811690700100000000000000000000000000000000900463ffffffff16612b4b565b9092509050601682146110d057600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b600061112285858585612c79565b9050600080516020615b468339815191528160405161114391815260200190565b60405180910390a16016811461115857600080fd5b949350505050565b600061116a613b20565b6111748484612d89565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146111a757600080fd5b7fd010ef68d3ac3e07c14bed496400730a484fd17c48a4d373cbc4722a56540def81604051610a5b9190614a58565b60006111e3848484612e7c565b9050600080516020615b468339815191528160405161120491815260200190565b60405180910390a16016811461121957600080fd5b9392505050565b60008060006101676001600160a01b031663593d6e8260e01b868660405160240161124c929190614a6b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161128a91906149be565b6000604051808303816000865af19150503d80600081146112c7576040519150601f19603f3d011682016040523d82523d6000602084013e6112cc565b606091505b5091509150816112dd5760156112f1565b808060200190518101906112f191906149ec565b60030b95945050505050565b60008061130b858585612f5c565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461133e57600080fd5b6040518181527f25b6684a7e8fe1b676e9c39c8dd65034fbafea906d3bdfd97bf748b7b55e14c8906020016109d6565b6000606080606061137e85613048565b604051600785900b815293975091955093509150600080516020615b468339815191529060200160405180910390a1600784900b6016146113be57600080fd5b7f2efc8334b040613a552197fe34283d6ca2909c8ffae393e128424931f20c69b38383836040516113f193929190614aae565b60405180910390a19193509193565b600061140a613b5b565b61141383613148565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461144657600080fd5b7fea9419ffbaa766adf982c4c9864330eee1d848eff36c79e510e7e589c8bb265f81604051610d199190614ae7565b6000806114828484613231565b60405160079290920b80835293509150600080516020615b468339815191529060200160405180910390a1601682146114ba57600080fd5b60405181151581527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e90602001610a5b565b600061112285858585613282565b6040516001600160a01b03821660248201526000908190819061016790631f106b4b60e21b90604401610bfc565b6000610b6283836132e3565b6000806060611544868686613332565b6040518381529295509093509150600080516020615b468339815191529060200160405180910390a16016831461157a57600080fd5b7feff23992f47b3c101679f8b4dc9d3e242c903909dba4a453f2b2341ad463b0e282826040516115ab929190614afa565b60405180910390a193509350939050565b6000806115c883613430565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146115fb57600080fd5b60405181151581527f9ee19e13dfa1ba8db2502e15ff56dbecdeb0e0473323fb195473ce648030a2cd90602001610d19565b604080516001808252818301909252600091816020015b61164c613ac3565b81526020019060019003908161164457905050905061167e600080600160405180602001604052806000815250612adf565b8160008151811061169157611691614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546116ef90614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461171b90614a1d565b80156117685780601f1061173d57610100808354040283529160200191611768565b820191906000526020600020905b81548152906001019060200180831161174b57829003601f168201915b505050505081526020016002805461177f90614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546117ab90614a1d565b80156117f85780601f106117cd576101008083540402835291602001916117f8565b820191906000526020600020905b8154815290600101906020018083116117db57829003601f168201915b50505050508152602001866001600160a01b031681526020016003805461181e90614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461184a90614a1d565b80156118975780601f1061186c57610100808354040283529160200191611897565b820191906000526020600020905b81548152906001019060200180831161187a57829003601f168201915b505050918352505060016020820181905260045468010000000000000000900460070b6040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816118f15750506040805160a081018252600181526001600160a01b0388811660208301526000928201839052606082018390528916608082015282519293509183919061197457611974614a07565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282526000199092019101816119965750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a083015282519293509091839190611a2a57611a2a614a07565b60209081029190910101526004546000908190611a7090869067ffffffffffffffff811690700100000000000000000000000000000000900463ffffffff168787613479565b91509150600080516020615b4683398151915282604051611a9391815260200190565b60405180910390a160168214611aa857600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b038381166024830152821660448201526000908190819061016790638f8d7f9960e01b9060640161124c565b6000611b39611b348385614bcc565b6135ad565b9050600080516020615b4683398151915281604051610b8691815260200190565b6000611b65826135d7565b9050600080516020615b4683398151915281604051611b8691815260200190565b60405180910390a160168114611b9b57600080fd5b919050565b604051633cb0c7fd60e21b81526001600160a01b038084166004830152821660248201526000908190309063f2c31ff4906044016040805180830381600087803b158015611bed57600080fd5b505af1158015611c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c259190614d44565b604051600783900b81529193509150600080516020615b468339815191529060200160405180910390a1600782900b601614611c6057600080fd5b60405181151581527fd24dda6928587354b65aa1a18c2eaf249bef7e5bafd2a71fac71d286f76f957f90602001610a5b565b6040516001600160a01b03838116602483015282166044820152600090819081906101679063af99c63360e01b9060640161124c565b60408051606081018252600080825260208201819052918101829052604051631ac299b760e31b81526001600160a01b0384166004820152309063d614cdb890602401608060405180830381600087803b158015611d2557600080fd5b505af1158015611d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5d9190614dd3565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214611d9057600080fd5b7fa0a16bf9db2c17796faeca5af5aaeef8523f9d4c350c512cb00062ad89604f8881604051610d199190614e00565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b0316631ac299b760e31b179052925190928391829161016791611e3191906149be565b6000604051808303816000865af19150503d8060008114611e6e576040519150601f19603f3d011682016040523d82523d6000602084013e611e73565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082611ea357601581611eb7565b81806020019051810190611eb79190614e34565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b611ee9613ac3565b815260200190600190039081611ee1579050509050611f1c60006006600160405180602001604052806000815250612adf565b81600081518110611f2f57611f2f614a07565b6020026020010181905250611f5560018060405180602001604052806000815250612b16565b81600181518110611f6857611f68614a07565b6020026020010181905250611f8f6002600160405180602001604052806000815250612b16565b81600281518110611fa257611fa2614a07565b6020026020010181905250611fc96004600160405180602001604052806000815250612b16565b81600381518110611fdc57611fdc614a07565b60200260200101819052506120036003600160405180602001604052806000815250612b16565b8160048151811061201657612016614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff16815250905060006040518061012001604052806001805461207490614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546120a090614a1d565b80156120ed5780601f106120c2576101008083540402835291602001916120ed565b820191906000526020600020905b8154815290600101906020018083116120d057829003601f168201915b505050505081526020016002805461210490614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461213090614a1d565b801561217d5780601f106121525761010080835404028352916020019161217d565b820191906000526020600020905b81548152906001019060200180831161216057829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546121a390614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546121cf90614a1d565b801561221c5780601f106121f15761010080835404028352916020019161221c565b820191906000526020600020905b8154815290600101906020018083116121ff57829003601f168201915b50505091835250506001602082015260045468010000000000000000810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290506000806110be8361361e565b60006111e3848484613708565b6040517f593d6e82000000000000000000000000000000000000000000000000000000008152600090309063593d6e82906122bc9086908690600401614a6b565b602060405180830381600087803b1580156122d657600080fd5b505af11580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3991906149a5565b60006111e3848484613763565b6040516001600160a01b0383811660248301528216604482015260009081908190819061016790633cb0c7fd60e21b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161238d91906149be565b6000604051808303816000865af19150503d80600081146123ca576040519150601f19603f3d011682016040523d82523d6000602084013e6123cf565b606091505b5091509150816123e25760156000611eb7565b80806020019051810190611eb79190614e5f565b6000612400613b7b565b612409836137ba565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461243c57600080fd5b7fbdb65f8c2a2e9a3a37ea49e903836883766a922e4ce9b21f684035e304962d4181604051610d199190614e8b565b6000611b3983836138a3565b604051633b3bff0f60e01b81526001600160a01b03821660048201526000903090633b3bff0f90602401602060405180830381600087803b1580156124bb57600080fd5b505af11580156124cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f391906149a5565b9050600080516020615b468339815191528160405161251491815260200190565b60405180910390a16016811461252957600080fd5b604051600181527f319ab7084208e4afa38c6e6ff7aea9587439f2e4700746f4c7d425fea17426d290602001610b49565b60006111e38484846138f2565b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b8315158102919091179182905560405160ff9190920416151581527f457c3a16a0ebdc38e3675609957ca3fcc4490e220bd15d85d34f58e2e145cb089060200160405180910390a150565b60408051600080825260208201909252819081612622565b60408051606081018252600080825260208083018290529282015282526000199092019101816125f55790505b50905060006040518060400160405280336001600160a01b031681526020018561264b90614e9e565b600790810b9091526040805180820182526001600160a01b038a1681529187900b602083015280516002808252606082019092529293509091600091816020015b604080518082019091526000808252602082015281526020019060019003908161268c57905050905082816000815181106126c9576126c9614a07565b602002602001018190525081816001815181106126e8576126e8614a07565b602090810291909101810191909152604080516060810182526001600160a01b038a16815291820183905281810186905280516001808252818301909252600091816020015b61275b604051806060016040528060006001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161272e579050509050818160008151811061278457612784614a07565b6020026020010181905250612798816135ad565b9650601687146127a757600080fd5b5050505050509392505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167ff49f40db00000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612837916149be565b6000604051808303816000865af19150503d8060008114612874576040519150601f19603f3d011682016040523d82523d6000602084013e612879565b606091505b50915091508161288c57601560006128a0565b808060200190518101906128a09190614e5f565b60039190910b9890975095505050505050565b604080516001600160a01b0384166024820152604480820184905282518083039091018152606490910182526020810180516001600160e01b03167f098f23660000000000000000000000000000000000000000000000000000000017905290516000918291829182916101679161292a916149be565b6000604051808303816000865af19150503d8060008114612967576040519150601f19603f3d011682016040523d82523d6000602084013e61296c565b606091505b50915091508161297f5760156000611eb7565b80806020019051810190611eb79190614ed4565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f52f91387000000000000000000000000000000000000000000000000000000009060640161124c565b6040516001600160a01b0382166024820152600090819081908190610167907fa7daa18d00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612a6591906149be565b6000604051808303816000865af19150503d8060008114612aa2576040519150601f19603f3d011682016040523d82523d6000602084013e612aa7565b606091505b509150915081612aba5760156000612ace565b80806020019051810190612ace9190614e5f565b60039190910b969095509350505050565b612ae7613ac3565b6040518060400160405280612afc8787613948565b8152602001612b0b8585613961565b905295945050505050565b612b1e613ac3565b6040518060400160405280612b3286613a31565b8152602001612b418585613961565b9052949350505050565b600080848061010001516000015163ffffffff166000148015612b7b57506101008101516040015163ffffffff16155b15612b91576101008101516276a7006040909101525b6000806101676001600160a01b03163463c23baeb660e01b8a8a8a604051602401612bbe93929190614f00565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612bfc91906149be565b60006040518083038185875af1925050503d8060008114612c39576040519150601f19603f3d011682016040523d82523d6000602084013e612c3e565b606091505b509150915081612c515760156000612c65565b80806020019051810190612c659190614ed4565b60039190910b999098509650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907feca36917000000000000000000000000000000000000000000000000000000009060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612d1491906149be565b6000604051808303816000865af19150503d8060008114612d51576040519150601f19603f3d011682016040523d82523d6000602084013e612d56565b606091505b509150915081612d67576015612d7b565b80806020019051810190612d7b91906149ec565b60030b979650505050505050565b6000612d93613b20565b604080516001600160a01b0386166024820152600785900b60448083019190915282518083039091018152606490910182526020810180516001600160e01b03167f287e1da8000000000000000000000000000000000000000000000000000000001790529051600091829161016791612e0c916149be565b6000604051808303816000865af19150503d8060008114612e49576040519150601f19603f3d011682016040523d82523d6000602084013e612e4e565b606091505b5091509150612e5b613b20565b82612e68576015816128a0565b818060200190518101906128a0919061559e565b60008060006101676001600160a01b031663f7f38e2660e01b878787604051602401612eaa93929190615686565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612ee891906149be565b6000604051808303816000865af19150503d8060008114612f25576040519150601f19603f3d011682016040523d82523d6000602084013e612f2a565b606091505b509150915081612f3b576015612f4f565b80806020019051810190612f4f91906149ec565b60030b9695505050505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167f927da10500000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612fdf916149be565b6000604051808303816000865af19150503d806000811461301c576040519150601f19603f3d011682016040523d82523d6000602084013e613021565b606091505b50915091508161303457601560006128a0565b808060200190518101906128a091906156b2565b604080516001600160a01b03831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167fae7611a00000000000000000000000000000000000000000000000000000000017905290516000916060918291829185918291610167916130c0916149be565b6000604051808303816000865af19150503d80600081146130fd576040519150601f19603f3d011682016040523d82523d6000602084013e613102565b606091505b509150915060608060608461311b57601583838361312f565b8380602001905181019061312f91906156de565b60039390930b9d919c509a509098509650505050505050565b6000613152613b5b565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f3f28a19b0000000000000000000000000000000000000000000000000000000017905290516000918291610167916131c1916149be565b6000604051808303816000865af19150503d80600081146131fe576040519150601f19603f3d011682016040523d82523d6000602084013e613203565b606091505b5091509150613210613b5b565b8261321d57601581611eb7565b81806020019051810190611eb79190615777565b6040516001600160a01b03838116602483015282166044820152600090819081908190610167907f46de0fb1000000000000000000000000000000000000000000000000000000009060640161234f565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907f5cfc9011000000000000000000000000000000000000000000000000000000009060a401612cd6565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f5b8f8584000000000000000000000000000000000000000000000000000000009060640161124c565b60008060606000806101676001600160a01b031663278e0b8860e01b89898960405160240161336393929190615823565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516133a191906149be565b6000604051808303816000865af19150503d80600081146133de576040519150601f19603f3d011682016040523d82523d6000602084013e6133e3565b606091505b50915091508161340657604080516000808252602082019092526015919061341a565b8080602001905181019061341a91906158a7565b60039290920b9a90995090975095505050505050565b6040516001600160a01b0382166024820152600090819081908190610167907f335e04c10000000000000000000000000000000000000000000000000000000090604401612a27565b600080868061010001516000015163ffffffff1660001480156134a957506101008101516040015163ffffffff16155b156134bf576101008101516276a7006040909101525b6000806101676001600160a01b03163463b937581a60e01b8c8c8c8c8c6040516024016134f0959493929190615958565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161352e91906149be565b60006040518083038185875af1925050503d806000811461356b576040519150601f19603f3d011682016040523d82523d6000602084013e613570565b606091505b5091509150816135835760156000613597565b808060200190518101906135979190614ed4565b60039190910b9b909a5098505050505050505050565b60008060006101676001600160a01b031663189a554c60e01b85604051602401610bfc9190615a0e565b6040516001600160a01b038216602482015260009081908190610167907ff069f7120000000000000000000000000000000000000000000000000000000090604401610bfc565b600080828061010001516000015163ffffffff16600014801561364e57506101008101516040015163ffffffff16155b15613664576101008101516276a7006040909101525b6000806101676001600160a01b031634639c89bb3560e01b8860405160240161368d9190615ae4565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516136cb91906149be565b60006040518083038185875af1925050503d8060008114612967576040519150601f19603f3d011682016040523d82523d6000602084013e61296c565b6040516001600160a01b0384811660248301528316604482015263ffffffff8216606482015260009081908190610167907f9790686d0000000000000000000000000000000000000000000000000000000090608401612eaa565b6040516001600160a01b03848116602483015283166044820152811515606482015260009081908190610167907f367605ca0000000000000000000000000000000000000000000000000000000090608401612eaa565b60006137c4613b7b565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f1f69565f000000000000000000000000000000000000000000000000000000001790529051600091829161016791613833916149be565b6000604051808303816000865af19150503d8060008114613870576040519150601f19603f3d011682016040523d82523d6000602084013e613875565b606091505b5091509150613882613b7b565b8261388f57601581611eb7565b81806020019051810190611eb79190615af7565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde000000000000000000000000000000000000000000000000000000009060640161124c565b6040516001600160a01b038481166024830152831660448201526064810182905260009081908190610167907fe1f21c670000000000000000000000000000000000000000000000000000000090608401612eaa565b6000600160ff84161b9050600160ff83161b8117611219565b6139a76040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156139bc5760018152610962565b8260ff16600214156139de576000546001600160a01b03166020820152610962565b8260ff16600314156139f65760408101829052610962565b8260ff1660041415613a0e5760608101829052610962565b8260ff1660051415610962576000546001600160a01b0316608082015292915050565b600060ff8216613a4357506001919050565b8160ff1660011415613a5757506002919050565b8160ff1660021415613a6b57506004919050565b8160ff1660031415613a7f57506008919050565b8160ff1660041415613a9357506010919050565b8160ff1660051415613aa757506020919050565b8160ff1660061415613abb57506040919050565b506000919050565b604051806040016040528060008152602001613b1b6040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6040518060c00160405280613b33613b7b565b8152600060208201819052604082018190526060808301829052608083015260a09091015290565b6040518060400160405280613b6e613b7b565b8152600060209091015290565b60408051610240810182526060610120820181815261014083018290526000610160840181905261018084018390526101a084018190526101c084018190526101e0840181905261020084018390528451928301855280835260208301819052938201939093526102208201529081908152602001600067ffffffffffffffff168152602001600015158152602001600015158152602001600015158152602001606081526020016060815260200160608152602001606081525090565b6001600160a01b0381168114613c4e57600080fd5b50565b60008060408385031215613c6457600080fd5b8235613c6f81613c39565b91506020830135613c7f81613c39565b809150509250929050565b600080600060608486031215613c9f57600080fd5b8335613caa81613c39565b92506020840135613cba81613c39565b91506040840135613cca81613c39565b809150509250925092565b60008060408385031215613ce857600080fd5b8235613cf381613c39565b946020939093013593505050565b600060208284031215613d1357600080fd5b813561121981613c39565b8060070b8114613c4e57600080fd5b60008060008060808587031215613d4357600080fd5b8435613d4e81613c39565b93506020850135613d5e81613c39565b92506040850135613d6e81613c39565b91506060850135613d7e81613d1e565b939692955090935050565b60008060408385031215613d9c57600080fd5b8235613da781613c39565b91506020830135613c7f81613d1e565b60005b83811015613dd2578181015183820152602001613dba565b83811115613de1576000848401525b50505050565b60008151808452613dff816020860160208601613db7565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015613eca5782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152613e8c60e08b0186613de7565b928601518a8403603f1901858c0152929450613ea88584613de7565b9501511660c09890980197909752505098850198935090840190600101613e31565b5091979650505050505050565b60006101608251818552613eed82860182613de7565b91505060208301518482036020860152613f078282613de7565b9150506040830151613f2460408601826001600160a01b03169052565b5060608301518482036060860152613f3c8282613de7565b9150506080830151613f52608086018215159052565b5060a0830151613f6760a086018260070b9052565b5060c0830151613f7b60c086018215159052565b5060e083015184820360e0860152613f938282613e13565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff168852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613feb565b509495945050505050565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101614066565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff9081168952848201518116858a0152604080830151909116908901526060808201516001600160a01b03908116918a01919091526080808301511515908a015260a091820151169088015260c090960195908201906001016140e4565b6000610120825181855261416882860182613ed7565b9150506020830151614186602086018267ffffffffffffffff169052565b50604083015161419a604086018215159052565b5060608301516141ae606086018215159052565b5060808301516141c2608086018215159052565b5060a083015184820360a08601526141da8282613fd7565b91505060c083015184820360c08601526141f48282614052565b91505060e083015184820360e086015261420e82826140d0565b91505061010080840151858303828701526142298382613de7565b9695505050505050565b6000815160c0845261424860c0850182614152565b9050602083015160070b602085015260408301516001600160a01b038082166040870152606085015160070b60608701526080850151915085830360808701526142928383613de7565b92508060a08601511660a087015250508091505092915050565b8281526040602082015260006111586040830184614233565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405290565b6040805190810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405160a0810167ffffffffffffffff811182821017156142fe576142fe6142c5565b604051610120810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405160c0810167ffffffffffffffff811182821017156142fe576142fe6142c5565b604051601f8201601f1916810167ffffffffffffffff811182821017156143ba576143ba6142c5565b604052919050565b600067ffffffffffffffff8211156143dc576143dc6142c5565b5060051b60200190565b6000806000606084860312156143fb57600080fd5b833561440681613c39565b925060208481013561441781613c39565b9250604085013567ffffffffffffffff81111561443357600080fd5b8501601f8101871361444457600080fd5b8035614457614452826143c2565b614391565b81815260059190911b8201830190838101908983111561447657600080fd5b928401925b8284101561449d57833561448e81613d1e565b8252928401929084019061447b565b80955050505050509250925092565b63ffffffff81168114613c4e57600080fd5b60008082840360808112156144d257600080fd5b83356144dd81613c39565b92506060601f19820112156144f157600080fd5b506144fa6142db565b6020840135614508816144ac565b8152604084013561451881613c39565b6020820152606084013561452b816144ac565b6040820152919491935090915050565b8460070b81526080602082015260006145576080830186613fd7565b82810360408401526145698186614052565b9050828103606084015261457d81856140d0565b979650505050505050565b600081516040845261459d6040850182614152565b60209384015163ffffffff16949093019390935250919050565b8281526040602082015260006111586040830184614588565b67ffffffffffffffff81168114613c4e57600080fd5b600067ffffffffffffffff821115614600576146006142c5565b50601f01601f191660200190565b60008060006060848603121561462357600080fd5b833561462e81613c39565b925060208481013561463f816145d0565b925060408581013567ffffffffffffffff8082111561465d57600080fd5b818801915088601f83011261467157600080fd5b813561467f614452826143c2565b81815260059190911b8301850190858101908b83111561469e57600080fd5b8685015b83811015614712578035858111156146ba5760008081fd5b8601603f81018e136146cc5760008081fd5b888101356146dc614452826145e6565b8181528f8a8385010111156146f15760008081fd5b818a84018c83013760009181018b01919091528452509187019187016146a2565b50809750505050505050509250925092565b600081518084526020808501945080840160005b8381101561404757815160070b87529582019590820190600101614738565b83815267ffffffffffffffff831660208201526060604082015260006147806060830184614724565b95945050505050565b6000806020838503121561479c57600080fd5b823567ffffffffffffffff808211156147b457600080fd5b818501915085601f8301126147c857600080fd5b8135818111156147d757600080fd5b8660208260051b85010111156147ec57600080fd5b60209290920196919550909350505050565b828152608081016112196020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060006060848603121561484d57600080fd5b833561485881613c39565b9250602084013561486881613c39565b91506040840135613cca816144ac565b8015158114613c4e57600080fd5b60008060006060848603121561489b57600080fd5b83356148a681613c39565b925060208401356148b681613c39565b91506040840135613cca81614878565b8281526040602082015260006111586040830184614152565b6000806000606084860312156148f457600080fd5b83356148ff81613c39565b9250602084013561490f81613c39565b929592945050506040919091013590565b60006020828403121561493257600080fd5b813561121981614878565b60008060006060848603121561495257600080fd5b833561495d81613c39565b9250602084013561496d81613c39565b91506040840135613cca81613d1e565b8051611b9b81613d1e565b60006020828403121561499a57600080fd5b815161121981613d1e565b6000602082840312156149b757600080fd5b5051919050565b600082516149d0818460208701613db7565b9190910192915050565b8051600381900b8114611b9b57600080fd5b6000602082840312156149fe57600080fd5b611219826149da565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614a3157607f821691505b60208210811415614a5257634e487b7160e01b600052602260045260246000fd5b50919050565b6020815260006112196020830184614233565b6001600160a01b0383168152608081016112196020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b606081526000614ac16060830186613fd7565b8281036020840152614ad38186614052565b9050828103604084015261422981856140d0565b6020815260006112196020830184614588565b67ffffffffffffffff831681526040602082015260006111586040830184614724565b600082601f830112614b2e57600080fd5b81356020614b3e614452836143c2565b82815260609283028501820192828201919087851115614b5d57600080fd5b8387015b85811015614bbf5781818a031215614b795760008081fd5b614b816142db565b8135614b8c81613c39565b815281860135614b9b81613c39565b81870152604082810135614bae81613d1e565b908201528452928401928101614b61565b5090979650505050505050565b6000614bda614452846143c2565b80848252602080830192508560051b850136811115614bf857600080fd5b855b81811015614d2d57803567ffffffffffffffff80821115614c1b5760008081fd5b818901915060608236031215614c315760008081fd5b614c396142db565b8235614c4481613c39565b81528286013582811115614c585760008081fd5b830136601f820112614c6a5760008081fd5b8035614c78614452826143c2565b81815260069190911b82018801908881019036831115614c985760008081fd5b928901925b82841015614cee5760408436031215614cb65760008081fd5b614cbe614304565b8435614cc981613c39565b8152848b0135614cd881613d1e565b818c015282526040939093019290890190614c9d565b848a01525060409150508381013583811115614d0a5760008081fd5b614d1636828701614b1d565b918301919091525087525050938201938201614bfa565b50919695505050505050565b8051611b9b81614878565b60008060408385031215614d5757600080fd5b8251614d6281613d1e565b6020840151909250613c7f81614878565b8051611b9b81613c39565b600060608284031215614d9057600080fd5b614d986142db565b90508151614da5816144ac565b81526020820151614db581613c39565b60208201526040820151614dc8816144ac565b604082015292915050565b60008060808385031215614de657600080fd5b82519150614df78460208501614d7e565b90509250929050565b606081016109628284805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060808385031215614e4757600080fd5b614e50836149da565b9150614df78460208501614d7e565b60008060408385031215614e7257600080fd5b614e7b836149da565b91506020830151613c7f81614878565b6020815260006112196020830184614152565b60008160070b677fffffffffffffff19811415614ecb57634e487b7160e01b600052601160045260246000fd5b60000392915050565b60008060408385031215614ee757600080fd5b614ef0836149da565b91506020830151613c7f81613c39565b606081526000614f136060830186613ed7565b905067ffffffffffffffff8416602083015263ffffffff83166040830152949350505050565b600082601f830112614f4a57600080fd5b8151614f58614452826145e6565b818152846020838601011115614f6d57600080fd5b611158826020830160208701613db7565b600082601f830112614f8f57600080fd5b81516020614f9f614452836143c2565b82815260059290921b84018101918181019086841115614fbe57600080fd5b8286015b848110156150d457805167ffffffffffffffff80821115614fe257600080fd5b908801906040601f19838c038101821315614ffc57600080fd5b615004614304565b888501518152828501518481111561501b57600080fd5b949094019360a0858e03830112156150335760008081fd5b61503b614327565b91508885015161504a81614878565b82528483015161505981613c39565b828a0152606085810151858111156150715760008081fd5b61507f8f8c838a0101614f39565b858501525060809350838601518581111561509a5760008081fd5b6150a88f8c838a0101614f39565b8285015250506150ba60a08601614d73565b928201929092528188015285525050918301918301614fc2565b509695505050505050565b600061016082840312156150f257600080fd5b6150fa61434a565b9050815167ffffffffffffffff8082111561511457600080fd5b61512085838601614f39565b8352602084015191508082111561513657600080fd5b61514285838601614f39565b602084015261515360408501614d73565b6040840152606084015191508082111561516c57600080fd5b61517885838601614f39565b606084015261518960808501614d39565b608084015261519a60a0850161497d565b60a08401526151ab60c08501614d39565b60c084015260e08401519150808211156151c457600080fd5b506151d184828501614f7e565b60e0830152506101006151e684828501614d7e565b9082015292915050565b8051611b9b816145d0565b600082601f83011261520c57600080fd5b8151602061521c614452836143c2565b82815260a0928302850182019282820191908785111561523b57600080fd5b8387015b85811015614bbf5781818a0312156152575760008081fd5b61525f614327565b815161526a816144ac565b81528186015161527981613c39565b8187015260408281015161528c81614878565b9082015260608281015161529f81614878565b908201526080828101516152b281613c39565b90820152845292840192810161523f565b600082601f8301126152d457600080fd5b815160206152e4614452836143c2565b82815260c0928302850182019282820191908785111561530357600080fd5b8387015b85811015614bbf5781818a03121561531f5760008081fd5b61532761436e565b8151615332816144ac565b815281860151615341816144ac565b81870152604082810151615354816144ac565b90820152606082810151615367816144ac565b9082015260808281015161537a81614878565b9082015260a08281015161538d81613c39565b908201528452928401928101615307565b600082601f8301126153af57600080fd5b815160206153bf614452836143c2565b82815260c092830285018201928282019190878511156153de57600080fd5b8387015b85811015614bbf5781818a0312156153fa5760008081fd5b61540261436e565b815161540d816144ac565b81528186015161541c816144ac565b8187015260408281015161542f816144ac565b9082015260608281015161544281613c39565b9082015260808281015161545581614878565b9082015260a08281015161546881613c39565b9082015284529284019281016153e2565b6000610120828403121561548c57600080fd5b61549461434a565b9050815167ffffffffffffffff808211156154ae57600080fd5b6154ba858386016150df565b83526154c8602085016151f0565b60208401526154d960408501614d39565b60408401526154ea60608501614d39565b60608401526154fb60808501614d39565b608084015260a084015191508082111561551457600080fd5b615520858386016151fb565b60a084015260c084015191508082111561553957600080fd5b615545858386016152c3565b60c084015260e084015191508082111561555e57600080fd5b61556a8583860161539e565b60e08401526101009150818401518181111561558557600080fd5b61559186828701614f39565b8385015250505092915050565b600080604083850312156155b157600080fd5b6155ba836149da565b9150602083015167ffffffffffffffff808211156155d757600080fd5b9084019060c082870312156155eb57600080fd5b6155f361436e565b82518281111561560257600080fd5b61560e88828601615479565b82525061561d6020840161497d565b602082015261562e60408401614d73565b604082015261563f6060840161497d565b606082015260808301518281111561565657600080fd5b61566288828601614f39565b60808301525061567460a08401614d73565b60a08201528093505050509250929050565b60006001600160a01b038086168352808516602084015250606060408301526147806060830184614724565b600080604083850312156156c557600080fd5b6156ce836149da565b9150602083015190509250929050565b600080600080608085870312156156f457600080fd5b6156fd856149da565b9350602085015167ffffffffffffffff8082111561571a57600080fd5b615726888389016151fb565b9450604087015191508082111561573c57600080fd5b615748888389016152c3565b9350606087015191508082111561575e57600080fd5b5061576b8782880161539e565b91505092959194509250565b6000806040838503121561578a57600080fd5b615793836149da565b9150602083015167ffffffffffffffff808211156157b057600080fd5b90840190604082870312156157c457600080fd5b6040516040810181811083821117156157df576157df6142c5565b6040528251828111156157f157600080fd5b6157fd88828601615479565b82525060208301519250615810836144ac565b8260208201528093505050509250929050565b6000606082016001600160a01b0386168352602067ffffffffffffffff8616818501526060604085015281855180845260808601915060808160051b870101935082870160005b8281101561589857607f19888703018452615886868351613de7565b9550928401929084019060010161586a565b50939998505050505050505050565b6000806000606084860312156158bc57600080fd5b6158c5846149da565b92506020808501516158d6816145d0565b604086015190935067ffffffffffffffff8111156158f357600080fd5b8501601f8101871361590457600080fd5b8051615912614452826143c2565b81815260059190911b8201830190838101908983111561593157600080fd5b928401925b8284101561449d57835161594981613d1e565b82529284019290840190615936565b60a08152600061596b60a0830188613ed7565b67ffffffffffffffff8716602084015263ffffffff8616604084015282810360608401526159998186613fd7565b905082810360808401526159ad8185614052565b98975050505050505050565b600081518084526020808501945080840160005b8381101561404757815180516001600160a01b03908116895284820151168489015260409081015160070b90880152606090960195908201906001016159cd565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015615ad557898403603f19018652825180516001600160a01b0390811686528982015160608b880181905281519088018190526080880192918c01919086905b80821015615aa75783518051841686528e015160070b8e860152938c0193928d019260019190910190615a79565b5050505090880151858203868a015290615ac181836159b9565b978a01979550505091870191600101615a36565b50919998505050505050505050565b6020815260006112196020830184613ed7565b60008060408385031215615b0a57600080fd5b615b13836149da565b9150602083015167ffffffffffffffff811115615b2f57600080fd5b615b3b85828601615479565b915050925092905056fe90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aaa26469706673582212209b2868512f7ada058e50140bc7190fa533d71748a7da3f3bddc48212a1d566c664736f6c63430008090033", + "deployedBytecode": "0x6080604052600436106102c65760003560e01c80638070905f11610179578063d85f74c1116100d6578063f2f38a741161008a578063f848fec411610064578063f848fec414610844578063f9e978bd14610864578063fdc8321e1461088457600080fd5b8063f2f38a74146107d6578063f4a01e5b14610804578063f7be34251461082457600080fd5b8063eee55ac8116100bb578063eee55ac814610776578063f25b120014610796578063f2c31ff4146107b657600080fd5b8063d85f74c114610743578063d92ac2481461075657600080fd5b8063a345f7bd1161012d578063af99c63311610112578063af99c633146106d5578063c0b19b6d146106f5578063d614cdb81461072357600080fd5b8063a345f7bd1461067b578063a3ad5b551461069b57600080fd5b80638ba74da01161015e5780638ba74da0146106285780638f8d7f991461063b5780639604ca651461065b57600080fd5b80638070905f146105d957806386f88d881461060857600080fd5b80634cbdb37b1161022757806369837dc2116101db5780636da6b1f0116101c05780636da6b1f0146105795780637c41ad2c146105995780637d3e5da8146105b957600080fd5b806369837dc21461052b5780636a4dde211461055957600080fd5b8063593d6e821161020c578063593d6e82146104a65780635a5e6c31146104c65780635b9076b7146104fb57600080fd5b80634cbdb37b1461045857806356af84031461048657600080fd5b80632eecbca31161027e5780633eed2c39116102635780633eed2c39146104035780634b5c6687146104235780634ba670351461043857600080fd5b80632eecbca3146103c35780633b3bff0f146103e357600080fd5b806319db44b6116102af57806319db44b6146103385780632b256ec8146103755780632d73bb2e146103a357600080fd5b80630fd2601e146102cb57806313c05dd814610303575b600080fd5b3480156102d757600080fd5b506102eb6102e6366004613c51565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561030f57600080fd5b5061032361031e366004613c8a565b610968565b604080519283529015156020830152016102fa565b34801561034457600080fd5b50610358610353366004613cd5565b6109e6565b604080519283526001600160a01b039091166020830152016102fa565b34801561038157600080fd5b50610395610390366004613d01565b610a6a565b6040519081526020016102fa565b3480156103af57600080fd5b506103956103be366004613c51565b610b56565b3480156103cf57600080fd5b506102eb6103de366004613c51565b610b9b565b3480156103ef57600080fd5b506103956103fe366004613d01565b610bd2565b34801561040f57600080fd5b5061032361041e366004613d01565b610cac565b610436610431366004613d01565b610d26565b005b34801561044457600080fd5b50610395610453366004613d2d565b611114565b34801561046457600080fd5b50610478610473366004613d89565b611160565b6040516102fa9291906142ac565b34801561049257600080fd5b506103956104a13660046143e6565b6111d6565b3480156104b257600080fd5b506103956104c13660046144be565b611220565b3480156104d257600080fd5b506104e66104e1366004613c8a565b6112fd565b604080519283526020830191909152016102fa565b34801561050757600080fd5b5061051b610516366004613d01565b61136e565b6040516102fa949392919061453b565b34801561053757600080fd5b5061054b610546366004613d01565b611400565b6040516102fa9291906145b7565b34801561056557600080fd5b50610323610574366004613c51565b611475565b34801561058557600080fd5b50610395610594366004613d2d565b6114ec565b3480156105a557600080fd5b506103956105b4366004613d01565b6114fa565b3480156105c557600080fd5b506103956105d4366004613c51565b611528565b3480156105e557600080fd5b506105f96105f436600461460e565b611534565b6040516102fa93929190614757565b34801561061457600080fd5b50610323610623366004613d01565b6115bc565b610436610636366004613c51565b61162d565b34801561064757600080fd5b506102eb610656366004613c51565b611aef565b34801561066757600080fd5b50610395610676366004614789565b611b25565b34801561068757600080fd5b50610395610696366004613d01565b611b5a565b3480156106a757600080fd5b506106bb6106b6366004613c51565b611ba0565b6040805160079390930b83529015156020830152016102fa565b3480156106e157600080fd5b506102eb6106f0366004613c51565b611c92565b34801561070157600080fd5b50610715610710366004613d01565b611cc8565b6040516102fa9291906147fe565b34801561072f57600080fd5b5061071561073e366004613d01565b611dbf565b610436610751366004613d01565b611ec9565b34801561076257600080fd5b50610395610771366004614838565b61226e565b34801561078257600080fd5b506103956107913660046144be565b61227b565b3480156107a257600080fd5b506103956107b1366004614886565b61230e565b3480156107c257600080fd5b506106bb6107d1366004613c51565b61231b565b3480156107e257600080fd5b506107f66107f1366004613d01565b6123f6565b6040516102fa9291906148c6565b34801561081057600080fd5b5061039561081f366004613c51565b61246b565b34801561083057600080fd5b5061039561083f366004613d01565b612477565b34801561085057600080fd5b5061039561085f3660046148df565b61255a565b34801561087057600080fd5b5061043661087f366004614920565b612567565b34801561089057600080fd5b5061039561089f36600461493d565b6125dd565b604051638f8d7f9960e01b81526001600160a01b038084166004830152821660248201526000903090638f8d7f99906044015b602060405180830381600087803b1580156108f157600080fd5b505af1158015610905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109299190614988565b604051600782900b8152909150600080516020615b468339815191529060200160405180910390a1600781900b60161461096257600080fd5b92915050565b6000806109768585856127b4565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146109a957600080fd5b60405181151581527e1c2e72360171244b3bb8cc8ddd767820edf37138ad6f129fb3574b407c307d906020015b60405180910390a1935093915050565b6000806109f384846128b3565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214610a2657600080fd5b6040516001600160a01b03821681527fc2c78c7c31baf14949e75c51df12be56edb9af523cf82839c2869bbcf13b3ecb906020015b60405180910390a19250929050565b604051631f106b4b60e21b81526001600160a01b03821660048201526000903090637c41ad2c90602401602060405180830381600087803b158015610aae57600080fd5b505af1158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae691906149a5565b9050600080516020615b4683398151915281604051610b0791815260200190565b60405180910390a160168114610b1c57600080fd5b604051600181527f0c9c765845f4d139956bb8fc8decb2eec6093c9c608b809641b16054b29f0e13906020015b60405180910390a1919050565b6000610b628383612993565b60070b9050600080516020615b4683398151915281604051610b8691815260200190565b60405180910390a16016811461096257600080fd5b60405163af99c63360e01b81526001600160a01b03808416600483015282166024820152600090309063af99c633906044016108d7565b6040516001600160a01b03821660248201526000908190819061016790633b3bff0f60e01b906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610c3a91906149be565b6000604051808303816000865af19150503d8060008114610c77576040519150601f19603f3d011682016040523d82523d6000602084013e610c7c565b606091505b509150915081610c8d576015610ca1565b80806020019051810190610ca191906149ec565b60030b949350505050565b600080610cb8836129e2565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214610ceb57600080fd5b60405181151581527f6b7f3306751292f85ab4161ee2b0ac16dfc8ded13e6446ce6bd859d0a2f4c78e906020015b60405180910390a1915091565b60408051600480825260a08201909252600091816020015b610d46613ac3565b815260200190600190039081610d3e579050509050610d7960006006600160405180602001604052806000815250612adf565b81600081518110610d8c57610d8c614a07565b6020026020010181905250610db260018060405180602001604052806000815250612b16565b81600181518110610dc557610dc5614a07565b6020026020010181905250610dec6002600160405180602001604052806000815250612b16565b81600281518110610dff57610dff614a07565b6020026020010181905250610e266003600160405180602001604052806000815250612b16565b81600381518110610e3957610e39614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff168152509050600060405180610120016040528060018054610e9790614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ec390614a1d565b8015610f105780601f10610ee557610100808354040283529160200191610f10565b820191906000526020600020905b815481529060010190602001808311610ef357829003601f168201915b5050505050815260200160028054610f2790614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5390614a1d565b8015610fa05780601f10610f7557610100808354040283529160200191610fa0565b820191906000526020600020905b815481529060010190602001808311610f8357829003601f168201915b50505050508152602001856001600160a01b0316815260200160038054610fc690614a1d565b80601f0160208091040260200160405190810160405280929190818152602001828054610ff290614a1d565b801561103f5780601f106110145761010080835404028352916020019161103f565b820191906000526020600020905b81548152906001019060200180831161102257829003601f168201915b50505091835250506001602082015260045468010000000000000000810460070b6040830152600160a01b810460ff16151560608301526080820186905260a090910184905290915060009081906110be90849067ffffffffffffffff811690700100000000000000000000000000000000900463ffffffff16612b4b565b9092509050601682146110d057600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b600061112285858585612c79565b9050600080516020615b468339815191528160405161114391815260200190565b60405180910390a16016811461115857600080fd5b949350505050565b600061116a613b20565b6111748484612d89565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146111a757600080fd5b7fd010ef68d3ac3e07c14bed496400730a484fd17c48a4d373cbc4722a56540def81604051610a5b9190614a58565b60006111e3848484612e7c565b9050600080516020615b468339815191528160405161120491815260200190565b60405180910390a16016811461121957600080fd5b9392505050565b60008060006101676001600160a01b031663593d6e8260e01b868660405160240161124c929190614a6b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161128a91906149be565b6000604051808303816000865af19150503d80600081146112c7576040519150601f19603f3d011682016040523d82523d6000602084013e6112cc565b606091505b5091509150816112dd5760156112f1565b808060200190518101906112f191906149ec565b60030b95945050505050565b60008061130b858585612f5c565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461133e57600080fd5b6040518181527f25b6684a7e8fe1b676e9c39c8dd65034fbafea906d3bdfd97bf748b7b55e14c8906020016109d6565b6000606080606061137e85613048565b604051600785900b815293975091955093509150600080516020615b468339815191529060200160405180910390a1600784900b6016146113be57600080fd5b7f2efc8334b040613a552197fe34283d6ca2909c8ffae393e128424931f20c69b38383836040516113f193929190614aae565b60405180910390a19193509193565b600061140a613b5b565b61141383613148565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461144657600080fd5b7fea9419ffbaa766adf982c4c9864330eee1d848eff36c79e510e7e589c8bb265f81604051610d199190614ae7565b6000806114828484613231565b60405160079290920b80835293509150600080516020615b468339815191529060200160405180910390a1601682146114ba57600080fd5b60405181151581527f59800d968fcce138300a0019410b4b75041610d65b3cdc5f31656b03ed14912e90602001610a5b565b600061112285858585613282565b6040516001600160a01b03821660248201526000908190819061016790631f106b4b60e21b90604401610bfc565b6000610b6283836132e3565b6000806060611544868686613332565b6040518381529295509093509150600080516020615b468339815191529060200160405180910390a16016831461157a57600080fd5b7feff23992f47b3c101679f8b4dc9d3e242c903909dba4a453f2b2341ad463b0e282826040516115ab929190614afa565b60405180910390a193509350939050565b6000806115c883613430565b6040518281529193509150600080516020615b468339815191529060200160405180910390a1601682146115fb57600080fd5b60405181151581527f9ee19e13dfa1ba8db2502e15ff56dbecdeb0e0473323fb195473ce648030a2cd90602001610d19565b604080516001808252818301909252600091816020015b61164c613ac3565b81526020019060019003908161164457905050905061167e600080600160405180602001604052806000815250612adf565b8160008151811061169157611691614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546116ef90614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461171b90614a1d565b80156117685780601f1061173d57610100808354040283529160200191611768565b820191906000526020600020905b81548152906001019060200180831161174b57829003601f168201915b505050505081526020016002805461177f90614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546117ab90614a1d565b80156117f85780601f106117cd576101008083540402835291602001916117f8565b820191906000526020600020905b8154815290600101906020018083116117db57829003601f168201915b50505050508152602001866001600160a01b031681526020016003805461181e90614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461184a90614a1d565b80156118975780601f1061186c57610100808354040283529160200191611897565b820191906000526020600020905b81548152906001019060200180831161187a57829003601f168201915b505050918352505060016020820181905260045468010000000000000000900460070b6040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182526000808252602080830182905292820181905260608201819052608082015282526000199092019101816118f15750506040805160a081018252600181526001600160a01b0388811660208301526000928201839052606082018390528916608082015282519293509183919061197457611974614a07565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a082015282526000199092019101816119965750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a083015282519293509091839190611a2a57611a2a614a07565b60209081029190910101526004546000908190611a7090869067ffffffffffffffff811690700100000000000000000000000000000000900463ffffffff168787613479565b91509150600080516020615b4683398151915282604051611a9391815260200190565b60405180910390a160168214611aa857600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b038381166024830152821660448201526000908190819061016790638f8d7f9960e01b9060640161124c565b6000611b39611b348385614bcc565b6135ad565b9050600080516020615b4683398151915281604051610b8691815260200190565b6000611b65826135d7565b9050600080516020615b4683398151915281604051611b8691815260200190565b60405180910390a160168114611b9b57600080fd5b919050565b604051633cb0c7fd60e21b81526001600160a01b038084166004830152821660248201526000908190309063f2c31ff4906044016040805180830381600087803b158015611bed57600080fd5b505af1158015611c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c259190614d44565b604051600783900b81529193509150600080516020615b468339815191529060200160405180910390a1600782900b601614611c6057600080fd5b60405181151581527fd24dda6928587354b65aa1a18c2eaf249bef7e5bafd2a71fac71d286f76f957f90602001610a5b565b6040516001600160a01b03838116602483015282166044820152600090819081906101679063af99c63360e01b9060640161124c565b60408051606081018252600080825260208201819052918101829052604051631ac299b760e31b81526001600160a01b0384166004820152309063d614cdb890602401608060405180830381600087803b158015611d2557600080fd5b505af1158015611d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5d9190614dd3565b6040518281529193509150600080516020615b468339815191529060200160405180910390a160168214611d9057600080fd5b7fa0a16bf9db2c17796faeca5af5aaeef8523f9d4c350c512cb00062ad89604f8881604051610d199190614e00565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b0316631ac299b760e31b179052925190928391829161016791611e3191906149be565b6000604051808303816000865af19150503d8060008114611e6e576040519150601f19603f3d011682016040523d82523d6000602084013e611e73565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082611ea357601581611eb7565b81806020019051810190611eb79190614e34565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b611ee9613ac3565b815260200190600190039081611ee1579050509050611f1c60006006600160405180602001604052806000815250612adf565b81600081518110611f2f57611f2f614a07565b6020026020010181905250611f5560018060405180602001604052806000815250612b16565b81600181518110611f6857611f68614a07565b6020026020010181905250611f8f6002600160405180602001604052806000815250612b16565b81600281518110611fa257611fa2614a07565b6020026020010181905250611fc96004600160405180602001604052806000815250612b16565b81600381518110611fdc57611fdc614a07565b60200260200101819052506120036003600160405180602001604052806000815250612b16565b8160048151811061201657612016614a07565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff16815250905060006040518061012001604052806001805461207490614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546120a090614a1d565b80156120ed5780601f106120c2576101008083540402835291602001916120ed565b820191906000526020600020905b8154815290600101906020018083116120d057829003601f168201915b505050505081526020016002805461210490614a1d565b80601f016020809104026020016040519081016040528092919081815260200182805461213090614a1d565b801561217d5780601f106121525761010080835404028352916020019161217d565b820191906000526020600020905b81548152906001019060200180831161216057829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546121a390614a1d565b80601f01602080910402602001604051908101604052809291908181526020018280546121cf90614a1d565b801561221c5780601f106121f15761010080835404028352916020019161221c565b820191906000526020600020905b8154815290600101906020018083116121ff57829003601f168201915b50505091835250506001602082015260045468010000000000000000810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290506000806110be8361361e565b60006111e3848484613708565b6040517f593d6e82000000000000000000000000000000000000000000000000000000008152600090309063593d6e82906122bc9086908690600401614a6b565b602060405180830381600087803b1580156122d657600080fd5b505af11580156122ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3991906149a5565b60006111e3848484613763565b6040516001600160a01b0383811660248301528216604482015260009081908190819061016790633cb0c7fd60e21b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161238d91906149be565b6000604051808303816000865af19150503d80600081146123ca576040519150601f19603f3d011682016040523d82523d6000602084013e6123cf565b606091505b5091509150816123e25760156000611eb7565b80806020019051810190611eb79190614e5f565b6000612400613b7b565b612409836137ba565b6040518281529193509150600080516020615b468339815191529060200160405180910390a16016821461243c57600080fd5b7fbdb65f8c2a2e9a3a37ea49e903836883766a922e4ce9b21f684035e304962d4181604051610d199190614e8b565b6000611b3983836138a3565b604051633b3bff0f60e01b81526001600160a01b03821660048201526000903090633b3bff0f90602401602060405180830381600087803b1580156124bb57600080fd5b505af11580156124cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124f391906149a5565b9050600080516020615b468339815191528160405161251491815260200190565b60405180910390a16016811461252957600080fd5b604051600181527f319ab7084208e4afa38c6e6ff7aea9587439f2e4700746f4c7d425fea17426d290602001610b49565b60006111e38484846138f2565b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b8315158102919091179182905560405160ff9190920416151581527f457c3a16a0ebdc38e3675609957ca3fcc4490e220bd15d85d34f58e2e145cb089060200160405180910390a150565b60408051600080825260208201909252819081612622565b60408051606081018252600080825260208083018290529282015282526000199092019101816125f55790505b50905060006040518060400160405280336001600160a01b031681526020018561264b90614e9e565b600790810b9091526040805180820182526001600160a01b038a1681529187900b602083015280516002808252606082019092529293509091600091816020015b604080518082019091526000808252602082015281526020019060019003908161268c57905050905082816000815181106126c9576126c9614a07565b602002602001018190525081816001815181106126e8576126e8614a07565b602090810291909101810191909152604080516060810182526001600160a01b038a16815291820183905281810186905280516001808252818301909252600091816020015b61275b604051806060016040528060006001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161272e579050509050818160008151811061278457612784614a07565b6020026020010181905250612798816135ad565b9650601687146127a757600080fd5b5050505050509392505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167ff49f40db00000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612837916149be565b6000604051808303816000865af19150503d8060008114612874576040519150601f19603f3d011682016040523d82523d6000602084013e612879565b606091505b50915091508161288c57601560006128a0565b808060200190518101906128a09190614e5f565b60039190910b9890975095505050505050565b604080516001600160a01b0384166024820152604480820184905282518083039091018152606490910182526020810180516001600160e01b03167f098f23660000000000000000000000000000000000000000000000000000000017905290516000918291829182916101679161292a916149be565b6000604051808303816000865af19150503d8060008114612967576040519150601f19603f3d011682016040523d82523d6000602084013e61296c565b606091505b50915091508161297f5760156000611eb7565b80806020019051810190611eb79190614ed4565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f52f91387000000000000000000000000000000000000000000000000000000009060640161124c565b6040516001600160a01b0382166024820152600090819081908190610167907fa7daa18d00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612a6591906149be565b6000604051808303816000865af19150503d8060008114612aa2576040519150601f19603f3d011682016040523d82523d6000602084013e612aa7565b606091505b509150915081612aba5760156000612ace565b80806020019051810190612ace9190614e5f565b60039190910b969095509350505050565b612ae7613ac3565b6040518060400160405280612afc8787613948565b8152602001612b0b8585613961565b905295945050505050565b612b1e613ac3565b6040518060400160405280612b3286613a31565b8152602001612b418585613961565b9052949350505050565b600080848061010001516000015163ffffffff166000148015612b7b57506101008101516040015163ffffffff16155b15612b91576101008101516276a7006040909101525b6000806101676001600160a01b03163463c23baeb660e01b8a8a8a604051602401612bbe93929190614f00565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612bfc91906149be565b60006040518083038185875af1925050503d8060008114612c39576040519150601f19603f3d011682016040523d82523d6000602084013e612c3e565b606091505b509150915081612c515760156000612c65565b80806020019051810190612c659190614ed4565b60039190910b999098509650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907feca36917000000000000000000000000000000000000000000000000000000009060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612d1491906149be565b6000604051808303816000865af19150503d8060008114612d51576040519150601f19603f3d011682016040523d82523d6000602084013e612d56565b606091505b509150915081612d67576015612d7b565b80806020019051810190612d7b91906149ec565b60030b979650505050505050565b6000612d93613b20565b604080516001600160a01b0386166024820152600785900b60448083019190915282518083039091018152606490910182526020810180516001600160e01b03167f287e1da8000000000000000000000000000000000000000000000000000000001790529051600091829161016791612e0c916149be565b6000604051808303816000865af19150503d8060008114612e49576040519150601f19603f3d011682016040523d82523d6000602084013e612e4e565b606091505b5091509150612e5b613b20565b82612e68576015816128a0565b818060200190518101906128a0919061559e565b60008060006101676001600160a01b031663f7f38e2660e01b878787604051602401612eaa93929190615686565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612ee891906149be565b6000604051808303816000865af19150503d8060008114612f25576040519150601f19603f3d011682016040523d82523d6000602084013e612f2a565b606091505b509150915081612f3b576015612f4f565b80806020019051810190612f4f91906149ec565b60030b9695505050505050565b604080516001600160a01b0385811660248301528481166044830152831660648083019190915282518083039091018152608490910182526020810180516001600160e01b03167f927da10500000000000000000000000000000000000000000000000000000000179052905160009182918291829161016791612fdf916149be565b6000604051808303816000865af19150503d806000811461301c576040519150601f19603f3d011682016040523d82523d6000602084013e613021565b606091505b50915091508161303457601560006128a0565b808060200190518101906128a091906156b2565b604080516001600160a01b03831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167fae7611a00000000000000000000000000000000000000000000000000000000017905290516000916060918291829185918291610167916130c0916149be565b6000604051808303816000865af19150503d80600081146130fd576040519150601f19603f3d011682016040523d82523d6000602084013e613102565b606091505b509150915060608060608461311b57601583838361312f565b8380602001905181019061312f91906156de565b60039390930b9d919c509a509098509650505050505050565b6000613152613b5b565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f3f28a19b0000000000000000000000000000000000000000000000000000000017905290516000918291610167916131c1916149be565b6000604051808303816000865af19150503d80600081146131fe576040519150601f19603f3d011682016040523d82523d6000602084013e613203565b606091505b5091509150613210613b5b565b8261321d57601581611eb7565b81806020019051810190611eb79190615777565b6040516001600160a01b03838116602483015282166044820152600090819081908190610167907f46de0fb1000000000000000000000000000000000000000000000000000000009060640161234f565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b608482015260009081908190610167907f5cfc9011000000000000000000000000000000000000000000000000000000009060a401612cd6565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f5b8f8584000000000000000000000000000000000000000000000000000000009060640161124c565b60008060606000806101676001600160a01b031663278e0b8860e01b89898960405160240161336393929190615823565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516133a191906149be565b6000604051808303816000865af19150503d80600081146133de576040519150601f19603f3d011682016040523d82523d6000602084013e6133e3565b606091505b50915091508161340657604080516000808252602082019092526015919061341a565b8080602001905181019061341a91906158a7565b60039290920b9a90995090975095505050505050565b6040516001600160a01b0382166024820152600090819081908190610167907f335e04c10000000000000000000000000000000000000000000000000000000090604401612a27565b600080868061010001516000015163ffffffff1660001480156134a957506101008101516040015163ffffffff16155b156134bf576101008101516276a7006040909101525b6000806101676001600160a01b03163463b937581a60e01b8c8c8c8c8c6040516024016134f0959493929190615958565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161352e91906149be565b60006040518083038185875af1925050503d806000811461356b576040519150601f19603f3d011682016040523d82523d6000602084013e613570565b606091505b5091509150816135835760156000613597565b808060200190518101906135979190614ed4565b60039190910b9b909a5098505050505050505050565b60008060006101676001600160a01b031663189a554c60e01b85604051602401610bfc9190615a0e565b6040516001600160a01b038216602482015260009081908190610167907ff069f7120000000000000000000000000000000000000000000000000000000090604401610bfc565b600080828061010001516000015163ffffffff16600014801561364e57506101008101516040015163ffffffff16155b15613664576101008101516276a7006040909101525b6000806101676001600160a01b031634639c89bb3560e01b8860405160240161368d9190615ae4565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516136cb91906149be565b60006040518083038185875af1925050503d8060008114612967576040519150601f19603f3d011682016040523d82523d6000602084013e61296c565b6040516001600160a01b0384811660248301528316604482015263ffffffff8216606482015260009081908190610167907f9790686d0000000000000000000000000000000000000000000000000000000090608401612eaa565b6040516001600160a01b03848116602483015283166044820152811515606482015260009081908190610167907f367605ca0000000000000000000000000000000000000000000000000000000090608401612eaa565b60006137c4613b7b565b604080516001600160a01b03851660248083019190915282518083039091018152604490910182526020810180516001600160e01b03167f1f69565f000000000000000000000000000000000000000000000000000000001790529051600091829161016791613833916149be565b6000604051808303816000865af19150503d8060008114613870576040519150601f19603f3d011682016040523d82523d6000602084013e613875565b606091505b5091509150613882613b7b565b8261388f57601581611eb7565b81806020019051810190611eb79190615af7565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde000000000000000000000000000000000000000000000000000000009060640161124c565b6040516001600160a01b038481166024830152831660448201526064810182905260009081908190610167907fe1f21c670000000000000000000000000000000000000000000000000000000090608401612eaa565b6000600160ff84161b9050600160ff83161b8117611219565b6139a76040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156139bc5760018152610962565b8260ff16600214156139de576000546001600160a01b03166020820152610962565b8260ff16600314156139f65760408101829052610962565b8260ff1660041415613a0e5760608101829052610962565b8260ff1660051415610962576000546001600160a01b0316608082015292915050565b600060ff8216613a4357506001919050565b8160ff1660011415613a5757506002919050565b8160ff1660021415613a6b57506004919050565b8160ff1660031415613a7f57506008919050565b8160ff1660041415613a9357506010919050565b8160ff1660051415613aa757506020919050565b8160ff1660061415613abb57506040919050565b506000919050565b604051806040016040528060008152602001613b1b6040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6040518060c00160405280613b33613b7b565b8152600060208201819052604082018190526060808301829052608083015260a09091015290565b6040518060400160405280613b6e613b7b565b8152600060209091015290565b60408051610240810182526060610120820181815261014083018290526000610160840181905261018084018390526101a084018190526101c084018190526101e0840181905261020084018390528451928301855280835260208301819052938201939093526102208201529081908152602001600067ffffffffffffffff168152602001600015158152602001600015158152602001600015158152602001606081526020016060815260200160608152602001606081525090565b6001600160a01b0381168114613c4e57600080fd5b50565b60008060408385031215613c6457600080fd5b8235613c6f81613c39565b91506020830135613c7f81613c39565b809150509250929050565b600080600060608486031215613c9f57600080fd5b8335613caa81613c39565b92506020840135613cba81613c39565b91506040840135613cca81613c39565b809150509250925092565b60008060408385031215613ce857600080fd5b8235613cf381613c39565b946020939093013593505050565b600060208284031215613d1357600080fd5b813561121981613c39565b8060070b8114613c4e57600080fd5b60008060008060808587031215613d4357600080fd5b8435613d4e81613c39565b93506020850135613d5e81613c39565b92506040850135613d6e81613c39565b91506060850135613d7e81613d1e565b939692955090935050565b60008060408385031215613d9c57600080fd5b8235613da781613c39565b91506020830135613c7f81613d1e565b60005b83811015613dd2578181015183820152602001613dba565b83811115613de1576000848401525b50505050565b60008151808452613dff816020860160208601613db7565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015613eca5782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152613e8c60e08b0186613de7565b928601518a8403603f1901858c0152929450613ea88584613de7565b9501511660c09890980197909752505098850198935090840190600101613e31565b5091979650505050505050565b60006101608251818552613eed82860182613de7565b91505060208301518482036020860152613f078282613de7565b9150506040830151613f2460408601826001600160a01b03169052565b5060608301518482036060860152613f3c8282613de7565b9150506080830151613f52608086018215159052565b5060a0830151613f6760a086018260070b9052565b5060c0830151613f7b60c086018215159052565b5060e083015184820360e0860152613f938282613e13565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff168852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613feb565b509495945050505050565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101614066565b600081518084526020808501945080840160005b83811015614047578151805163ffffffff9081168952848201518116858a0152604080830151909116908901526060808201516001600160a01b03908116918a01919091526080808301511515908a015260a091820151169088015260c090960195908201906001016140e4565b6000610120825181855261416882860182613ed7565b9150506020830151614186602086018267ffffffffffffffff169052565b50604083015161419a604086018215159052565b5060608301516141ae606086018215159052565b5060808301516141c2608086018215159052565b5060a083015184820360a08601526141da8282613fd7565b91505060c083015184820360c08601526141f48282614052565b91505060e083015184820360e086015261420e82826140d0565b91505061010080840151858303828701526142298382613de7565b9695505050505050565b6000815160c0845261424860c0850182614152565b9050602083015160070b602085015260408301516001600160a01b038082166040870152606085015160070b60608701526080850151915085830360808701526142928383613de7565b92508060a08601511660a087015250508091505092915050565b8281526040602082015260006111586040830184614233565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405290565b6040805190810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405160a0810167ffffffffffffffff811182821017156142fe576142fe6142c5565b604051610120810167ffffffffffffffff811182821017156142fe576142fe6142c5565b60405160c0810167ffffffffffffffff811182821017156142fe576142fe6142c5565b604051601f8201601f1916810167ffffffffffffffff811182821017156143ba576143ba6142c5565b604052919050565b600067ffffffffffffffff8211156143dc576143dc6142c5565b5060051b60200190565b6000806000606084860312156143fb57600080fd5b833561440681613c39565b925060208481013561441781613c39565b9250604085013567ffffffffffffffff81111561443357600080fd5b8501601f8101871361444457600080fd5b8035614457614452826143c2565b614391565b81815260059190911b8201830190838101908983111561447657600080fd5b928401925b8284101561449d57833561448e81613d1e565b8252928401929084019061447b565b80955050505050509250925092565b63ffffffff81168114613c4e57600080fd5b60008082840360808112156144d257600080fd5b83356144dd81613c39565b92506060601f19820112156144f157600080fd5b506144fa6142db565b6020840135614508816144ac565b8152604084013561451881613c39565b6020820152606084013561452b816144ac565b6040820152919491935090915050565b8460070b81526080602082015260006145576080830186613fd7565b82810360408401526145698186614052565b9050828103606084015261457d81856140d0565b979650505050505050565b600081516040845261459d6040850182614152565b60209384015163ffffffff16949093019390935250919050565b8281526040602082015260006111586040830184614588565b67ffffffffffffffff81168114613c4e57600080fd5b600067ffffffffffffffff821115614600576146006142c5565b50601f01601f191660200190565b60008060006060848603121561462357600080fd5b833561462e81613c39565b925060208481013561463f816145d0565b925060408581013567ffffffffffffffff8082111561465d57600080fd5b818801915088601f83011261467157600080fd5b813561467f614452826143c2565b81815260059190911b8301850190858101908b83111561469e57600080fd5b8685015b83811015614712578035858111156146ba5760008081fd5b8601603f81018e136146cc5760008081fd5b888101356146dc614452826145e6565b8181528f8a8385010111156146f15760008081fd5b818a84018c83013760009181018b01919091528452509187019187016146a2565b50809750505050505050509250925092565b600081518084526020808501945080840160005b8381101561404757815160070b87529582019590820190600101614738565b83815267ffffffffffffffff831660208201526060604082015260006147806060830184614724565b95945050505050565b6000806020838503121561479c57600080fd5b823567ffffffffffffffff808211156147b457600080fd5b818501915085601f8301126147c857600080fd5b8135818111156147d757600080fd5b8660208260051b85010111156147ec57600080fd5b60209290920196919550909350505050565b828152608081016112196020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060006060848603121561484d57600080fd5b833561485881613c39565b9250602084013561486881613c39565b91506040840135613cca816144ac565b8015158114613c4e57600080fd5b60008060006060848603121561489b57600080fd5b83356148a681613c39565b925060208401356148b681613c39565b91506040840135613cca81614878565b8281526040602082015260006111586040830184614152565b6000806000606084860312156148f457600080fd5b83356148ff81613c39565b9250602084013561490f81613c39565b929592945050506040919091013590565b60006020828403121561493257600080fd5b813561121981614878565b60008060006060848603121561495257600080fd5b833561495d81613c39565b9250602084013561496d81613c39565b91506040840135613cca81613d1e565b8051611b9b81613d1e565b60006020828403121561499a57600080fd5b815161121981613d1e565b6000602082840312156149b757600080fd5b5051919050565b600082516149d0818460208701613db7565b9190910192915050565b8051600381900b8114611b9b57600080fd5b6000602082840312156149fe57600080fd5b611219826149da565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680614a3157607f821691505b60208210811415614a5257634e487b7160e01b600052602260045260246000fd5b50919050565b6020815260006112196020830184614233565b6001600160a01b0383168152608081016112196020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b606081526000614ac16060830186613fd7565b8281036020840152614ad38186614052565b9050828103604084015261422981856140d0565b6020815260006112196020830184614588565b67ffffffffffffffff831681526040602082015260006111586040830184614724565b600082601f830112614b2e57600080fd5b81356020614b3e614452836143c2565b82815260609283028501820192828201919087851115614b5d57600080fd5b8387015b85811015614bbf5781818a031215614b795760008081fd5b614b816142db565b8135614b8c81613c39565b815281860135614b9b81613c39565b81870152604082810135614bae81613d1e565b908201528452928401928101614b61565b5090979650505050505050565b6000614bda614452846143c2565b80848252602080830192508560051b850136811115614bf857600080fd5b855b81811015614d2d57803567ffffffffffffffff80821115614c1b5760008081fd5b818901915060608236031215614c315760008081fd5b614c396142db565b8235614c4481613c39565b81528286013582811115614c585760008081fd5b830136601f820112614c6a5760008081fd5b8035614c78614452826143c2565b81815260069190911b82018801908881019036831115614c985760008081fd5b928901925b82841015614cee5760408436031215614cb65760008081fd5b614cbe614304565b8435614cc981613c39565b8152848b0135614cd881613d1e565b818c015282526040939093019290890190614c9d565b848a01525060409150508381013583811115614d0a5760008081fd5b614d1636828701614b1d565b918301919091525087525050938201938201614bfa565b50919695505050505050565b8051611b9b81614878565b60008060408385031215614d5757600080fd5b8251614d6281613d1e565b6020840151909250613c7f81614878565b8051611b9b81613c39565b600060608284031215614d9057600080fd5b614d986142db565b90508151614da5816144ac565b81526020820151614db581613c39565b60208201526040820151614dc8816144ac565b604082015292915050565b60008060808385031215614de657600080fd5b82519150614df78460208501614d7e565b90509250929050565b606081016109628284805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60008060808385031215614e4757600080fd5b614e50836149da565b9150614df78460208501614d7e565b60008060408385031215614e7257600080fd5b614e7b836149da565b91506020830151613c7f81614878565b6020815260006112196020830184614152565b60008160070b677fffffffffffffff19811415614ecb57634e487b7160e01b600052601160045260246000fd5b60000392915050565b60008060408385031215614ee757600080fd5b614ef0836149da565b91506020830151613c7f81613c39565b606081526000614f136060830186613ed7565b905067ffffffffffffffff8416602083015263ffffffff83166040830152949350505050565b600082601f830112614f4a57600080fd5b8151614f58614452826145e6565b818152846020838601011115614f6d57600080fd5b611158826020830160208701613db7565b600082601f830112614f8f57600080fd5b81516020614f9f614452836143c2565b82815260059290921b84018101918181019086841115614fbe57600080fd5b8286015b848110156150d457805167ffffffffffffffff80821115614fe257600080fd5b908801906040601f19838c038101821315614ffc57600080fd5b615004614304565b888501518152828501518481111561501b57600080fd5b949094019360a0858e03830112156150335760008081fd5b61503b614327565b91508885015161504a81614878565b82528483015161505981613c39565b828a0152606085810151858111156150715760008081fd5b61507f8f8c838a0101614f39565b858501525060809350838601518581111561509a5760008081fd5b6150a88f8c838a0101614f39565b8285015250506150ba60a08601614d73565b928201929092528188015285525050918301918301614fc2565b509695505050505050565b600061016082840312156150f257600080fd5b6150fa61434a565b9050815167ffffffffffffffff8082111561511457600080fd5b61512085838601614f39565b8352602084015191508082111561513657600080fd5b61514285838601614f39565b602084015261515360408501614d73565b6040840152606084015191508082111561516c57600080fd5b61517885838601614f39565b606084015261518960808501614d39565b608084015261519a60a0850161497d565b60a08401526151ab60c08501614d39565b60c084015260e08401519150808211156151c457600080fd5b506151d184828501614f7e565b60e0830152506101006151e684828501614d7e565b9082015292915050565b8051611b9b816145d0565b600082601f83011261520c57600080fd5b8151602061521c614452836143c2565b82815260a0928302850182019282820191908785111561523b57600080fd5b8387015b85811015614bbf5781818a0312156152575760008081fd5b61525f614327565b815161526a816144ac565b81528186015161527981613c39565b8187015260408281015161528c81614878565b9082015260608281015161529f81614878565b908201526080828101516152b281613c39565b90820152845292840192810161523f565b600082601f8301126152d457600080fd5b815160206152e4614452836143c2565b82815260c0928302850182019282820191908785111561530357600080fd5b8387015b85811015614bbf5781818a03121561531f5760008081fd5b61532761436e565b8151615332816144ac565b815281860151615341816144ac565b81870152604082810151615354816144ac565b90820152606082810151615367816144ac565b9082015260808281015161537a81614878565b9082015260a08281015161538d81613c39565b908201528452928401928101615307565b600082601f8301126153af57600080fd5b815160206153bf614452836143c2565b82815260c092830285018201928282019190878511156153de57600080fd5b8387015b85811015614bbf5781818a0312156153fa5760008081fd5b61540261436e565b815161540d816144ac565b81528186015161541c816144ac565b8187015260408281015161542f816144ac565b9082015260608281015161544281613c39565b9082015260808281015161545581614878565b9082015260a08281015161546881613c39565b9082015284529284019281016153e2565b6000610120828403121561548c57600080fd5b61549461434a565b9050815167ffffffffffffffff808211156154ae57600080fd5b6154ba858386016150df565b83526154c8602085016151f0565b60208401526154d960408501614d39565b60408401526154ea60608501614d39565b60608401526154fb60808501614d39565b608084015260a084015191508082111561551457600080fd5b615520858386016151fb565b60a084015260c084015191508082111561553957600080fd5b615545858386016152c3565b60c084015260e084015191508082111561555e57600080fd5b61556a8583860161539e565b60e08401526101009150818401518181111561558557600080fd5b61559186828701614f39565b8385015250505092915050565b600080604083850312156155b157600080fd5b6155ba836149da565b9150602083015167ffffffffffffffff808211156155d757600080fd5b9084019060c082870312156155eb57600080fd5b6155f361436e565b82518281111561560257600080fd5b61560e88828601615479565b82525061561d6020840161497d565b602082015261562e60408401614d73565b604082015261563f6060840161497d565b606082015260808301518281111561565657600080fd5b61566288828601614f39565b60808301525061567460a08401614d73565b60a08201528093505050509250929050565b60006001600160a01b038086168352808516602084015250606060408301526147806060830184614724565b600080604083850312156156c557600080fd5b6156ce836149da565b9150602083015190509250929050565b600080600080608085870312156156f457600080fd5b6156fd856149da565b9350602085015167ffffffffffffffff8082111561571a57600080fd5b615726888389016151fb565b9450604087015191508082111561573c57600080fd5b615748888389016152c3565b9350606087015191508082111561575e57600080fd5b5061576b8782880161539e565b91505092959194509250565b6000806040838503121561578a57600080fd5b615793836149da565b9150602083015167ffffffffffffffff808211156157b057600080fd5b90840190604082870312156157c457600080fd5b6040516040810181811083821117156157df576157df6142c5565b6040528251828111156157f157600080fd5b6157fd88828601615479565b82525060208301519250615810836144ac565b8260208201528093505050509250929050565b6000606082016001600160a01b0386168352602067ffffffffffffffff8616818501526060604085015281855180845260808601915060808160051b870101935082870160005b8281101561589857607f19888703018452615886868351613de7565b9550928401929084019060010161586a565b50939998505050505050505050565b6000806000606084860312156158bc57600080fd5b6158c5846149da565b92506020808501516158d6816145d0565b604086015190935067ffffffffffffffff8111156158f357600080fd5b8501601f8101871361590457600080fd5b8051615912614452826143c2565b81815260059190911b8201830190838101908983111561593157600080fd5b928401925b8284101561449d57835161594981613d1e565b82529284019290840190615936565b60a08152600061596b60a0830188613ed7565b67ffffffffffffffff8716602084015263ffffffff8616604084015282810360608401526159998186613fd7565b905082810360808401526159ad8185614052565b98975050505050505050565b600081518084526020808501945080840160005b8381101561404757815180516001600160a01b03908116895284820151168489015260409081015160070b90880152606090960195908201906001016159cd565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015615ad557898403603f19018652825180516001600160a01b0390811686528982015160608b880181905281519088018190526080880192918c01919086905b80821015615aa75783518051841686528e015160070b8e860152938c0193928d019260019190910190615a79565b5050505090880151858203868a015290615ac181836159b9565b978a01979550505091870191600101615a36565b50919998505050505050505050565b6020815260006112196020830184613ed7565b60008060408385031215615b0a57600080fd5b615b13836149da565b9150602083015167ffffffffffffffff811115615b2f57600080fd5b615b3b85828601615479565b915050925092905056fe90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aaa26469706673582212209b2868512f7ada058e50140bc7190fa533d71748a7da3f3bddc48212a1d566c664736f6c63430008090033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/packages/server/tests/contracts/BaseHTS.sol b/packages/server/tests/contracts/BaseHTS.sol index fac99e0441..f1b5791ee5 100644 --- a/packages/server/tests/contracts/BaseHTS.sol +++ b/packages/server/tests/contracts/BaseHTS.sol @@ -9,9 +9,9 @@ contract BaseHTS is FeeHelper { string name = "tokenName"; string symbol = "tokenSymbol"; string memo = "memo"; - uint initialTotalSupply = 1000; - uint32 maxSupply = 1000; - uint decimals = 8; + uint64 initialTotalSupply = 1000; + int64 maxSupply = 1000; + uint32 decimals = 8; bool freezeDefaultStatus = false; event CreatedToken(address tokenAddress); diff --git a/packages/server/tests/contracts/HederaTokenService.sol b/packages/server/tests/contracts/HederaTokenService.sol index 4b1ac1bbf3..15b7a60b1a 100644 --- a/packages/server/tests/contracts/HederaTokenService.sol +++ b/packages/server/tests/contracts/HederaTokenService.sol @@ -154,8 +154,8 @@ abstract contract HederaTokenService is HederaResponseCodes { /// @return tokenAddress the created token's address function createFungibleToken( IHederaTokenService.HederaToken memory token, - uint initialTotalSupply, - uint decimals) nonEmptyExpiry(token) + uint64 initialTotalSupply, + uint32 decimals) nonEmptyExpiry(token) internal returns (int responseCode, address tokenAddress) { (bool success, bytes memory result) = precompileAddress.call{value: msg.value}( abi.encodeWithSelector(IHederaTokenService.createFungibleToken.selector, @@ -176,8 +176,8 @@ abstract contract HederaTokenService is HederaResponseCodes { /// @return tokenAddress the created token's address function createFungibleTokenWithCustomFees( IHederaTokenService.HederaToken memory token, - uint initialTotalSupply, - uint decimals, + uint64 initialTotalSupply, + uint32 decimals, IHederaTokenService.FixedFee[] memory fixedFees, IHederaTokenService.FractionalFee[] memory fractionalFees) nonEmptyExpiry(token) internal returns (int responseCode, address tokenAddress) { diff --git a/packages/server/tests/contracts/IHederaTokenService.json b/packages/server/tests/contracts/IHederaTokenService.json index 8226d85089..dafdcaebc7 100644 --- a/packages/server/tests/contracts/IHederaTokenService.json +++ b/packages/server/tests/contracts/IHederaTokenService.json @@ -207,9 +207,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -288,14 +288,14 @@ "type": "tuple" }, { - "internalType": "uint256", + "internalType": "uint64", "name": "initialTotalSupply", - "type": "uint256" + "type": "uint64" }, { - "internalType": "uint256", + "internalType": "uint32", "name": "decimals", - "type": "uint256" + "type": "uint32" } ], "name": "createFungibleToken", @@ -344,9 +344,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -425,14 +425,14 @@ "type": "tuple" }, { - "internalType": "uint256", + "internalType": "uint64", "name": "initialTotalSupply", - "type": "uint256" + "type": "uint64" }, { - "internalType": "uint256", + "internalType": "uint32", "name": "decimals", - "type": "uint256" + "type": "uint32" }, { "components": [ @@ -550,9 +550,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -677,9 +677,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -1075,9 +1075,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -1357,9 +1357,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", @@ -1866,9 +1866,9 @@ "type": "bool" }, { - "internalType": "uint32", + "internalType": "int64", "name": "maxSupply", - "type": "uint32" + "type": "int64" }, { "internalType": "bool", diff --git a/packages/server/tests/contracts/IHederaTokenService.sol b/packages/server/tests/contracts/IHederaTokenService.sol index 389a5393a2..da5786b88b 100644 --- a/packages/server/tests/contracts/IHederaTokenService.sol +++ b/packages/server/tests/contracts/IHederaTokenService.sol @@ -140,7 +140,7 @@ interface IHederaTokenService { // IWA Compatibility. Depends on TokenSupplyType. For tokens of type FUNGIBLE_COMMON - the // maximum number of tokens that can be in circulation. For tokens of type NON_FUNGIBLE_UNIQUE - // the maximum number of NFTs (serial numbers) that can be minted. This field can never be changed! - uint32 maxSupply; + int64 maxSupply; // The default Freeze status (frozen or unfrozen) of Hedera accounts relative to this token. If // true, an account must be unfrozen before it can receive the token @@ -359,8 +359,8 @@ interface IHederaTokenService { /// @return tokenAddress the created token's address function createFungibleToken( HederaToken memory token, - uint initialTotalSupply, - uint decimals) + uint64 initialTotalSupply, + uint32 decimals) external payable returns (int responseCode, address tokenAddress); /// Creates a Fungible Token with the specified properties @@ -374,8 +374,8 @@ interface IHederaTokenService { /// @return tokenAddress the created token's address function createFungibleTokenWithCustomFees( HederaToken memory token, - uint initialTotalSupply, - uint decimals, + uint64 initialTotalSupply, + uint32 decimals, FixedFee[] memory fixedFees, FractionalFee[] memory fractionalFees) external payable returns (int responseCode, address tokenAddress); diff --git a/packages/server/tests/contracts/contracts_v1/BaseHTS.json b/packages/server/tests/contracts/contracts_v1/BaseHTS.json new file mode 100644 index 0000000000..bd665ef9eb --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/BaseHTS.json @@ -0,0 +1,302 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BaseHTS", + "sourceName": "contracts_v1/BaseHTS.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "CreatedToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "name": "ResponseCode", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "associateTokenPublic", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "treasury", + "type": "address" + } + ], + "name": "createFungibleTokenPublic", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "address", + "name": "fixedFeeTokenAddress", + "type": "address" + } + ], + "name": "createFungibleTokenWithCustomFeesPublic", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "treasury", + "type": "address" + } + ], + "name": "createNonFungibleTokenPublic", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "kycGranted", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "name": "updateTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60c06040526009608081905268746f6b656e4e616d6560b81b60a09081526200002c9160019190620000cb565b5060408051808201909152600b8082526a1d1bdad95b94de5b589bdb60aa1b60209092019182526200006191600291620000cb565b50604080518082019091526004808252636d656d6f60e01b60209092019182526200008f91600391620000cb565b506103e860048190556005805463ffffffff1916909117905560086006556007805460ff19169055348015620000c457600080fd5b50620001ae565b828054620000d99062000171565b90600052602060002090601f016020900481019282620000fd576000855562000148565b82601f106200011857805160ff191683800117855562000148565b8280016001018555821562000148579182015b82811115620001485782518255916020019190600101906200012b565b50620001569291506200015a565b5090565b5b808211156200015657600081556001016200015b565b600181811c908216806200018657607f821691505b60208210811415620001a857634e487b7160e01b600052602260045260246000fd5b50919050565b61205480620001be6000396000f3fe6080604052600436106100bc5760003560e01c80638f8d7f9911610074578063d85f74c11161004e578063d85f74c1146101dd578063f2c31ff4146101f0578063f4a01e5b1461022a57600080fd5b80638f8d7f991461015c578063af99c6331461018f578063d614cdb8146101af57600080fd5b8063593d6e82116100a5578063593d6e82146101095780637c41ad2c146101295780638ba74da01461014957600080fd5b80633b3bff0f146100c15780634b5c6687146100f4575b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611982565b61024a565b6040519081526020015b60405180910390f35b610107610102366004611982565b61033d565b005b34801561011557600080fd5b506100e16101243660046119e8565b6106fd565b34801561013557600080fd5b506100e1610144366004611982565b6107da565b610107610157366004611a65565b610821565b34801561016857600080fd5b5061017c610177366004611a65565b610cc5565b60405160079190910b81526020016100eb565b34801561019b57600080fd5b5061017c6101aa366004611a65565b610d14565b3480156101bb57600080fd5b506101cf6101ca366004611982565b610d63565b6040516100eb929190611a9e565b6101076101eb366004611982565b610e86565b3480156101fc57600080fd5b5061021061020b366004611a65565b61121e565b6040805160079390930b83529015156020830152016100eb565b34801561023657600080fd5b506100e1610245366004611a65565b611302565b6040516001600160a01b038216602482015260009081908190610167907f3b3bff0f00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102cb9190611b08565b6000604051808303816000865af19150503d8060008114610308576040519150601f19603f3d011682016040523d82523d6000602084013e61030d565b606091505b50915091508161031e576015610332565b808060200190518101906103329190611b3b565b60030b949350505050565b60408051600480825260a08201909252600091816020015b61035d61190d565b8152602001906001900390816103555790505090506103906000600660016040518060200160405280600081525061135c565b816000815181106103a3576103a3611b56565b60200260200101819052506103c960018060405180602001604052806000815250611393565b816001815181106103dc576103dc611b56565b60200260200101819052506104036002600160405180602001604052806000815250611393565b8160028151811061041657610416611b56565b602002602001018190525061043d6003600160405180602001604052806000815250611393565b8160038151811061045057610450611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546104ae90611b6c565b80601f01602080910402602001604051908101604052809291908181526020018280546104da90611b6c565b80156105275780601f106104fc57610100808354040283529160200191610527565b820191906000526020600020905b81548152906001019060200180831161050a57829003601f168201915b505050505081526020016002805461053e90611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461056a90611b6c565b80156105b75780601f1061058c576101008083540402835291602001916105b7565b820191906000526020600020905b81548152906001019060200180831161059a57829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546105dd90611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461060990611b6c565b80156106565780601f1061062b57610100808354040283529160200191610656565b820191906000526020600020905b81548152906001019060200180831161063957829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905260045460065491925060009182916106a7918591906113c8565b9092509050601682146106b957600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b60008060006101676001600160a01b031663593d6e8260e01b8686604051602401610729929190611ba7565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516107679190611b08565b6000604051808303816000865af19150503d80600081146107a4576040519150601f19603f3d011682016040523d82523d6000602084013e6107a9565b606091505b5091509150816107ba5760156107ce565b808060200190518101906107ce9190611b3b565b60030b95945050505050565b6040516001600160a01b038216602482015260009081908190610167907f7c41ad2c000000000000000000000000000000000000000000000000000000009060440161028d565b604080516001808252818301909252600091816020015b61084061190d565b81526020019060019003908161083857905050905061087260008060016040518060200160405280600081525061135c565b8160008151811061088557610885611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546108e390611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461090f90611b6c565b801561095c5780601f106109315761010080835404028352916020019161095c565b820191906000526020600020905b81548152906001019060200180831161093f57829003601f168201915b505050505081526020016002805461097390611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461099f90611b6c565b80156109ec5780601f106109c1576101008083540402835291602001916109ec565b820191906000526020600020905b8154815290600101906020018083116109cf57829003601f168201915b50505050508152602001866001600160a01b0316815260200160038054610a1290611b6c565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3e90611b6c565b8015610a8b5780601f10610a6057610100808354040283529160200191610a8b565b820191906000526020600020905b815481529060010190602001808311610a6e57829003601f168201915b505050918352505060016020820181905260055463ffffffff166040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a081018252600080825260208083018290529282018190526060820181905260808201528252600019909201910181610adc5750506040805160a081018252600181526001600160a01b03888116602083015260009282018390526060820183905289166080820152825192935091839190610b5f57610b5f611b56565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a08201528252600019909201910181610b815750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a083015282519293509091839190610c1557610c15611b56565b6020026020010181905250600080610c348560045460065487876114f6565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c6991815260200190565b60405180910390a160168214610c7e57600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f8f8d7f990000000000000000000000000000000000000000000000000000000090606401610729565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907faf99c6330000000000000000000000000000000000000000000000000000000090606401610729565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b03167fd614cdb800000000000000000000000000000000000000000000000000000000179052925190928391829161016791610dee9190611b08565b6000604051808303816000865af19150503d8060008114610e2b576040519150601f19603f3d011682016040523d82523d6000602084013e610e30565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082610e6057601581610e74565b81806020019051810190610e749190611bea565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b610ea661190d565b815260200190600190039081610e9e579050509050610ed96000600660016040518060200160405280600081525061135c565b81600081518110610eec57610eec611b56565b6020026020010181905250610f1260018060405180602001604052806000815250611393565b81600181518110610f2557610f25611b56565b6020026020010181905250610f4c6002600160405180602001604052806000815250611393565b81600281518110610f5f57610f5f611b56565b6020026020010181905250610f866004600160405180602001604052806000815250611393565b81600381518110610f9957610f99611b56565b6020026020010181905250610fc06003600160405180602001604052806000815250611393565b81600481518110610fd357610fd3611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff16815250905060006040518061012001604052806001805461103190611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461105d90611b6c565b80156110aa5780601f1061107f576101008083540402835291602001916110aa565b820191906000526020600020905b81548152906001019060200180831161108d57829003601f168201915b50505050508152602001600280546110c190611b6c565b80601f01602080910402602001604051908101604052809291908181526020018280546110ed90611b6c565b801561113a5780601f1061110f5761010080835404028352916020019161113a565b820191906000526020600020905b81548152906001019060200180831161111d57829003601f168201915b50505050508152602001856001600160a01b031681526020016003805461116090611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461118c90611b6c565b80156111d95780601f106111ae576101008083540402835291602001916111d9565b820191906000526020600020905b8154815290600101906020018083116111bc57829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905290506000806106a78361162a565b604080516001600160a01b038481166024830152831660448083019190915282518083039091018152606490910182526020810180516001600160e01b03167ff2c31ff40000000000000000000000000000000000000000000000000000000017905290516000918291829182916101679161129991611b08565b6000604051808303816000865af19150503d80600081146112d6576040519150601f19603f3d011682016040523d82523d6000602084013e6112db565b606091505b5091509150816112ee5760156000610e74565b80806020019051810190610e749190611c55565b600061130e8383611740565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161134191815260200190565b60405180910390a16016811461135657600080fd5b92915050565b61136461190d565b6040518060400160405280611379878761178f565b815260200161138885856117ab565b905295945050505050565b61139b61190d565b60405180604001604052806113af8661187b565b81526020016113be85856117ab565b9052949350505050565b600080848061010001516000015163ffffffff1660001480156113f857506101008101516040015163ffffffff16155b1561140e576101008101516276a7006040909101525b6000806101676001600160a01b031634637812a04b60e01b8a8a8a60405160240161143b93929190611e79565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114799190611b08565b60006040518083038185875af1925050503d80600081146114b6576040519150601f19603f3d011682016040523d82523d6000602084013e6114bb565b606091505b5091509150816114ce57601560006114e2565b808060200190518101906114e29190611e9e565b60039190910b999098509650505050505050565b600080868061010001516000015163ffffffff16600014801561152657506101008101516040015163ffffffff16155b1561153c576101008101516276a7006040909101525b6000806101676001600160a01b031634634c381ae760e01b8c8c8c8c8c60405160240161156d959493929190611f53565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516115ab9190611b08565b60006040518083038185875af1925050503d80600081146115e8576040519150601f19603f3d011682016040523d82523d6000602084013e6115ed565b606091505b5091509150816116005760156000611614565b808060200190518101906116149190611e9e565b60039190910b9b909a5098505050505050505050565b600080828061010001516000015163ffffffff16600014801561165a57506101008101516040015163ffffffff16155b15611670576101008101516276a7006040909101525b6000806101676001600160a01b031634639dc711e060e01b88604051602401611699919061200b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516116d79190611b08565b60006040518083038185875af1925050503d8060008114611714576040519150601f19603f3d011682016040523d82523d6000602084013e611719565b606091505b50915091508161172c5760156000610e74565b80806020019051810190610e749190611e9e565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde0000000000000000000000000000000000000000000000000000000090606401610729565b6000600160ff84161b9050600160ff83161b81175b9392505050565b6117f16040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156118065760018152611356565b8260ff1660021415611828576000546001600160a01b03166020820152611356565b8260ff16600314156118405760408101829052611356565b8260ff16600414156118585760608101829052611356565b8260ff1660051415611356576000546001600160a01b0316608082015292915050565b600060ff821661188d57506001919050565b8160ff16600114156118a157506002919050565b8160ff16600214156118b557506004919050565b8160ff16600314156118c957506008919050565b8160ff16600414156118dd57506010919050565b8160ff16600514156118f157506020919050565b8160ff166006141561190557506040919050565b506000919050565b6040518060400160405280600081526020016119656040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6001600160a01b038116811461197f57600080fd5b50565b60006020828403121561199457600080fd5b81356117a48161196a565b6040516060810167ffffffffffffffff811182821017156119d057634e487b7160e01b600052604160045260246000fd5b60405290565b63ffffffff8116811461197f57600080fd5b60008082840360808112156119fc57600080fd5b8335611a078161196a565b92506060601f1982011215611a1b57600080fd5b50611a2461199f565b6020840135611a32816119d6565b81526040840135611a428161196a565b60208201526060840135611a55816119d6565b6040820152919491935090915050565b60008060408385031215611a7857600080fd5b8235611a838161196a565b91506020830135611a938161196a565b809150509250929050565b828152608081016117a46020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60005b83811015611af3578181015183820152602001611adb565b83811115611b02576000848401525b50505050565b60008251611b1a818460208701611ad8565b9190910192915050565b8051600381900b8114611b3657600080fd5b919050565b600060208284031215611b4d57600080fd5b6117a482611b24565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680611b8057607f821691505b60208210811415611ba157634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0383168152608081016117a46020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b6000808284036080811215611bfe57600080fd5b611c0784611b24565b92506060601f1982011215611c1b57600080fd5b50611c2461199f565b6020840151611c32816119d6565b81526040840151611c428161196a565b60208201526060840151611a55816119d6565b60008060408385031215611c6857600080fd5b611c7183611b24565b915060208301518015158114611a9357600080fd5b60008151808452611c9e816020860160208601611ad8565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015611d695782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152611d2b60e08b0186611c86565b928601518a8403603f1901858c0152929450611d478584611c86565b9501511660c09890980197909752505098850198935090840190600101611cd0565b5091979650505050505050565b60006101608251818552611d8c82860182611c86565b91505060208301518482036020860152611da68282611c86565b9150506040830151611dc360408601826001600160a01b03169052565b5060608301518482036060860152611ddb8282611c86565b9150506080830151611df1608086018215159052565b5060a0830151611e0960a086018263ffffffff169052565b5060c0830151611e1d60c086018215159052565b5060e083015184820360e0860152611e358282611cb2565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b606081526000611e8c6060830186611d76565b60208301949094525060400152919050565b60008060408385031215611eb157600080fd5b611eba83611b24565b91506020830151611a938161196a565b600081518084526020808501945080840160005b83811015611f48578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101611ede565b509495945050505050565b600060a0808352611f6681840189611d76565b60208881860152604088818701526060868403818801528389518086528486019150848b01955060005b81811015611fe6578651805163ffffffff168452868101516001600160a01b0390811688860152868201511515878601528582015115158686015260809182015116908401529585019591870191600101611f90565b50508781036080890152611ffa818a611eca565b9d9c50505050505050505050505050565b6020815260006117a46020830184611d7656fea2646970667358221220b2f08b6b5230ad3f15ae3442b41e373478b6b53f9ef05545b0dad522ab48f0fc64736f6c63430008090033", + "deployedBytecode": "0x6080604052600436106100bc5760003560e01c80638f8d7f9911610074578063d85f74c11161004e578063d85f74c1146101dd578063f2c31ff4146101f0578063f4a01e5b1461022a57600080fd5b80638f8d7f991461015c578063af99c6331461018f578063d614cdb8146101af57600080fd5b8063593d6e82116100a5578063593d6e82146101095780637c41ad2c146101295780638ba74da01461014957600080fd5b80633b3bff0f146100c15780634b5c6687146100f4575b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611982565b61024a565b6040519081526020015b60405180910390f35b610107610102366004611982565b61033d565b005b34801561011557600080fd5b506100e16101243660046119e8565b6106fd565b34801561013557600080fd5b506100e1610144366004611982565b6107da565b610107610157366004611a65565b610821565b34801561016857600080fd5b5061017c610177366004611a65565b610cc5565b60405160079190910b81526020016100eb565b34801561019b57600080fd5b5061017c6101aa366004611a65565b610d14565b3480156101bb57600080fd5b506101cf6101ca366004611982565b610d63565b6040516100eb929190611a9e565b6101076101eb366004611982565b610e86565b3480156101fc57600080fd5b5061021061020b366004611a65565b61121e565b6040805160079390930b83529015156020830152016100eb565b34801561023657600080fd5b506100e1610245366004611a65565b611302565b6040516001600160a01b038216602482015260009081908190610167907f3b3bff0f00000000000000000000000000000000000000000000000000000000906044015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102cb9190611b08565b6000604051808303816000865af19150503d8060008114610308576040519150601f19603f3d011682016040523d82523d6000602084013e61030d565b606091505b50915091508161031e576015610332565b808060200190518101906103329190611b3b565b60030b949350505050565b60408051600480825260a08201909252600091816020015b61035d61190d565b8152602001906001900390816103555790505090506103906000600660016040518060200160405280600081525061135c565b816000815181106103a3576103a3611b56565b60200260200101819052506103c960018060405180602001604052806000815250611393565b816001815181106103dc576103dc611b56565b60200260200101819052506104036002600160405180602001604052806000815250611393565b8160028151811061041657610416611b56565b602002602001018190525061043d6003600160405180602001604052806000815250611393565b8160038151811061045057610450611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546104ae90611b6c565b80601f01602080910402602001604051908101604052809291908181526020018280546104da90611b6c565b80156105275780601f106104fc57610100808354040283529160200191610527565b820191906000526020600020905b81548152906001019060200180831161050a57829003601f168201915b505050505081526020016002805461053e90611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461056a90611b6c565b80156105b75780601f1061058c576101008083540402835291602001916105b7565b820191906000526020600020905b81548152906001019060200180831161059a57829003601f168201915b50505050508152602001856001600160a01b03168152602001600380546105dd90611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461060990611b6c565b80156106565780601f1061062b57610100808354040283529160200191610656565b820191906000526020600020905b81548152906001019060200180831161063957829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905260045460065491925060009182916106a7918591906113c8565b9092509050601682146106b957600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b60008060006101676001600160a01b031663593d6e8260e01b8686604051602401610729929190611ba7565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516107679190611b08565b6000604051808303816000865af19150503d80600081146107a4576040519150601f19603f3d011682016040523d82523d6000602084013e6107a9565b606091505b5091509150816107ba5760156107ce565b808060200190518101906107ce9190611b3b565b60030b95945050505050565b6040516001600160a01b038216602482015260009081908190610167907f7c41ad2c000000000000000000000000000000000000000000000000000000009060440161028d565b604080516001808252818301909252600091816020015b61084061190d565b81526020019060019003908161083857905050905061087260008060016040518060200160405280600081525061135c565b8160008151811061088557610885611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001856001600160a01b03168152602001627a120063ffffffff1681525090506000604051806101200160405280600180546108e390611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461090f90611b6c565b801561095c5780601f106109315761010080835404028352916020019161095c565b820191906000526020600020905b81548152906001019060200180831161093f57829003601f168201915b505050505081526020016002805461097390611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461099f90611b6c565b80156109ec5780601f106109c1576101008083540402835291602001916109ec565b820191906000526020600020905b8154815290600101906020018083116109cf57829003601f168201915b50505050508152602001866001600160a01b0316815260200160038054610a1290611b6c565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3e90611b6c565b8015610a8b5780601f10610a6057610100808354040283529160200191610a8b565b820191906000526020600020905b815481529060010190602001808311610a6e57829003601f168201915b505050918352505060016020820181905260055463ffffffff166040808401919091526000606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a081018252600080825260208083018290529282018190526060820181905260808201528252600019909201910181610adc5750506040805160a081018252600181526001600160a01b03888116602083015260009282018390526060820183905289166080820152825192935091839190610b5f57610b5f611b56565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a08201528252600019909201910181610b815750506040805160c0810182526004815260056020820152600a91810191909152601e60608201526000608082018190526001600160a01b038a1660a083015282519293509091839190610c1557610c15611b56565b6020026020010181905250600080610c348560045460065487876114f6565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c6991815260200190565b60405180910390a160168214610c7e57600080fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f8f8d7f990000000000000000000000000000000000000000000000000000000090606401610729565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907faf99c6330000000000000000000000000000000000000000000000000000000090606401610729565b604080516060810182526000808252602080830182905282840182905283516001600160a01b038616602480830191909152855180830390910181526044909101855290810180516001600160e01b03167fd614cdb800000000000000000000000000000000000000000000000000000000179052925190928391829161016791610dee9190611b08565b6000604051808303816000865af19150503d8060008114610e2b576040519150601f19603f3d011682016040523d82523d6000602084013e610e30565b606091505b506040805160608101825260008082526020820181905291810191909152919350915082610e6057601581610e74565b81806020019051810190610e749190611bea565b60039190910b97909650945050505050565b60408051600580825260c08201909252600091816020015b610ea661190d565b815260200190600190039081610e9e579050509050610ed96000600660016040518060200160405280600081525061135c565b81600081518110610eec57610eec611b56565b6020026020010181905250610f1260018060405180602001604052806000815250611393565b81600181518110610f2557610f25611b56565b6020026020010181905250610f4c6002600160405180602001604052806000815250611393565b81600281518110610f5f57610f5f611b56565b6020026020010181905250610f866004600160405180602001604052806000815250611393565b81600381518110610f9957610f99611b56565b6020026020010181905250610fc06003600160405180602001604052806000815250611393565b81600481518110610fd357610fd3611b56565b602002602001018190525060006040518060600160405280600063ffffffff168152602001846001600160a01b03168152602001627a120063ffffffff16815250905060006040518061012001604052806001805461103190611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461105d90611b6c565b80156110aa5780601f1061107f576101008083540402835291602001916110aa565b820191906000526020600020905b81548152906001019060200180831161108d57829003601f168201915b50505050508152602001600280546110c190611b6c565b80601f01602080910402602001604051908101604052809291908181526020018280546110ed90611b6c565b801561113a5780601f1061110f5761010080835404028352916020019161113a565b820191906000526020600020905b81548152906001019060200180831161111d57829003601f168201915b50505050508152602001856001600160a01b031681526020016003805461116090611b6c565b80601f016020809104026020016040519081016040528092919081815260200182805461118c90611b6c565b80156111d95780601f106111ae576101008083540402835291602001916111d9565b820191906000526020600020905b8154815290600101906020018083116111bc57829003601f168201915b50505091835250506001602082015260055463ffffffff16604082015260075460ff16151560608201526080810185905260a00183905290506000806106a78361162a565b604080516001600160a01b038481166024830152831660448083019190915282518083039091018152606490910182526020810180516001600160e01b03167ff2c31ff40000000000000000000000000000000000000000000000000000000017905290516000918291829182916101679161129991611b08565b6000604051808303816000865af19150503d80600081146112d6576040519150601f19603f3d011682016040523d82523d6000602084013e6112db565b606091505b5091509150816112ee5760156000610e74565b80806020019051810190610e749190611c55565b600061130e8383611740565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161134191815260200190565b60405180910390a16016811461135657600080fd5b92915050565b61136461190d565b6040518060400160405280611379878761178f565b815260200161138885856117ab565b905295945050505050565b61139b61190d565b60405180604001604052806113af8661187b565b81526020016113be85856117ab565b9052949350505050565b600080848061010001516000015163ffffffff1660001480156113f857506101008101516040015163ffffffff16155b1561140e576101008101516276a7006040909101525b6000806101676001600160a01b031634637812a04b60e01b8a8a8a60405160240161143b93929190611e79565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114799190611b08565b60006040518083038185875af1925050503d80600081146114b6576040519150601f19603f3d011682016040523d82523d6000602084013e6114bb565b606091505b5091509150816114ce57601560006114e2565b808060200190518101906114e29190611e9e565b60039190910b999098509650505050505050565b600080868061010001516000015163ffffffff16600014801561152657506101008101516040015163ffffffff16155b1561153c576101008101516276a7006040909101525b6000806101676001600160a01b031634634c381ae760e01b8c8c8c8c8c60405160240161156d959493929190611f53565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516115ab9190611b08565b60006040518083038185875af1925050503d80600081146115e8576040519150601f19603f3d011682016040523d82523d6000602084013e6115ed565b606091505b5091509150816116005760156000611614565b808060200190518101906116149190611e9e565b60039190910b9b909a5098505050505050505050565b600080828061010001516000015163ffffffff16600014801561165a57506101008101516040015163ffffffff16155b15611670576101008101516276a7006040909101525b6000806101676001600160a01b031634639dc711e060e01b88604051602401611699919061200b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516116d79190611b08565b60006040518083038185875af1925050503d8060008114611714576040519150601f19603f3d011682016040523d82523d6000602084013e611719565b606091505b50915091508161172c5760156000610e74565b80806020019051810190610e749190611e9e565b6040516001600160a01b0383811660248301528216604482015260009081908190610167907f49146bde0000000000000000000000000000000000000000000000000000000090606401610729565b6000600160ff84161b9050600160ff83161b81175b9392505050565b6117f16040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b8260ff16600114156118065760018152611356565b8260ff1660021415611828576000546001600160a01b03166020820152611356565b8260ff16600314156118405760408101829052611356565b8260ff16600414156118585760608101829052611356565b8260ff1660051415611356576000546001600160a01b0316608082015292915050565b600060ff821661188d57506001919050565b8160ff16600114156118a157506002919050565b8160ff16600214156118b557506004919050565b8160ff16600314156118c957506008919050565b8160ff16600414156118dd57506010919050565b8160ff16600514156118f157506020919050565b8160ff166006141561190557506040919050565b506000919050565b6040518060400160405280600081526020016119656040518060a0016040528060001515815260200160006001600160a01b03168152602001606081526020016060815260200160006001600160a01b031681525090565b905290565b6001600160a01b038116811461197f57600080fd5b50565b60006020828403121561199457600080fd5b81356117a48161196a565b6040516060810167ffffffffffffffff811182821017156119d057634e487b7160e01b600052604160045260246000fd5b60405290565b63ffffffff8116811461197f57600080fd5b60008082840360808112156119fc57600080fd5b8335611a078161196a565b92506060601f1982011215611a1b57600080fd5b50611a2461199f565b6020840135611a32816119d6565b81526040840135611a428161196a565b60208201526060840135611a55816119d6565b6040820152919491935090915050565b60008060408385031215611a7857600080fd5b8235611a838161196a565b91506020830135611a938161196a565b809150509250929050565b828152608081016117a46020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b60005b83811015611af3578181015183820152602001611adb565b83811115611b02576000848401525b50505050565b60008251611b1a818460208701611ad8565b9190910192915050565b8051600381900b8114611b3657600080fd5b919050565b600060208284031215611b4d57600080fd5b6117a482611b24565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680611b8057607f821691505b60208210811415611ba157634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0383168152608081016117a46020830184805163ffffffff90811683526020808301516001600160a01b03169084015260409182015116910152565b6000808284036080811215611bfe57600080fd5b611c0784611b24565b92506060601f1982011215611c1b57600080fd5b50611c2461199f565b6020840151611c32816119d6565b81526040840151611c428161196a565b60208201526060840151611a55816119d6565b60008060408385031215611c6857600080fd5b611c7183611b24565b915060208301518015158114611a9357600080fd5b60008151808452611c9e816020860160208601611ad8565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015611d695782840389528151604081518652868201519150808787015281511515818701528682015160606001600160a01b03808316828a015283850151935060a09250608083818b0152611d2b60e08b0186611c86565b928601518a8403603f1901858c0152929450611d478584611c86565b9501511660c09890980197909752505098850198935090840190600101611cd0565b5091979650505050505050565b60006101608251818552611d8c82860182611c86565b91505060208301518482036020860152611da68282611c86565b9150506040830151611dc360408601826001600160a01b03169052565b5060608301518482036060860152611ddb8282611c86565b9150506080830151611df1608086018215159052565b5060a0830151611e0960a086018263ffffffff169052565b5060c0830151611e1d60c086018215159052565b5060e083015184820360e0860152611e358282611cb2565b61010085810151805163ffffffff9081168984015260208201516001600160a01b03166101208a015260408201511661014089015291935091505090949350505050565b606081526000611e8c6060830186611d76565b60208301949094525060400152919050565b60008060408385031215611eb157600080fd5b611eba83611b24565b91506020830151611a938161196a565b600081518084526020808501945080840160005b83811015611f48578151805163ffffffff9081168952848201518116858a01526040808301518216908a01526060808301519091169089015260808082015115159089015260a0908101516001600160a01b03169088015260c09096019590820190600101611ede565b509495945050505050565b600060a0808352611f6681840189611d76565b60208881860152604088818701526060868403818801528389518086528486019150848b01955060005b81811015611fe6578651805163ffffffff168452868101516001600160a01b0390811688860152868201511515878601528582015115158686015260809182015116908401529585019591870191600101611f90565b50508781036080890152611ffa818a611eca565b9d9c50505050505050505050505050565b6020815260006117a46020830184611d7656fea2646970667358221220b2f08b6b5230ad3f15ae3442b41e373478b6b53f9ef05545b0dad522ab48f0fc64736f6c63430008090033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/BaseHTS.sol b/packages/server/tests/contracts/contracts_v1/BaseHTS.sol new file mode 100644 index 0000000000..ff24da5d1e --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/BaseHTS.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./FeeHelper.sol"; + +contract BaseHTS is FeeHelper { + + string name = "tokenName"; + string symbol = "tokenSymbol"; + string memo = "memo"; + uint initialTotalSupply = 1000; + uint32 maxSupply = 1000; + uint decimals = 8; + bool freezeDefaultStatus = false; + + event CreatedToken(address tokenAddress); + event ResponseCode(int responseCode); + + function createFungibleTokenPublic( + address treasury + ) public payable { + IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](4); + keys[0] = getSingleKey(0, 6, 1, bytes("")); + keys[1] = getSingleKey(1, 1, bytes("")); + keys[2] = getSingleKey(2, 1, bytes("")); + keys[3] = getSingleKey(3, 1, bytes("")); + + IHederaTokenService.Expiry memory expiry = IHederaTokenService.Expiry( + 0, treasury, 8000000 + ); + + IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( + name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + ); + + (int responseCode, address tokenAddress) = + HederaTokenService.createFungibleToken(token, initialTotalSupply, decimals); + + if (responseCode != HederaResponseCodes.SUCCESS) { + revert (); + } + + emit CreatedToken(tokenAddress); + } + + function createNonFungibleTokenPublic( + address treasury + ) public payable { + IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](5); + keys[0] = getSingleKey(0, 6, 1, bytes("")); + keys[1] = getSingleKey(1, 1, bytes("")); + keys[2] = getSingleKey(2, 1, bytes("")); + keys[3] = getSingleKey(4, 1, bytes("")); + keys[4] = getSingleKey(3, 1, bytes("")); + + IHederaTokenService.Expiry memory expiry = IHederaTokenService.Expiry( + 0, treasury, 8000000 + ); + + IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( + name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + ); + + (int responseCode, address tokenAddress) = + HederaTokenService.createNonFungibleToken(token); + + if (responseCode != HederaResponseCodes.SUCCESS) { + revert (); + } + + emit CreatedToken(tokenAddress); + } + + function associateTokenPublic(address account, address token) public returns (int responseCode) { + responseCode = HederaTokenService.associateToken(account, token); + emit ResponseCode(responseCode); + if (responseCode != HederaResponseCodes.SUCCESS) { + revert (); + } + } + + function createFungibleTokenWithCustomFeesPublic( + address treasury, + address fixedFeeTokenAddress + ) public payable { + IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1); + keys[0] = getSingleKey(0, 0, 1, bytes("")); + + IHederaTokenService.Expiry memory expiry = IHederaTokenService.Expiry( + 0, treasury, 8000000 + ); + + IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( + name, symbol, treasury, memo, true, maxSupply, false, keys, expiry + ); + + IHederaTokenService.FixedFee[] memory fixedFees = new IHederaTokenService.FixedFee[](1); + fixedFees[0] = IHederaTokenService.FixedFee(1, fixedFeeTokenAddress, false, false, treasury); + + IHederaTokenService.FractionalFee[] memory fractionalFees = new IHederaTokenService.FractionalFee[](1); + fractionalFees[0] = IHederaTokenService.FractionalFee(4, 5, 10, 30, false, treasury); + + (int responseCode, address tokenAddress) = + HederaTokenService.createFungibleTokenWithCustomFees(token, initialTotalSupply, decimals, fixedFees, fractionalFees); + emit ResponseCode(responseCode); + + if (responseCode != HederaResponseCodes.SUCCESS) { + revert (); + } + + emit CreatedToken(tokenAddress); + } +} \ No newline at end of file diff --git a/packages/server/tests/contracts/contracts_v1/ERC20Mock.json b/packages/server/tests/contracts/contracts_v1/ERC20Mock.json new file mode 100644 index 0000000000..a9dfb2e810 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/ERC20Mock.json @@ -0,0 +1,389 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ERC20Mock", + "sourceName": "contracts/mocks/ERC20Mock.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "initialAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405260405162000f7038038062000f708339810160408190526200002691620002cf565b8351849084906200003f9060039060208501906200015c565b508051620000559060049060208401906200015c565b5050506200006a82826200007460201b60201c565b50505050620003c5565b6001600160a01b038216620000cf5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b8060026000828254620000e3919062000362565b90915550506001600160a01b038216600090815260208190526040812080548392906200011290849062000362565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b8280546200016a9062000389565b90600052602060002090601f0160209004810192826200018e5760008555620001d9565b82601f10620001a957805160ff1916838001178555620001d9565b82800160010185558215620001d9579182015b82811115620001d9578251825591602001919060010190620001bc565b50620001e7929150620001eb565b5090565b5b80821115620001e75760008155600101620001ec565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200022a57600080fd5b81516001600160401b038082111562000247576200024762000202565b604051601f8301601f19908116603f0116810190828211818310171562000272576200027262000202565b816040528381526020925086838588010111156200028f57600080fd5b600091505b83821015620002b3578582018301518183018401529082019062000294565b83821115620002c55760008385830101525b9695505050505050565b60008060008060808587031215620002e657600080fd5b84516001600160401b0380821115620002fe57600080fd5b6200030c8883890162000218565b955060208701519150808211156200032357600080fd5b50620003328782880162000218565b604087015190945090506001600160a01b03811681146200035257600080fd5b6060959095015193969295505050565b600082198211156200038457634e487b7160e01b600052601160045260246000fd5b500190565b600181811c908216806200039e57607f821691505b602082108103620003bf57634e487b7160e01b600052602260045260246000fd5b50919050565b610b9b80620003d56000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f19116100975780639dc29fac116100665780639dc29fac146101ee578063a457c2d714610201578063a9059cbb14610214578063dd62ed3e1461022757600080fd5b806340c10f191461019757806356189cb4146101aa57806370a08231146101bd57806395d89b41146101e657600080fd5b8063222f5be0116100d3578063222f5be01461014d57806323b872dd14610162578063313ce56714610175578063395093511461018457600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b61010261023a565b60405161010f91906109ba565b60405180910390f35b61012b610126366004610a2b565b6102cc565b604051901515815260200161010f565b6002545b60405190815260200161010f565b61016061015b366004610a55565b6102e4565b005b61012b610170366004610a55565b6102f4565b6040516012815260200161010f565b61012b610192366004610a2b565b610318565b6101606101a5366004610a2b565b61033a565b6101606101b8366004610a55565b610348565b61013f6101cb366004610a91565b6001600160a01b031660009081526020819052604090205490565b610102610353565b6101606101fc366004610a2b565b610362565b61012b61020f366004610a2b565b61036c565b61012b610222366004610a2b565b6103ec565b61013f610235366004610ab3565b6103fa565b60606003805461024990610ae6565b80601f016020809104026020016040519081016040528092919081815260200182805461027590610ae6565b80156102c25780601f10610297576101008083540402835291602001916102c2565b820191906000526020600020905b8154815290600101906020018083116102a557829003601f168201915b5050505050905090565b6000336102da818585610425565b5060019392505050565b6102ef838383610549565b505050565b600033610302858285610719565b61030d858585610549565b506001949350505050565b6000336102da81858561032b83836103fa565b6103359190610b36565b610425565b610344828261078d565b5050565b6102ef838383610425565b60606004805461024990610ae6565b610344828261086c565b6000338161037a82866103fa565b9050838110156103df5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b61030d8286868403610425565b6000336102da818585610549565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104875760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103d6565b6001600160a01b0382166104e85760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103d6565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166105ad5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103d6565b6001600160a01b03821661060f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103d6565b6001600160a01b038316600090815260208190526040902054818110156106875760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103d6565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106be908490610b36565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161070a91815260200190565b60405180910390a35b50505050565b600061072584846103fa565b9050600019811461071357818110156107805760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103d6565b6107138484848403610425565b6001600160a01b0382166107e35760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103d6565b80600260008282546107f59190610b36565b90915550506001600160a01b03821660009081526020819052604081208054839290610822908490610b36565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166108cc5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103d6565b6001600160a01b038216600090815260208190526040902054818110156109405760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016103d6565b6001600160a01b038316600090815260208190526040812083830390556002805484929061096f908490610b4e565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600060208083528351808285015260005b818110156109e7578581018301518582016040015282016109cb565b818111156109f9576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a2657600080fd5b919050565b60008060408385031215610a3e57600080fd5b610a4783610a0f565b946020939093013593505050565b600080600060608486031215610a6a57600080fd5b610a7384610a0f565b9250610a8160208501610a0f565b9150604084013590509250925092565b600060208284031215610aa357600080fd5b610aac82610a0f565b9392505050565b60008060408385031215610ac657600080fd5b610acf83610a0f565b9150610add60208401610a0f565b90509250929050565b600181811c90821680610afa57607f821691505b602082108103610b1a57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610b4957610b49610b20565b500190565b600082821015610b6057610b60610b20565b50039056fea264697066735822122062e84cb8f44c4c035bb08b344b04b097859a13109c006676ce804cd4dee3465b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806340c10f19116100975780639dc29fac116100665780639dc29fac146101ee578063a457c2d714610201578063a9059cbb14610214578063dd62ed3e1461022757600080fd5b806340c10f191461019757806356189cb4146101aa57806370a08231146101bd57806395d89b41146101e657600080fd5b8063222f5be0116100d3578063222f5be01461014d57806323b872dd14610162578063313ce56714610175578063395093511461018457600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b61010261023a565b60405161010f91906109ba565b60405180910390f35b61012b610126366004610a2b565b6102cc565b604051901515815260200161010f565b6002545b60405190815260200161010f565b61016061015b366004610a55565b6102e4565b005b61012b610170366004610a55565b6102f4565b6040516012815260200161010f565b61012b610192366004610a2b565b610318565b6101606101a5366004610a2b565b61033a565b6101606101b8366004610a55565b610348565b61013f6101cb366004610a91565b6001600160a01b031660009081526020819052604090205490565b610102610353565b6101606101fc366004610a2b565b610362565b61012b61020f366004610a2b565b61036c565b61012b610222366004610a2b565b6103ec565b61013f610235366004610ab3565b6103fa565b60606003805461024990610ae6565b80601f016020809104026020016040519081016040528092919081815260200182805461027590610ae6565b80156102c25780601f10610297576101008083540402835291602001916102c2565b820191906000526020600020905b8154815290600101906020018083116102a557829003601f168201915b5050505050905090565b6000336102da818585610425565b5060019392505050565b6102ef838383610549565b505050565b600033610302858285610719565b61030d858585610549565b506001949350505050565b6000336102da81858561032b83836103fa565b6103359190610b36565b610425565b610344828261078d565b5050565b6102ef838383610425565b60606004805461024990610ae6565b610344828261086c565b6000338161037a82866103fa565b9050838110156103df5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b61030d8286868403610425565b6000336102da818585610549565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104875760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103d6565b6001600160a01b0382166104e85760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103d6565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166105ad5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103d6565b6001600160a01b03821661060f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103d6565b6001600160a01b038316600090815260208190526040902054818110156106875760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103d6565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106be908490610b36565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161070a91815260200190565b60405180910390a35b50505050565b600061072584846103fa565b9050600019811461071357818110156107805760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103d6565b6107138484848403610425565b6001600160a01b0382166107e35760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103d6565b80600260008282546107f59190610b36565b90915550506001600160a01b03821660009081526020819052604081208054839290610822908490610b36565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166108cc5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103d6565b6001600160a01b038216600090815260208190526040902054818110156109405760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016103d6565b6001600160a01b038316600090815260208190526040812083830390556002805484929061096f908490610b4e565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600060208083528351808285015260005b818110156109e7578581018301518582016040015282016109cb565b818111156109f9576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114610a2657600080fd5b919050565b60008060408385031215610a3e57600080fd5b610a4783610a0f565b946020939093013593505050565b600080600060608486031215610a6a57600080fd5b610a7384610a0f565b9250610a8160208501610a0f565b9150604084013590509250925092565b600060208284031215610aa357600080fd5b610aac82610a0f565b9392505050565b60008060408385031215610ac657600080fd5b610acf83610a0f565b9150610add60208401610a0f565b90509250929050565b600181811c90821680610afa57607f821691505b602082108103610b1a57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610b4957610b49610b20565b500190565b600082821015610b6057610b60610b20565b50039056fea264697066735822122062e84cb8f44c4c035bb08b344b04b097859a13109c006676ce804cd4dee3465b64736f6c634300080d0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/FeeHelper.json b/packages/server/tests/contracts/contracts_v1/FeeHelper.json new file mode 100644 index 0000000000..5fc885d922 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/FeeHelper.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "FeeHelper", + "sourceName": "contracts/FeeHelper.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/FeeHelper.sol b/packages/server/tests/contracts/contracts_v1/FeeHelper.sol new file mode 100644 index 0000000000..7753962d34 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/FeeHelper.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./HederaTokenService.sol"; +import "./HederaResponseCodes.sol"; +import "./IHederaTokenService.sol"; +import "./KeyHelper.sol"; + +abstract contract FeeHelper is KeyHelper { + + function createNAmountFixedFeesForHbars(uint8 numberOfFees, uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](numberOfFees); + + for(uint8 i = 0; i < numberOfFees; i++) { + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeForHbars(amount, feeCollector); + fixedFees[i] = fixedFee; + } + } + + function createSingleFixedFeeForToken(uint32 amount, address tokenId, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeForToken(amount, tokenId, feeCollector); + fixedFees[0] = fixedFee; + } + + function createFixedFeesForToken(uint32 amount, address tokenId, address firstFeeCollector, address secondFeeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee1 = createFixedFeeForToken(amount, tokenId, firstFeeCollector); + IHederaTokenService.FixedFee memory fixedFee2 = createFixedFeeForToken(2*amount, tokenId, secondFeeCollector); + fixedFees[0] = fixedFee1; + fixedFees[0] = fixedFee2; + } + + function createSingleFixedFeeForHbars(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeForHbars(amount, feeCollector); + fixedFees[0] = fixedFee; + } + + function createSingleFixedFeeForCurrentToken(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeForCurrentToken(amount, feeCollector); + fixedFees[0] = fixedFee; + } + + function createSingleFixedFeeWithInvalidFlags(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeWithInvalidFlags(amount, feeCollector); + fixedFees[0] = fixedFee; + } + + function createSingleFixedFeeWithTokenIdAndHbars(uint32 amount, address tokenId, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](1); + IHederaTokenService.FixedFee memory fixedFee = createFixedFeeWithTokenIdAndHbars(amount, tokenId, feeCollector); + fixedFees[0] = fixedFee; + } + + function createFixedFeesWithAllTypes(uint32 amount, address tokenId, address feeCollector) internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) { + fixedFees = new IHederaTokenService.FixedFee[](3); + IHederaTokenService.FixedFee memory fixedFeeForToken = createFixedFeeForToken(amount, tokenId, feeCollector); + IHederaTokenService.FixedFee memory fixedFeeForHbars = createFixedFeeForHbars(amount*2, feeCollector); + IHederaTokenService.FixedFee memory fixedFeeForCurrentToken = createFixedFeeForCurrentToken(amount*4, feeCollector); + fixedFees[0] = fixedFeeForToken; + fixedFees[1] = fixedFeeForHbars; + fixedFees[2] = fixedFeeForCurrentToken; + } + + function createFixedFeeForToken(uint32 amount, address tokenId, address feeCollector) internal pure returns (IHederaTokenService.FixedFee memory fixedFee) { + fixedFee.amount = amount; + fixedFee.tokenId = tokenId; + fixedFee.feeCollector = feeCollector; + } + + function createFixedFeeForHbars(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee memory fixedFee) { + fixedFee.amount = amount; + fixedFee.useHbarsForPayment = true; + fixedFee.feeCollector = feeCollector; + } + + function createFixedFeeForCurrentToken(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee memory fixedFee) { + fixedFee.amount = amount; + fixedFee.useCurrentTokenForPayment = true; + fixedFee.feeCollector = feeCollector; + } + + //Used for negative scenarios + function createFixedFeeWithInvalidFlags(uint32 amount, address feeCollector) internal pure returns (IHederaTokenService.FixedFee memory fixedFee) { + fixedFee.amount = amount; + fixedFee.useHbarsForPayment = true; + fixedFee.useCurrentTokenForPayment = true; + fixedFee.feeCollector = feeCollector; + } + + //Used for negative scenarios + function createFixedFeeWithTokenIdAndHbars(uint32 amount, address tokenId, address feeCollector) internal pure returns (IHederaTokenService.FixedFee memory fixedFee) { + fixedFee.amount = amount; + fixedFee.tokenId = tokenId; + fixedFee.useHbarsForPayment = true; + fixedFee.feeCollector = feeCollector; + } + + function getEmptyFixedFees() internal pure returns (IHederaTokenService.FixedFee[] memory fixedFees) {} + + function createNAmountFractionalFees(uint8 numberOfFees, uint32 numerator, uint32 denominator, + bool netOfTransfers, address feeCollector) internal pure returns (IHederaTokenService.FractionalFee[] memory fractionalFees) { + fractionalFees = new IHederaTokenService.FractionalFee[](numberOfFees); + + for(uint8 i = 0; i < numberOfFees; i++) { + IHederaTokenService.FractionalFee memory fractionalFee = createFractionalFee(numerator, denominator, netOfTransfers, feeCollector); + fractionalFees[i] = fractionalFee; + } + } + + function createSingleFractionalFee(uint32 numerator, uint32 denominator, + bool netOfTransfers, address feeCollector) internal pure returns (IHederaTokenService.FractionalFee[] memory fractionalFees) { + fractionalFees = new IHederaTokenService.FractionalFee[](1); + IHederaTokenService.FractionalFee memory fractionalFee = createFractionalFee(numerator, denominator, netOfTransfers, feeCollector); + fractionalFees[0] = fractionalFee; + } + + function createSingleFractionalFeeWithLimits(uint32 numerator, uint32 denominator, uint32 minimumAmount, uint32 maximumAmount, + bool netOfTransfers, address feeCollector) internal pure returns (IHederaTokenService.FractionalFee[] memory fractionalFees) { + fractionalFees = new IHederaTokenService.FractionalFee[](1); + IHederaTokenService.FractionalFee memory fractionalFee = createFractionalFeeWithLimits(numerator, denominator, minimumAmount, maximumAmount, netOfTransfers, feeCollector); + fractionalFees[0] = fractionalFee; + } + + function createFractionalFee(uint32 numerator, uint32 denominator, + bool netOfTransfers, address feeCollector) internal pure returns (IHederaTokenService.FractionalFee memory fractionalFee) { + fractionalFee.numerator = numerator; + fractionalFee.denominator = denominator; + fractionalFee.netOfTransfers = netOfTransfers; + fractionalFee.feeCollector = feeCollector; + } + + function createFractionalFeeWithLimits(uint32 numerator, uint32 denominator, uint32 minimumAmount, uint32 maximumAmount, + bool netOfTransfers, address feeCollector) internal pure returns (IHederaTokenService.FractionalFee memory fractionalFee) { + fractionalFee.numerator = numerator; + fractionalFee.denominator = denominator; + fractionalFee.minimumAmount = minimumAmount; + fractionalFee.maximumAmount = maximumAmount; + fractionalFee.netOfTransfers = netOfTransfers; + fractionalFee.feeCollector = feeCollector; + } + + function getEmptyFractionalFees() internal pure returns (IHederaTokenService.FractionalFee[] memory fractionalFees) { + fractionalFees = new IHederaTokenService.FractionalFee[](0); + } + + function createNAmountRoyaltyFees(uint8 numberOfFees, uint32 numerator, uint32 denominator, + address feeCollector) internal pure returns (IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + royaltyFees = new IHederaTokenService.RoyaltyFee[](numberOfFees); + + for(uint8 i = 0; i < numberOfFees; i++) { + IHederaTokenService.RoyaltyFee memory royaltyFee = createRoyaltyFee(numerator, denominator, feeCollector); + royaltyFees[i] = royaltyFee; + } + } + + function getEmptyRoyaltyFees() internal pure returns (IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + royaltyFees = new IHederaTokenService.RoyaltyFee[](0); + } + + function createSingleRoyaltyFee(uint32 numerator, uint32 denominator, address feeCollector) internal pure returns (IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + royaltyFees = new IHederaTokenService.RoyaltyFee[](1); + + IHederaTokenService.RoyaltyFee memory royaltyFee = createRoyaltyFee(numerator, denominator, feeCollector); + royaltyFees[0] = royaltyFee; + } + + function createSingleRoyaltyFeeWithFallbackFee(uint32 numerator, uint32 denominator, uint32 amount, address tokenId, bool useHbarsForPayment, + address feeCollector) internal pure returns (IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + royaltyFees = new IHederaTokenService.RoyaltyFee[](1); + + IHederaTokenService.RoyaltyFee memory royaltyFee = createRoyaltyFeeWithFallbackFee(numerator, denominator, amount, tokenId, useHbarsForPayment, feeCollector); + royaltyFees[0] = royaltyFee; + } + + function createRoyaltyFeesWithAllTypes( + uint32 numerator, + uint32 denominator, + uint32 amount, + address tokenId, + address feeCollector) + internal pure returns (IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + royaltyFees = new IHederaTokenService.RoyaltyFee[](3); + IHederaTokenService.RoyaltyFee memory royaltyFeeWithoutFallback = createRoyaltyFee(numerator, denominator, feeCollector); + IHederaTokenService.RoyaltyFee memory royaltyFeeWithFallbackHbar = createRoyaltyFeeWithFallbackFee(numerator, denominator, amount, address(0x0), true, feeCollector); + IHederaTokenService.RoyaltyFee memory royaltyFeeWithFallbackToken = createRoyaltyFeeWithFallbackFee(numerator, denominator, amount, tokenId, false, feeCollector); + royaltyFees[0] = royaltyFeeWithoutFallback; + royaltyFees[1] = royaltyFeeWithFallbackHbar; + royaltyFees[2] = royaltyFeeWithFallbackToken; + } + + function createRoyaltyFee(uint32 numerator, uint32 denominator, address feeCollector) internal pure returns (IHederaTokenService.RoyaltyFee memory royaltyFee) { + royaltyFee.numerator = numerator; + royaltyFee.denominator = denominator; + royaltyFee.feeCollector = feeCollector; + } + + function createRoyaltyFeeWithFallbackFee(uint32 numerator, uint32 denominator, uint32 amount, address tokenId, bool useHbarsForPayment, + address feeCollector) internal pure returns (IHederaTokenService.RoyaltyFee memory royaltyFee) { + royaltyFee.numerator = numerator; + royaltyFee.denominator = denominator; + royaltyFee.amount = amount; + royaltyFee.tokenId = tokenId; + royaltyFee.useHbarsForPayment = useHbarsForPayment; + royaltyFee.feeCollector = feeCollector; + } +} diff --git a/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.json b/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.json new file mode 100644 index 0000000000..bd8d81a741 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.json @@ -0,0 +1,10 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HederaResponseCodes", + "sourceName": "contracts/HederaResponseCodes.sol", + "abi": [], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.sol b/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.sol new file mode 100644 index 0000000000..59b73d1ebc --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/HederaResponseCodes.sol @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; + +abstract contract HederaResponseCodes { + + // response codes + int32 internal constant OK = 0; // The transaction passed the precheck validations. + int32 internal constant INVALID_TRANSACTION = 1; // For any error not handled by specific error codes listed below. + int32 internal constant PAYER_ACCOUNT_NOT_FOUND = 2; //Payer account does not exist. + int32 internal constant INVALID_NODE_ACCOUNT = 3; //Node Account provided does not match the node account of the node the transaction was submitted to. + int32 internal constant TRANSACTION_EXPIRED = 4; // Pre-Check error when TransactionValidStart + transactionValidDuration is less than current consensus time. + int32 internal constant INVALID_TRANSACTION_START = 5; // Transaction start time is greater than current consensus time + int32 internal constant INVALID_TRANSACTION_DURATION = 6; //valid transaction duration is a positive non zero number that does not exceed 120 seconds + int32 internal constant INVALID_SIGNATURE = 7; // The transaction signature is not valid + int32 internal constant MEMO_TOO_LONG = 8; //Transaction memo size exceeded 100 bytes + int32 internal constant INSUFFICIENT_TX_FEE = 9; // The fee provided in the transaction is insufficient for this type of transaction + int32 internal constant INSUFFICIENT_PAYER_BALANCE = 10; // The payer account has insufficient cryptocurrency to pay the transaction fee + int32 internal constant DUPLICATE_TRANSACTION = 11; // This transaction ID is a duplicate of one that was submitted to this node or reached consensus in the last 180 seconds (receipt period) + int32 internal constant BUSY = 12; //If API is throttled out + int32 internal constant NOT_SUPPORTED = 13; //The API is not currently supported + + int32 internal constant INVALID_FILE_ID = 14; //The file id is invalid or does not exist + int32 internal constant INVALID_ACCOUNT_ID = 15; //The account id is invalid or does not exist + int32 internal constant INVALID_CONTRACT_ID = 16; //The contract id is invalid or does not exist + int32 internal constant INVALID_TRANSACTION_ID = 17; //Transaction id is not valid + int32 internal constant RECEIPT_NOT_FOUND = 18; //Receipt for given transaction id does not exist + int32 internal constant RECORD_NOT_FOUND = 19; //Record for given transaction id does not exist + int32 internal constant INVALID_SOLIDITY_ID = 20; //The solidity id is invalid or entity with this solidity id does not exist + + int32 internal constant UNKNOWN = 21; // The responding node has submitted the transaction to the network. Its final status is still unknown. + int32 internal constant SUCCESS = 22; // The transaction succeeded + int32 internal constant FAIL_INVALID = 23; // There was a system error and the transaction failed because of invalid request parameters. + int32 internal constant FAIL_FEE = 24; // There was a system error while performing fee calculation, reserved for future. + int32 internal constant FAIL_BALANCE = 25; // There was a system error while performing balance checks, reserved for future. + + int32 internal constant KEY_REQUIRED = 26; //Key not provided in the transaction body + int32 internal constant BAD_ENCODING = 27; //Unsupported algorithm/encoding used for keys in the transaction + int32 internal constant INSUFFICIENT_ACCOUNT_BALANCE = 28; //When the account balance is not sufficient for the transfer + int32 internal constant INVALID_SOLIDITY_ADDRESS = 29; //During an update transaction when the system is not able to find the Users Solidity address + + int32 internal constant INSUFFICIENT_GAS = 30; //Not enough gas was supplied to execute transaction + int32 internal constant CONTRACT_SIZE_LIMIT_EXCEEDED = 31; //contract byte code size is over the limit + int32 internal constant LOCAL_CALL_MODIFICATION_EXCEPTION = 32; //local execution (query) is requested for a function which changes state + int32 internal constant CONTRACT_REVERT_EXECUTED = 33; //Contract REVERT OPCODE executed + int32 internal constant CONTRACT_EXECUTION_EXCEPTION = 34; //For any contract execution related error not handled by specific error codes listed above. + int32 internal constant INVALID_RECEIVING_NODE_ACCOUNT = 35; //In Query validation, account with +ve(amount) value should be Receiving node account, the receiver account should be only one account in the list + int32 internal constant MISSING_QUERY_HEADER = 36; // Header is missing in Query request + + int32 internal constant ACCOUNT_UPDATE_FAILED = 37; // The update of the account failed + int32 internal constant INVALID_KEY_ENCODING = 38; // Provided key encoding was not supported by the system + int32 internal constant NULL_SOLIDITY_ADDRESS = 39; // null solidity address + + int32 internal constant CONTRACT_UPDATE_FAILED = 40; // update of the contract failed + int32 internal constant INVALID_QUERY_HEADER = 41; // the query header is invalid + + int32 internal constant INVALID_FEE_SUBMITTED = 42; // Invalid fee submitted + int32 internal constant INVALID_PAYER_SIGNATURE = 43; // Payer signature is invalid + + int32 internal constant KEY_NOT_PROVIDED = 44; // The keys were not provided in the request. + int32 internal constant INVALID_EXPIRATION_TIME = 45; // Expiration time provided in the transaction was invalid. + int32 internal constant NO_WACL_KEY = 46; //WriteAccess Control Keys are not provided for the file + int32 internal constant FILE_CONTENT_EMPTY = 47; //The contents of file are provided as empty. + int32 internal constant INVALID_ACCOUNT_AMOUNTS = 48; // The crypto transfer credit and debit do not sum equal to 0 + int32 internal constant EMPTY_TRANSACTION_BODY = 49; // Transaction body provided is empty + int32 internal constant INVALID_TRANSACTION_BODY = 50; // Invalid transaction body provided + + int32 internal constant INVALID_SIGNATURE_TYPE_MISMATCHING_KEY = 51; // the type of key (base ed25519 key, KeyList, or ThresholdKey) does not match the type of signature (base ed25519 signature, SignatureList, or ThresholdKeySignature) + int32 internal constant INVALID_SIGNATURE_COUNT_MISMATCHING_KEY = 52; // the number of key (KeyList, or ThresholdKey) does not match that of signature (SignatureList, or ThresholdKeySignature). e.g. if a keyList has 3 base keys, then the corresponding signatureList should also have 3 base signatures. + + int32 internal constant EMPTY_LIVE_HASH_BODY = 53; // the livehash body is empty + int32 internal constant EMPTY_LIVE_HASH = 54; // the livehash data is missing + int32 internal constant EMPTY_LIVE_HASH_KEYS = 55; // the keys for a livehash are missing + int32 internal constant INVALID_LIVE_HASH_SIZE = 56; // the livehash data is not the output of a SHA-384 digest + + int32 internal constant EMPTY_QUERY_BODY = 57; // the query body is empty + int32 internal constant EMPTY_LIVE_HASH_QUERY = 58; // the crypto livehash query is empty + int32 internal constant LIVE_HASH_NOT_FOUND = 59; // the livehash is not present + int32 internal constant ACCOUNT_ID_DOES_NOT_EXIST = 60; // the account id passed has not yet been created. + int32 internal constant LIVE_HASH_ALREADY_EXISTS = 61; // the livehash already exists for a given account + + int32 internal constant INVALID_FILE_WACL = 62; // File WACL keys are invalid + int32 internal constant SERIALIZATION_FAILED = 63; // Serialization failure + int32 internal constant TRANSACTION_OVERSIZE = 64; // The size of the Transaction is greater than transactionMaxBytes + int32 internal constant TRANSACTION_TOO_MANY_LAYERS = 65; // The Transaction has more than 50 levels + int32 internal constant CONTRACT_DELETED = 66; //Contract is marked as deleted + + int32 internal constant PLATFORM_NOT_ACTIVE = 67; // the platform node is either disconnected or lagging behind. + int32 internal constant KEY_PREFIX_MISMATCH = 68; // one internal key matches more than one prefixes on the signature map + int32 internal constant PLATFORM_TRANSACTION_NOT_CREATED = 69; // transaction not created by platform due to large backlog + int32 internal constant INVALID_RENEWAL_PERIOD = 70; // auto renewal period is not a positive number of seconds + int32 internal constant INVALID_PAYER_ACCOUNT_ID = 71; // the response code when a smart contract id is passed for a crypto API request + int32 internal constant ACCOUNT_DELETED = 72; // the account has been marked as deleted + int32 internal constant FILE_DELETED = 73; // the file has been marked as deleted + int32 internal constant ACCOUNT_REPEATED_IN_ACCOUNT_AMOUNTS = 74; // same accounts repeated in the transfer account list + int32 internal constant SETTING_NEGATIVE_ACCOUNT_BALANCE = 75; // attempting to set negative balance value for crypto account + int32 internal constant OBTAINER_REQUIRED = 76; // when deleting smart contract that has crypto balance either transfer account or transfer smart contract is required + int32 internal constant OBTAINER_SAME_CONTRACT_ID = 77; //when deleting smart contract that has crypto balance you can not use the same contract id as transferContractId as the one being deleted + int32 internal constant OBTAINER_DOES_NOT_EXIST = 78; //transferAccountId or transferContractId specified for contract delete does not exist + int32 internal constant MODIFYING_IMMUTABLE_CONTRACT = 79; //attempting to modify (update or delete a immutable smart contract, i.e. one created without a admin key) + int32 internal constant FILE_SYSTEM_EXCEPTION = 80; //Unexpected exception thrown by file system functions + int32 internal constant AUTORENEW_DURATION_NOT_IN_RANGE = 81; // the duration is not a subset of [MINIMUM_AUTORENEW_DURATION,MAXIMUM_AUTORENEW_DURATION] + int32 internal constant ERROR_DECODING_BYTESTRING = 82; // Decoding the smart contract binary to a byte array failed. Check that the input is a valid hex string. + int32 internal constant CONTRACT_FILE_EMPTY = 83; // File to create a smart contract was of length zero + int32 internal constant CONTRACT_BYTECODE_EMPTY = 84; // Bytecode for smart contract is of length zero + int32 internal constant INVALID_INITIAL_BALANCE = 85; // Attempt to set negative initial balance + int32 internal constant INVALID_RECEIVE_RECORD_THRESHOLD = 86; // [Deprecated]. attempt to set negative receive record threshold + int32 internal constant INVALID_SEND_RECORD_THRESHOLD = 87; // [Deprecated]. attempt to set negative send record threshold + int32 internal constant ACCOUNT_IS_NOT_GENESIS_ACCOUNT = 88; // Special Account Operations should be performed by only Genesis account, return this code if it is not Genesis Account + int32 internal constant PAYER_ACCOUNT_UNAUTHORIZED = 89; // The fee payer account doesn't have permission to submit such Transaction + int32 internal constant INVALID_FREEZE_TRANSACTION_BODY = 90; // FreezeTransactionBody is invalid + int32 internal constant FREEZE_TRANSACTION_BODY_NOT_FOUND = 91; // FreezeTransactionBody does not exist + int32 internal constant TRANSFER_LIST_SIZE_LIMIT_EXCEEDED = 92; //Exceeded the number of accounts (both from and to) allowed for crypto transfer list + int32 internal constant RESULT_SIZE_LIMIT_EXCEEDED = 93; // Smart contract result size greater than specified maxResultSize + int32 internal constant NOT_SPECIAL_ACCOUNT = 94; //The payer account is not a special account(account 0.0.55) + int32 internal constant CONTRACT_NEGATIVE_GAS = 95; // Negative gas was offered in smart contract call + int32 internal constant CONTRACT_NEGATIVE_VALUE = 96; // Negative value / initial balance was specified in a smart contract call / create + int32 internal constant INVALID_FEE_FILE = 97; // Failed to update fee file + int32 internal constant INVALID_EXCHANGE_RATE_FILE = 98; // Failed to update exchange rate file + int32 internal constant INSUFFICIENT_LOCAL_CALL_GAS = 99; // Payment tendered for contract local call cannot cover both the fee and the gas + int32 internal constant ENTITY_NOT_ALLOWED_TO_DELETE = 100; // Entities with Entity ID below 1000 are not allowed to be deleted + int32 internal constant AUTHORIZATION_FAILED = 101; // Violating one of these rules: 1) treasury account can update all entities below 0.0.1000, 2) account 0.0.50 can update all entities from 0.0.51 - 0.0.80, 3) Network Function Master Account A/c 0.0.50 - Update all Network Function accounts & perform all the Network Functions listed below, 4) Network Function Accounts: i) A/c 0.0.55 - Update Address Book files (0.0.101/102), ii) A/c 0.0.56 - Update Fee schedule (0.0.111), iii) A/c 0.0.57 - Update Exchange Rate (0.0.112). + int32 internal constant FILE_UPLOADED_PROTO_INVALID = 102; // Fee Schedule Proto uploaded but not valid (append or update is required) + int32 internal constant FILE_UPLOADED_PROTO_NOT_SAVED_TO_DISK = 103; // Fee Schedule Proto uploaded but not valid (append or update is required) + int32 internal constant FEE_SCHEDULE_FILE_PART_UPLOADED = 104; // Fee Schedule Proto File Part uploaded + int32 internal constant EXCHANGE_RATE_CHANGE_LIMIT_EXCEEDED = 105; // The change on Exchange Rate exceeds Exchange_Rate_Allowed_Percentage + int32 internal constant MAX_CONTRACT_STORAGE_EXCEEDED = 106; // Contract permanent storage exceeded the currently allowable limit + int32 internal constant TRANSFER_ACCOUNT_SAME_AS_DELETE_ACCOUNT = 107; // Transfer Account should not be same as Account to be deleted + int32 internal constant TOTAL_LEDGER_BALANCE_INVALID = 108; + int32 internal constant EXPIRATION_REDUCTION_NOT_ALLOWED = 110; // The expiration date/time on a smart contract may not be reduced + int32 internal constant MAX_GAS_LIMIT_EXCEEDED = 111; //Gas exceeded currently allowable gas limit per transaction + int32 internal constant MAX_FILE_SIZE_EXCEEDED = 112; // File size exceeded the currently allowable limit + + int32 internal constant INVALID_TOPIC_ID = 150; // The Topic ID specified is not in the system. + int32 internal constant INVALID_ADMIN_KEY = 155; // A provided admin key was invalid. + int32 internal constant INVALID_SUBMIT_KEY = 156; // A provided submit key was invalid. + int32 internal constant UNAUTHORIZED = 157; // An attempted operation was not authorized (ie - a deleteTopic for a topic with no adminKey). + int32 internal constant INVALID_TOPIC_MESSAGE = 158; // A ConsensusService message is empty. + int32 internal constant INVALID_AUTORENEW_ACCOUNT = 159; // The autoRenewAccount specified is not a valid, active account. + int32 internal constant AUTORENEW_ACCOUNT_NOT_ALLOWED = 160; // An adminKey was not specified on the topic, so there must not be an autoRenewAccount. + // The topic has expired, was not automatically renewed, and is in a 7 day grace period before the topic will be + // deleted unrecoverably. This error response code will not be returned until autoRenew functionality is supported + // by HAPI. + int32 internal constant TOPIC_EXPIRED = 162; + int32 internal constant INVALID_CHUNK_NUMBER = 163; // chunk number must be from 1 to total (chunks) inclusive. + int32 internal constant INVALID_CHUNK_TRANSACTION_ID = 164; // For every chunk, the payer account that is part of initialTransactionID must match the Payer Account of this transaction. The entire initialTransactionID should match the transactionID of the first chunk, but this is not checked or enforced by Hedera except when the chunk number is 1. + int32 internal constant ACCOUNT_FROZEN_FOR_TOKEN = 165; // Account is frozen and cannot transact with the token + int32 internal constant TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED = 166; // An involved account already has more than tokens.maxPerAccount associations with non-deleted tokens. + int32 internal constant INVALID_TOKEN_ID = 167; // The token is invalid or does not exist + int32 internal constant INVALID_TOKEN_DECIMALS = 168; // Invalid token decimals + int32 internal constant INVALID_TOKEN_INITIAL_SUPPLY = 169; // Invalid token initial supply + int32 internal constant INVALID_TREASURY_ACCOUNT_FOR_TOKEN = 170; // Treasury Account does not exist or is deleted + int32 internal constant INVALID_TOKEN_SYMBOL = 171; // Token Symbol is not UTF-8 capitalized alphabetical string + int32 internal constant TOKEN_HAS_NO_FREEZE_KEY = 172; // Freeze key is not set on token + int32 internal constant TRANSFERS_NOT_ZERO_SUM_FOR_TOKEN = 173; // Amounts in transfer list are not net zero + int32 internal constant MISSING_TOKEN_SYMBOL = 174; // A token symbol was not provided + int32 internal constant TOKEN_SYMBOL_TOO_LONG = 175; // The provided token symbol was too long + int32 internal constant ACCOUNT_KYC_NOT_GRANTED_FOR_TOKEN = 176; // KYC must be granted and account does not have KYC granted + int32 internal constant TOKEN_HAS_NO_KYC_KEY = 177; // KYC key is not set on token + int32 internal constant INSUFFICIENT_TOKEN_BALANCE = 178; // Token balance is not sufficient for the transaction + int32 internal constant TOKEN_WAS_DELETED = 179; // Token transactions cannot be executed on deleted token + int32 internal constant TOKEN_HAS_NO_SUPPLY_KEY = 180; // Supply key is not set on token + int32 internal constant TOKEN_HAS_NO_WIPE_KEY = 181; // Wipe key is not set on token + int32 internal constant INVALID_TOKEN_MINT_AMOUNT = 182; // The requested token mint amount would cause an invalid total supply + int32 internal constant INVALID_TOKEN_BURN_AMOUNT = 183; // The requested token burn amount would cause an invalid total supply + int32 internal constant TOKEN_NOT_ASSOCIATED_TO_ACCOUNT = 184; // A required token-account relationship is missing + int32 internal constant CANNOT_WIPE_TOKEN_TREASURY_ACCOUNT = 185; // The target of a wipe operation was the token treasury account + int32 internal constant INVALID_KYC_KEY = 186; // The provided KYC key was invalid. + int32 internal constant INVALID_WIPE_KEY = 187; // The provided wipe key was invalid. + int32 internal constant INVALID_FREEZE_KEY = 188; // The provided freeze key was invalid. + int32 internal constant INVALID_SUPPLY_KEY = 189; // The provided supply key was invalid. + int32 internal constant MISSING_TOKEN_NAME = 190; // Token Name is not provided + int32 internal constant TOKEN_NAME_TOO_LONG = 191; // Token Name is too long + int32 internal constant INVALID_WIPING_AMOUNT = 192; // The provided wipe amount must not be negative, zero or bigger than the token holder balance + int32 internal constant TOKEN_IS_IMMUTABLE = 193; // Token does not have Admin key set, thus update/delete transactions cannot be performed + int32 internal constant TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT = 194; // An associateToken operation specified a token already associated to the account + int32 internal constant TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES = 195; // An attempted operation is invalid until all token balances for the target account are zero + int32 internal constant ACCOUNT_IS_TREASURY = 196; // An attempted operation is invalid because the account is a treasury + int32 internal constant TOKEN_ID_REPEATED_IN_TOKEN_LIST = 197; // Same TokenIDs present in the token list + int32 internal constant TOKEN_TRANSFER_LIST_SIZE_LIMIT_EXCEEDED = 198; // Exceeded the number of token transfers (both from and to) allowed for token transfer list + int32 internal constant EMPTY_TOKEN_TRANSFER_BODY = 199; // TokenTransfersTransactionBody has no TokenTransferList + int32 internal constant EMPTY_TOKEN_TRANSFER_ACCOUNT_AMOUNTS = 200; // TokenTransfersTransactionBody has a TokenTransferList with no AccountAmounts + + int32 internal constant INVALID_SCHEDULE_ID = 201; // The Scheduled entity does not exist; or has now expired, been deleted, or been executed + int32 internal constant SCHEDULE_IS_IMMUTABLE = 202; // The Scheduled entity cannot be modified. Admin key not set + int32 internal constant INVALID_SCHEDULE_PAYER_ID = 203; // The provided Scheduled Payer does not exist + int32 internal constant INVALID_SCHEDULE_ACCOUNT_ID = 204; // The Schedule Create Transaction TransactionID account does not exist + int32 internal constant NO_NEW_VALID_SIGNATURES = 205; // The provided sig map did not contain any new valid signatures from required signers of the scheduled transaction + int32 internal constant UNRESOLVABLE_REQUIRED_SIGNERS = 206; // The required signers for a scheduled transaction cannot be resolved, for example because they do not exist or have been deleted + int32 internal constant SCHEDULED_TRANSACTION_NOT_IN_WHITELIST = 207; // Only whitelisted transaction types may be scheduled + int32 internal constant SOME_SIGNATURES_WERE_INVALID = 208; // At least one of the signatures in the provided sig map did not represent a valid signature for any required signer + int32 internal constant TRANSACTION_ID_FIELD_NOT_ALLOWED = 209; // The scheduled field in the TransactionID may not be set to true + int32 internal constant IDENTICAL_SCHEDULE_ALREADY_CREATED = 210; // A schedule already exists with the same identifying fields of an attempted ScheduleCreate (that is, all fields other than scheduledPayerAccountID) + int32 internal constant INVALID_ZERO_BYTE_IN_STRING = 211; // A string field in the transaction has a UTF-8 encoding with the prohibited zero byte + int32 internal constant SCHEDULE_ALREADY_DELETED = 212; // A schedule being signed or deleted has already been deleted + int32 internal constant SCHEDULE_ALREADY_EXECUTED = 213; // A schedule being signed or deleted has already been executed + int32 internal constant MESSAGE_SIZE_TOO_LARGE = 214; // ConsensusSubmitMessage request's message size is larger than allowed. +} diff --git a/packages/server/tests/contracts/contracts_v1/HederaTokenService.json b/packages/server/tests/contracts/contracts_v1/HederaTokenService.json new file mode 100644 index 0000000000..d1d1194843 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/HederaTokenService.json @@ -0,0 +1,208 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HederaTokenService", + "sourceName": "contracts/HederaTokenService.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "kycGranted", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "name": "updateTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/HederaTokenService.sol b/packages/server/tests/contracts/contracts_v1/HederaTokenService.sol new file mode 100644 index 0000000000..4b1ac1bbf3 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/HederaTokenService.sol @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./HederaResponseCodes.sol"; +import "./IHederaTokenService.sol"; + +abstract contract HederaTokenService is HederaResponseCodes { + + address constant precompileAddress = address(0x167); + // 90 days in seconds + uint32 constant defaultAutoRenewPeriod = 7776000; + + uint constant ADMIN_KEY_TYPE = 1; + uint constant KYC_KEY_TYPE = 2; + uint constant FREEZE_KEY_TYPE = 4; + uint constant WIPE_KEY_TYPE = 8; + uint constant SUPPLY_KEY_TYPE = 16; + uint constant FEE_SCHEDULE_KEY_TYPE = 32; + uint constant PAUSE_KEY_TYPE = 64; + + modifier nonEmptyExpiry(IHederaTokenService.HederaToken memory token) + { + if (token.expiry.second == 0 && token.expiry.autoRenewPeriod == 0) { + token.expiry.autoRenewPeriod = defaultAutoRenewPeriod; + } + _; + } + + /// Initiates a Token Transfer + /// @param tokenTransfers the list of transfers to do + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function cryptoTransfer(IHederaTokenService.TokenTransferList[] memory tokenTransfers) internal + returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.cryptoTransfer.selector, tokenTransfers)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Mints an amount of the token to the defined treasury account + /// @param token The token for which to mint tokens. If token does not exist, transaction results in + /// INVALID_TOKEN_ID + /// @param amount Applicable to tokens of type FUNGIBLE_COMMON. The amount to mint to the Treasury Account. + /// Amount must be a positive non-zero number represented in the lowest denomination of the + /// token. The new supply must be lower than 2^63. + /// @param metadata Applicable to tokens of type NON_FUNGIBLE_UNIQUE. A list of metadata that are being created. + /// Maximum allowed size of each metadata is 100 bytes + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return newTotalSupply The new supply of tokens. For NFTs it is the total count of NFTs + /// @return serialNumbers If the token is an NFT the newly generate serial numbers, otherwise empty. + function mintToken(address token, uint64 amount, bytes[] memory metadata) internal + returns (int responseCode, uint64 newTotalSupply, int64[] memory serialNumbers) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.mintToken.selector, + token, amount, metadata)); + (responseCode, newTotalSupply, serialNumbers) = + success + ? abi.decode(result, (int32, uint64, int64[])) + : (HederaResponseCodes.UNKNOWN, 0, new int64[](0)); + } + + /// Burns an amount of the token from the defined treasury account + /// @param token The token for which to burn tokens. If token does not exist, transaction results in + /// INVALID_TOKEN_ID + /// @param amount Applicable to tokens of type FUNGIBLE_COMMON. The amount to burn from the Treasury Account. + /// Amount must be a positive non-zero number, not bigger than the token balance of the treasury + /// account (0; balance], represented in the lowest denomination. + /// @param serialNumbers Applicable to tokens of type NON_FUNGIBLE_UNIQUE. The list of serial numbers to be burned. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return newTotalSupply The new supply of tokens. For NFTs it is the total count of NFTs + function burnToken(address token, uint64 amount, int64[] memory serialNumbers) internal + returns (int responseCode, uint64 newTotalSupply) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.burnToken.selector, + token, amount, serialNumbers)); + (responseCode, newTotalSupply) = + success + ? abi.decode(result, (int32, uint64)) + : (HederaResponseCodes.UNKNOWN, 0); + } + + /// Associates the provided account with the provided tokens. Must be signed by the provided + /// Account's key or called from the accounts contract key + /// If the provided account is not found, the transaction will resolve to INVALID_ACCOUNT_ID. + /// If the provided account has been deleted, the transaction will resolve to ACCOUNT_DELETED. + /// If any of the provided tokens is not found, the transaction will resolve to INVALID_TOKEN_REF. + /// If any of the provided tokens has been deleted, the transaction will resolve to TOKEN_WAS_DELETED. + /// If an association between the provided account and any of the tokens already exists, the + /// transaction will resolve to TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT. + /// If the provided account's associations count exceed the constraint of maximum token associations + /// per account, the transaction will resolve to TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED. + /// On success, associations between the provided account and tokens are made and the account is + /// ready to interact with the tokens. + /// @param account The account to be associated with the provided tokens + /// @param tokens The tokens to be associated with the provided account. In the case of NON_FUNGIBLE_UNIQUE + /// Type, once an account is associated, it can hold any number of NFTs (serial numbers) of that + /// token type + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function associateTokens(address account, address[] memory tokens) internal returns (int responseCode) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.associateTokens.selector, + account, tokens)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + function associateToken(address account, address token) internal returns (int responseCode) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.associateToken.selector, + account, token)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Dissociates the provided account with the provided tokens. Must be signed by the provided + /// Account's key. + /// If the provided account is not found, the transaction will resolve to INVALID_ACCOUNT_ID. + /// If the provided account has been deleted, the transaction will resolve to ACCOUNT_DELETED. + /// If any of the provided tokens is not found, the transaction will resolve to INVALID_TOKEN_REF. + /// If any of the provided tokens has been deleted, the transaction will resolve to TOKEN_WAS_DELETED. + /// If an association between the provided account and any of the tokens does not exist, the + /// transaction will resolve to TOKEN_NOT_ASSOCIATED_TO_ACCOUNT. + /// If a token has not been deleted and has not expired, and the user has a nonzero balance, the + /// transaction will resolve to TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES. + /// If a fungible token has expired, the user can disassociate even if their token balance is + /// not zero. + /// If a non fungible token has expired, the user can not disassociate if their token + /// balance is not zero. The transaction will resolve to TRANSACTION_REQUIRED_ZERO_TOKEN_BALANCES. + /// On success, associations between the provided account and tokens are removed. + /// @param account The account to be dissociated from the provided tokens + /// @param tokens The tokens to be dissociated from the provided account. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function dissociateTokens(address account, address[] memory tokens) internal returns (int responseCode) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.dissociateTokens.selector, + account, tokens)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + function dissociateToken(address account, address token) internal returns (int responseCode) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.dissociateToken.selector, + account, token)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Creates a Fungible Token with the specified properties + /// @param token the basic properties of the token being created + /// @param initialTotalSupply Specifies the initial supply of tokens to be put in circulation. The + /// initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible. + /// @param decimals the number of decimal places a token is divisible by + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createFungibleToken( + IHederaTokenService.HederaToken memory token, + uint initialTotalSupply, + uint decimals) nonEmptyExpiry(token) + internal returns (int responseCode, address tokenAddress) { + (bool success, bytes memory result) = precompileAddress.call{value: msg.value}( + abi.encodeWithSelector(IHederaTokenService.createFungibleToken.selector, + token, initialTotalSupply, decimals)); + + + (responseCode, tokenAddress) = success ? abi.decode(result, (int32, address)) : (HederaResponseCodes.UNKNOWN, address(0)); + } + + /// Creates a Fungible Token with the specified properties + /// @param token the basic properties of the token being created + /// @param initialTotalSupply Specifies the initial supply of tokens to be put in circulation. The + /// initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible. + /// @param decimals the number of decimal places a token is divisible by + /// @param fixedFees list of fixed fees to apply to the token + /// @param fractionalFees list of fractional fees to apply to the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createFungibleTokenWithCustomFees( + IHederaTokenService.HederaToken memory token, + uint initialTotalSupply, + uint decimals, + IHederaTokenService.FixedFee[] memory fixedFees, + IHederaTokenService.FractionalFee[] memory fractionalFees) nonEmptyExpiry(token) + internal returns (int responseCode, address tokenAddress) { + (bool success, bytes memory result) = precompileAddress.call{value: msg.value}( + abi.encodeWithSelector(IHederaTokenService.createFungibleTokenWithCustomFees.selector, + token, initialTotalSupply, decimals, fixedFees, fractionalFees)); + (responseCode, tokenAddress) = success ? abi.decode(result, (int32, address)) : (HederaResponseCodes.UNKNOWN, address(0)); + } + + /// Creates an Non Fungible Unique Token with the specified properties + /// @param token the basic properties of the token being created + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createNonFungibleToken(IHederaTokenService.HederaToken memory token) nonEmptyExpiry(token) + internal returns (int responseCode, address tokenAddress) { + (bool success, bytes memory result) = precompileAddress.call{value: msg.value}( + abi.encodeWithSelector(IHederaTokenService.createNonFungibleToken.selector, token)); + (responseCode, tokenAddress) = success ? abi.decode(result, (int32, address)) : (HederaResponseCodes.UNKNOWN, address(0)); + } + + /// Creates an Non Fungible Unique Token with the specified properties + /// @param token the basic properties of the token being created + /// @param fixedFees list of fixed fees to apply to the token + /// @param royaltyFees list of royalty fees to apply to the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createNonFungibleTokenWithCustomFees( + IHederaTokenService.HederaToken memory token, + IHederaTokenService.FixedFee[] memory fixedFees, + IHederaTokenService.RoyaltyFee[] memory royaltyFees) nonEmptyExpiry(token) + internal returns (int responseCode, address tokenAddress) { + (bool success, bytes memory result) = precompileAddress.call{value: msg.value}( + abi.encodeWithSelector(IHederaTokenService.createNonFungibleTokenWithCustomFees.selector, + token, fixedFees, royaltyFees)); + (responseCode, tokenAddress) = success ? abi.decode(result, (int32, address)) : (HederaResponseCodes.UNKNOWN, address(0)); + } + + /// Retrieves fungible specific token info for a fungible token + /// @param token The ID of the token as a solidity address + function getFungibleTokenInfo(address token) internal returns (int responseCode, IHederaTokenService.FungibleTokenInfo memory tokenInfo) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getFungibleTokenInfo.selector, token)); + IHederaTokenService.FungibleTokenInfo memory defaultTokenInfo; + (responseCode, tokenInfo) = success ? abi.decode(result, (int32, IHederaTokenService.FungibleTokenInfo)) : (HederaResponseCodes.UNKNOWN, defaultTokenInfo); + } + + /// Retrieves general token info for a given token + /// @param token The ID of the token as a solidity address + function getTokenInfo(address token) internal returns (int responseCode, IHederaTokenService.TokenInfo memory tokenInfo) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getTokenInfo.selector, token)); + IHederaTokenService.TokenInfo memory defaultTokenInfo; + (responseCode, tokenInfo) = success ? abi.decode(result, (int32, IHederaTokenService.TokenInfo)) : (HederaResponseCodes.UNKNOWN, defaultTokenInfo); + } + + /// Retrieves non-fungible specific token info for a given NFT + /// @param token The ID of the token as a solidity address + function getNonFungibleTokenInfo(address token, int64 serialNumber) internal returns (int responseCode, IHederaTokenService.NonFungibleTokenInfo memory tokenInfo) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getNonFungibleTokenInfo.selector, token, serialNumber)); + IHederaTokenService.NonFungibleTokenInfo memory defaultTokenInfo; + (responseCode, tokenInfo) = success ? abi.decode(result, (int32, IHederaTokenService.NonFungibleTokenInfo)) : (HederaResponseCodes.UNKNOWN, defaultTokenInfo); + } + + /// Query token custom fees + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return fixedFees Set of fixed fees for `token` + /// @return fractionalFees Set of fractional fees for `token` + /// @return royaltyFees Set of royalty fees for `token` + function getTokenCustomFees(address token) internal returns (int64 responseCode, + IHederaTokenService.FixedFee[] memory fixedFees, + IHederaTokenService.FractionalFee[] memory fractionalFees, + IHederaTokenService.RoyaltyFee[] memory royaltyFees) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getTokenCustomFees.selector, token)); + IHederaTokenService.FixedFee[] memory defaultFixedFees; + IHederaTokenService.FractionalFee[] memory defaultFractionalFees; + IHederaTokenService.RoyaltyFee[] memory defaultRoyaltyFees; + (responseCode, fixedFees, fractionalFees, royaltyFees) = + success ? abi.decode + (result, (int32, IHederaTokenService.FixedFee[], IHederaTokenService.FractionalFee[], IHederaTokenService.RoyaltyFee[])) + : (HederaResponseCodes.UNKNOWN, defaultFixedFees, defaultFractionalFees, defaultRoyaltyFees); + } + + /// Allows spender to withdraw from your account multiple times, up to the value amount. If this function is called + /// again it overwrites the current allowance with value. + /// Only Applicable to Fungible Tokens + /// @param token The hedera token address to approve + /// @param spender the account authorized to spend + /// @param amount the amount of tokens authorized to spend. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function approve(address token, address spender, uint256 amount) internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.approve.selector, + token, spender, amount)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Returns the amount which spender is still allowed to withdraw from owner. + /// Only Applicable to Fungible Tokens + /// @param token The Hedera token address to check the allowance of + /// @param owner the owner of the tokens to be spent + /// @param spender the spender of the tokens + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function allowance(address token, address owner, address spender) internal returns (int responseCode, uint256 amount) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.allowance.selector, + token, owner, spender)); + (responseCode, amount) = success ? abi.decode(result, (int32, uint256)) : (HederaResponseCodes.UNKNOWN, 0); + } + + /// Allow or reaffirm the approved address to transfer an NFT the approved address does not own. + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to approve + /// @param approved The new approved NFT controller. To revoke approvals pass in the zero address. + /// @param serialNumber The NFT serial number to approve + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function approveNFT(address token, address approved, uint256 serialNumber) internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.approveNFT.selector, + token, approved, serialNumber)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Get the approved address for a single NFT + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to check approval + /// @param serialNumber The NFT to find the approved address for + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return approved The approved address for this NFT, or the zero address if there is none + function getApproved(address token, uint256 serialNumber) internal returns (int responseCode, address approved) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getApproved.selector, + token, serialNumber)); + (responseCode, approved) = + success + ? abi.decode(result, (int32, address)) + : (HederaResponseCodes.UNKNOWN, address(0)); + } + + /// Query if token account is frozen + /// @param token The token address to check + /// @param account The account address associated with the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return frozen True if `account` is frozen for `token` + function isFrozen(address token, address account)internal returns (int64 responseCode, bool frozen){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.isFrozen.selector, token, account)); + (responseCode, frozen) = success ? abi.decode(result, (int32,bool)) : (HederaResponseCodes.UNKNOWN,false); + } + + /// Query if token account has kyc granted + /// @param token The token address to check + /// @param account The account address associated with the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return kycGranted True if `account` has kyc granted for `token` + function isKyc(address token, address account)external returns (int64 responseCode, bool kycGranted){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.isKyc.selector, token, account)); + (responseCode, kycGranted) = success ? abi.decode(result, (int32,bool)) : (HederaResponseCodes.UNKNOWN,false); + } + + /// Operation to freeze token account + /// @param token The token address + /// @param account The account address to be frozen + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function freezeToken(address token, address account) internal returns (int64 responseCode){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.freezeToken.selector, token, account)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to unfreeze token account + /// @param token The token address + /// @param account The account address to be unfrozen + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function unfreezeToken(address token, address account)internal returns (int64 responseCode){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.unfreezeToken.selector, token, account)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to grant kyc to token account + /// @param token The token address + /// @param account The account address to grant kyc + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function grantTokenKyc(address token, address account)external returns (int64 responseCode){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.grantTokenKyc.selector, token, account)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to revoke kyc to token account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function revokeTokenKyc(address token, address account)external returns (int64 responseCode){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.revokeTokenKyc.selector, token, account)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Enable or disable approval for a third party ("operator") to manage + /// all of `msg.sender`'s assets + /// @param token The Hedera NFT token address to approve + /// @param operator Address to add to the set of authorized operators + /// @param approved True if the operator is approved, false to revoke approval + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function setApprovalForAll(address token, address operator, bool approved) internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.setApprovalForAll.selector, + token, operator, approved)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + + /// Query if an address is an authorized operator for another address + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to approve + /// @param owner The address that owns the NFTs + /// @param operator The address that acts on behalf of the owner + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return approved True if `operator` is an approved operator for `owner`, false otherwise + function isApprovedForAll(address token, address owner, address operator) internal returns (int responseCode, bool approved) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.isApprovedForAll.selector, + token, owner, operator)); + (responseCode, approved) = + success + ? abi.decode(result, (int32, bool)) + : (HederaResponseCodes.UNKNOWN, false); + } + + /// Query token default freeze status + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return defaultFreezeStatus True if `token` default freeze status is frozen. + function getTokenDefaultFreezeStatus(address token) internal returns (int responseCode, bool defaultFreezeStatus) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getTokenDefaultFreezeStatus.selector, token)); + (responseCode, defaultFreezeStatus) = success ? abi.decode(result, (int32, bool)) : (HederaResponseCodes.UNKNOWN, false); + } + + /// Query token default kyc status + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return defaultKycStatus True if `token` default kyc status is KycNotApplicable and false if Revoked. + function getTokenDefaultKycStatus(address token) internal returns (int responseCode, bool defaultKycStatus) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getTokenDefaultKycStatus.selector, token)); + (responseCode, defaultKycStatus) = success ? abi.decode(result, (int32, bool)) : (HederaResponseCodes.UNKNOWN, false); + } + + /********************** + * ABI v1 calls * + **********************/ + + /// Initiates a Fungible Token Transfer + /// @param token The ID of the token as a solidity address + /// @param accountIds account to do a transfer to/from + /// @param amounts The amount from the accountId at the same index + function transferTokens(address token, address[] memory accountIds, int64[] memory amounts) internal + returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.transferTokens.selector, + token, accountIds, amounts)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Initiates a Non-Fungable Token Transfer + /// @param token The ID of the token as a solidity address + /// @param sender the sender of an nft + /// @param receiver the receiver of the nft sent by the same index at sender + /// @param serialNumber the serial number of the nft sent by the same index at sender + function transferNFTs(address token, address[] memory sender, address[] memory receiver, int64[] memory serialNumber) + internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.transferNFTs.selector, + token, sender, receiver, serialNumber)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Transfers tokens where the calling account/contract is implicitly the first entry in the token transfer list, + /// where the amount is the value needed to zero balance the transfers. Regular signing rules apply for sending + /// (positive amount) or receiving (negative amount) + /// @param token The token to transfer to/from + /// @param sender The sender for the transaction + /// @param receiver The receiver of the transaction + /// @param amount Non-negative value to send. a negative value will result in a failure. + function transferToken(address token, address sender, address receiver, int64 amount) internal + returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.transferToken.selector, + token, sender, receiver, amount)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Transfers tokens where the calling account/contract is implicitly the first entry in the token transfer list, + /// where the amount is the value needed to zero balance the transfers. Regular signing rules apply for sending + /// (positive amount) or receiving (negative amount) + /// @param token The token to transfer to/from + /// @param sender The sender for the transaction + /// @param receiver The receiver of the transaction + /// @param serialNumber The serial number of the NFT to transfer. + function transferNFT(address token, address sender, address receiver, int64 serialNumber) internal + returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.transferNFT.selector, + token, sender, receiver, serialNumber)); + responseCode = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to pause token + /// @param token The token address to be paused + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function pauseToken(address token) external returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.pauseToken.selector, token)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to unpause token + /// @param token The token address to be unpaused + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function unpauseToken(address token) external returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.unpauseToken.selector, token)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to wipe fungible tokens from account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @param amount The number of tokens to wipe + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function wipeTokenAccount(address token, address account, uint32 amount) internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.wipeTokenAccount.selector, token, account, amount)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to wipe non fungible tokens from account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @param serialNumbers The serial numbers of token to wipe + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function wipeTokenAccountNFT(address token, address account, int64[] memory serialNumbers) internal + returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.wipeTokenAccountNFT.selector, token, account, serialNumbers)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to delete token + /// @param token The token address + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function deleteToken(address token) internal returns (int responseCode) + { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.deleteToken.selector, token)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } + + /// Operation to get token expiry info + /// @param token The token address + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return expiryInfo The expiry info of the token + function getTokenExpiryInfo(address token) external returns (int responseCode, IHederaTokenService.Expiry memory expiryInfo){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.getTokenExpiryInfo.selector, token)); + IHederaTokenService.Expiry memory defaultExpiryInfo; + (responseCode, expiryInfo) = success ? abi.decode(result, (int32, IHederaTokenService.Expiry)) : (HederaResponseCodes.UNKNOWN, defaultExpiryInfo); + } + + /// Operation to update token expiry info + /// @param token The token address + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function updateTokenExpiryInfo(address token, IHederaTokenService.Expiry memory expiryInfo) external returns (int responseCode){ + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.updateTokenExpiryInfo.selector, token, expiryInfo)); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } +} diff --git a/packages/server/tests/contracts/contracts_v1/IHederaTokenService.json b/packages/server/tests/contracts/contracts_v1/IHederaTokenService.json new file mode 100644 index 0000000000..dafdcaebc7 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/IHederaTokenService.json @@ -0,0 +1,2594 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IHederaTokenService", + "sourceName": "contracts/IHederaTokenService.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serialNumber", + "type": "uint256" + } + ], + "name": "approveNFT", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "associateToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "associateTokens", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + } + ], + "name": "burnToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "uint64", + "name": "newTotalSupply", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "initialTotalSupply", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "decimals", + "type": "uint32" + } + ], + "name": "createFungibleToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "initialTotalSupply", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "decimals", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "minimumAmount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maximumAmount", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "netOfTransfers", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FractionalFee[]", + "name": "fractionalFees", + "type": "tuple[]" + } + ], + "name": "createFungibleTokenWithCustomFees", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + } + ], + "name": "createNonFungibleToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.RoyaltyFee[]", + "name": "royaltyFees", + "type": "tuple[]" + } + ], + "name": "createNonFungibleTokenWithCustomFees", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "accountID", + "type": "address" + }, + { + "internalType": "int64", + "name": "amount", + "type": "int64" + } + ], + "internalType": "struct IHederaTokenService.AccountAmount[]", + "name": "transfers", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "senderAccountID", + "type": "address" + }, + { + "internalType": "address", + "name": "receiverAccountID", + "type": "address" + }, + { + "internalType": "int64", + "name": "serialNumber", + "type": "int64" + } + ], + "internalType": "struct IHederaTokenService.NftTransfer[]", + "name": "nftTransfers", + "type": "tuple[]" + } + ], + "internalType": "struct IHederaTokenService.TokenTransferList[]", + "name": "tokenTransfers", + "type": "tuple[]" + } + ], + "name": "cryptoTransfer", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "deleteToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "dissociateToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "dissociateTokens", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "freezeToken", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serialNumber", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "address", + "name": "approved", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getFungibleTokenInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "totalSupply", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "deleted", + "type": "bool" + }, + { + "internalType": "bool", + "name": "defaultKycStatus", + "type": "bool" + }, + { + "internalType": "bool", + "name": "pauseStatus", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "minimumAmount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maximumAmount", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "netOfTransfers", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FractionalFee[]", + "name": "fractionalFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.RoyaltyFee[]", + "name": "royaltyFees", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "ledgerId", + "type": "string" + } + ], + "internalType": "struct IHederaTokenService.TokenInfo", + "name": "tokenInfo", + "type": "tuple" + }, + { + "internalType": "uint32", + "name": "decimals", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.FungibleTokenInfo", + "name": "tokenInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "int64", + "name": "serialNumber", + "type": "int64" + } + ], + "name": "getNonFungibleTokenInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "totalSupply", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "deleted", + "type": "bool" + }, + { + "internalType": "bool", + "name": "defaultKycStatus", + "type": "bool" + }, + { + "internalType": "bool", + "name": "pauseStatus", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "minimumAmount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maximumAmount", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "netOfTransfers", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FractionalFee[]", + "name": "fractionalFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.RoyaltyFee[]", + "name": "royaltyFees", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "ledgerId", + "type": "string" + } + ], + "internalType": "struct IHederaTokenService.TokenInfo", + "name": "tokenInfo", + "type": "tuple" + }, + { + "internalType": "int64", + "name": "serialNumber", + "type": "int64" + }, + { + "internalType": "address", + "name": "ownerId", + "type": "address" + }, + { + "internalType": "int64", + "name": "creationTime", + "type": "int64" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "address", + "name": "spenderId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.NonFungibleTokenInfo", + "name": "tokenInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenCustomFees", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "minimumAmount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maximumAmount", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "netOfTransfers", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FractionalFee[]", + "name": "fractionalFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.RoyaltyFee[]", + "name": "royaltyFees", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenDefaultFreezeStatus", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "defaultFreezeStatus", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenDefaultKycStatus", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "defaultKycStatus", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "components": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "treasury", + "type": "address" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "bool", + "name": "tokenSupplyType", + "type": "bool" + }, + { + "internalType": "int64", + "name": "maxSupply", + "type": "int64" + }, + { + "internalType": "bool", + "name": "freezeDefault", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "keyType", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bool", + "name": "inheritAccountKey", + "type": "bool" + }, + { + "internalType": "address", + "name": "contractId", + "type": "address" + }, + { + "internalType": "bytes", + "name": "ed25519", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ECDSA_secp256k1", + "type": "bytes" + }, + { + "internalType": "address", + "name": "delegatableContractId", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.KeyValue", + "name": "key", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.TokenKey[]", + "name": "tokenKeys", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiry", + "type": "tuple" + } + ], + "internalType": "struct IHederaTokenService.HederaToken", + "name": "token", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "totalSupply", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "deleted", + "type": "bool" + }, + { + "internalType": "bool", + "name": "defaultKycStatus", + "type": "bool" + }, + { + "internalType": "bool", + "name": "pauseStatus", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "useCurrentTokenForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FixedFee[]", + "name": "fixedFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "minimumAmount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maximumAmount", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "netOfTransfers", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.FractionalFee[]", + "name": "fractionalFees", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "numerator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "denominator", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "tokenId", + "type": "address" + }, + { + "internalType": "bool", + "name": "useHbarsForPayment", + "type": "bool" + }, + { + "internalType": "address", + "name": "feeCollector", + "type": "address" + } + ], + "internalType": "struct IHederaTokenService.RoyaltyFee[]", + "name": "royaltyFees", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "ledgerId", + "type": "string" + } + ], + "internalType": "struct IHederaTokenService.TokenInfo", + "name": "tokenInfo", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isFrozen", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "frozen", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + }, + { + "internalType": "bool", + "name": "kycGranted", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "amount", + "type": "uint64" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "mintToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "uint64", + "name": "newTotalSupply", + "type": "uint64" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeTokenKyc", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "int64", + "name": "serialNumber", + "type": "int64" + } + ], + "name": "transferNFT", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address[]", + "name": "sender", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "receiver", + "type": "address[]" + }, + { + "internalType": "int64[]", + "name": "serialNumber", + "type": "int64[]" + } + ], + "name": "transferNFTs", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "int64", + "name": "amount", + "type": "int64" + } + ], + "name": "transferToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address[]", + "name": "accountId", + "type": "address[]" + }, + { + "internalType": "int64[]", + "name": "amount", + "type": "int64[]" + } + ], + "name": "transferTokens", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "unfreezeToken", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "second", + "type": "uint32" + }, + { + "internalType": "address", + "name": "autoRenewAccount", + "type": "address" + }, + { + "internalType": "uint32", + "name": "autoRenewPeriod", + "type": "uint32" + } + ], + "internalType": "struct IHederaTokenService.Expiry", + "name": "expiryInfo", + "type": "tuple" + } + ], + "name": "updateTokenExpiryInfo", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint32", + "name": "amount", + "type": "uint32" + } + ], + "name": "wipeTokenAccount", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + } + ], + "name": "wipeTokenAccountNFT", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/IHederaTokenService.sol b/packages/server/tests/contracts/contracts_v1/IHederaTokenService.sol new file mode 100644 index 0000000000..389a5393a2 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/IHederaTokenService.sol @@ -0,0 +1,620 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; +pragma experimental ABIEncoderV2; + +interface IHederaTokenService { + + /// Transfers cryptocurrency among two or more accounts by making the desired adjustments to their + /// balances. Each transfer list can specify up to 10 adjustments. Each negative amount is withdrawn + /// from the corresponding account (a sender), and each positive one is added to the corresponding + /// account (a receiver). The amounts list must sum to zero. Each amount is a number of tinybars + /// (there are 100,000,000 tinybars in one hbar). If any sender account fails to have sufficient + /// hbars, then the entire transaction fails, and none of those transfers occur, though the + /// transaction fee is still charged. This transaction must be signed by the keys for all the sending + /// accounts, and for any receiving accounts that have receiverSigRequired == true. The signatures + /// are in the same order as the accounts, skipping those accounts that don't need a signature. + struct AccountAmount { + // The Account ID, as a solidity address, that sends/receives cryptocurrency or tokens + address accountID; + + // The amount of the lowest denomination of the given token that + // the account sends(negative) or receives(positive) + int64 amount; + } + + /// A sender account, a receiver account, and the serial number of an NFT of a Token with + /// NON_FUNGIBLE_UNIQUE type. When minting NFTs the sender will be the default AccountID instance + /// (0.0.0 aka 0x0) and when burning NFTs, the receiver will be the default AccountID instance. + struct NftTransfer { + // The solidity address of the sender + address senderAccountID; + + // The solidity address of the receiver + address receiverAccountID; + + // The serial number of the NFT + int64 serialNumber; + } + + struct TokenTransferList { + // The ID of the token as a solidity address + address token; + + // Applicable to tokens of type FUNGIBLE_COMMON. Multiple list of AccountAmounts, each of which + // has an account and amount. + AccountAmount[] transfers; + + // Applicable to tokens of type NON_FUNGIBLE_UNIQUE. Multiple list of NftTransfers, each of + // which has a sender and receiver account, including the serial number of the NFT + NftTransfer[] nftTransfers; + } + + /// Expiry properties of a Hedera token - second, autoRenewAccount, autoRenewPeriod + struct Expiry { + // The epoch second at which the token should expire; if an auto-renew account and period are + // specified, this is coerced to the current epoch second plus the autoRenewPeriod + uint32 second; + + // ID of an account which will be automatically charged to renew the token's expiration, at + // autoRenewPeriod interval, expressed as a solidity address + address autoRenewAccount; + + // The interval at which the auto-renew account will be charged to extend the token's expiry + uint32 autoRenewPeriod; + } + + /// A Key can be a public key from either the Ed25519 or ECDSA(secp256k1) signature schemes, where + /// in the ECDSA(secp256k1) case we require the 33-byte compressed form of the public key. We call + /// these public keys primitive keys. + /// A Key can also be the ID of a smart contract instance, which is then authorized to perform any + /// precompiled contract action that requires this key to sign. + /// Note that when a Key is a smart contract ID, it doesn't mean the contract with that ID + /// will actually create a cryptographic signature. It only means that when the contract calls a + /// precompiled contract, the resulting "child transaction" will be authorized to perform any action + /// controlled by the Key. + /// Exactly one of the possible values should be populated in order for the Key to be valid. + struct KeyValue { + + // if set to true, the key of the calling Hedera account will be inherited as the token key + bool inheritAccountKey; + + // smart contract instance that is authorized as if it had signed with a key + address contractId; + + // Ed25519 public key bytes + bytes ed25519; + + // Compressed ECDSA(secp256k1) public key bytes + bytes ECDSA_secp256k1; + + // A smart contract that, if the recipient of the active message frame, should be treated + // as having signed. (Note this does not mean the code being executed in the frame + // will belong to the given contract, since it could be running another contract's code via + // delegatecall. So setting this key is a more permissive version of setting the + // contractID key, which also requires the code in the active message frame belong to the + // the contract with the given id.) + address delegatableContractId; + } + + /// A list of token key types the key should be applied to and the value of the key + struct TokenKey { + + // bit field representing the key type. Keys of all types that have corresponding bits set to 1 + // will be created for the token. + // 0th bit: adminKey + // 1st bit: kycKey + // 2nd bit: freezeKey + // 3rd bit: wipeKey + // 4th bit: supplyKey + // 5th bit: feeScheduleKey + // 6th bit: pauseKey + // 7th bit: ignored + uint keyType; + + // the value that will be set to the key type + KeyValue key; + } + + /// Basic properties of a Hedera Token - name, symbol, memo, tokenSupplyType, maxSupply, + /// treasury, freezeDefault. These properties are related both to Fungible and NFT token types. + struct HederaToken { + // The publicly visible name of the token. The token name is specified as a Unicode string. + // Its UTF-8 encoding cannot exceed 100 bytes, and cannot contain the 0 byte (NUL). + string name; + + // The publicly visible token symbol. The token symbol is specified as a Unicode string. + // Its UTF-8 encoding cannot exceed 100 bytes, and cannot contain the 0 byte (NUL). + string symbol; + + // The ID of the account which will act as a treasury for the token as a solidity address. + // This account will receive the specified initial supply or the newly minted NFTs in + // the case for NON_FUNGIBLE_UNIQUE Type + address treasury; + + // The memo associated with the token (UTF-8 encoding max 100 bytes) + string memo; + + // IWA compatibility. Specified the token supply type. Defaults to INFINITE + bool tokenSupplyType; + + // IWA Compatibility. Depends on TokenSupplyType. For tokens of type FUNGIBLE_COMMON - the + // maximum number of tokens that can be in circulation. For tokens of type NON_FUNGIBLE_UNIQUE - + // the maximum number of NFTs (serial numbers) that can be minted. This field can never be changed! + uint32 maxSupply; + + // The default Freeze status (frozen or unfrozen) of Hedera accounts relative to this token. If + // true, an account must be unfrozen before it can receive the token + bool freezeDefault; + + // list of keys to set to the token + TokenKey[] tokenKeys; + + // expiry properties of a Hedera token - second, autoRenewAccount, autoRenewPeriod + Expiry expiry; + } + + /// A fixed number of units (hbar or token) to assess as a fee during a transfer of + /// units of the token to which this fixed fee is attached. The denomination of + /// the fee depends on the values of tokenId, useHbarsForPayment and + /// useCurrentTokenForPayment. Exactly one of the values should be set. + struct FixedFee { + + uint32 amount; + + // Specifies ID of token that should be used for fixed fee denomination + address tokenId; + + // Specifies this fixed fee should be denominated in Hbar + bool useHbarsForPayment; + + // Specifies this fixed fee should be denominated in the Token currently being created + bool useCurrentTokenForPayment; + + // The ID of the account to receive the custom fee, expressed as a solidity address + address feeCollector; + } + + /// A fraction of the transferred units of a token to assess as a fee. The amount assessed will never + /// be less than the given minimumAmount, and never greater than the given maximumAmount. The + /// denomination is always units of the token to which this fractional fee is attached. + struct FractionalFee { + // A rational number's numerator, used to set the amount of a value transfer to collect as a custom fee + uint32 numerator; + + // A rational number's denominator, used to set the amount of a value transfer to collect as a custom fee + uint32 denominator; + + // The minimum amount to assess + uint32 minimumAmount; + + // The maximum amount to assess (zero implies no maximum) + uint32 maximumAmount; + bool netOfTransfers; + + // The ID of the account to receive the custom fee, expressed as a solidity address + address feeCollector; + } + + /// A fee to assess during a transfer that changes ownership of an NFT. Defines the fraction of + /// the fungible value exchanged for an NFT that the ledger should collect as a royalty. ("Fungible + /// value" includes both ℏ and units of fungible HTS tokens.) When the NFT sender does not receive + /// any fungible value, the ledger will assess the fallback fee, if present, to the new NFT owner. + /// Royalty fees can only be added to tokens of type type NON_FUNGIBLE_UNIQUE. + struct RoyaltyFee { + // A fraction's numerator of fungible value exchanged for an NFT to collect as royalty + uint32 numerator; + + // A fraction's denominator of fungible value exchanged for an NFT to collect as royalty + uint32 denominator; + + // If present, the fee to assess to the NFT receiver when no fungible value + // is exchanged with the sender. Consists of: + // amount: the amount to charge for the fee + // tokenId: Specifies ID of token that should be used for fixed fee denomination + // useHbarsForPayment: Specifies this fee should be denominated in Hbar + uint32 amount; + address tokenId; + bool useHbarsForPayment; + + // The ID of the account to receive the custom fee, expressed as a solidity address + address feeCollector; + } + + //TokenInfo defines the basic properties of a Fungible or Non-Fungible Hedera Token + struct TokenInfo { + //Basic properties of a Hedera Token + HederaToken token; + //The number of tokens (fungible) or serials (non-fungible) of the token + uint64 totalSupply; + //Specifies whether the token is deleted or not + bool deleted; + //Specifies whether the token kyc was defaulted with KycNotApplicable (true) or Revoked (false) + bool defaultKycStatus; + //Specifies whether the token is currently paused or not + bool pauseStatus; + //The fixed fees collected when transferring the token + FixedFee[] fixedFees; + //The fractional fees collected when transferring the token + FractionalFee[] fractionalFees; + //The royalty fees collected when transferring the token + RoyaltyFee[] royaltyFees; + //The ID of the network ledger + string ledgerId; + } + + //FungibleTokenInfo defines the basic properties of a Fungible Hedera Token + struct FungibleTokenInfo { + //The shared hedera token info + TokenInfo tokenInfo; + //The number of decimal places a token is divisible by + uint32 decimals; + } + + //NonFungibleTokenInfo defines the basic properties of a Non Fungible Hedera Token + struct NonFungibleTokenInfo { + //The shared hedera token info + TokenInfo tokenInfo; + //The serial number of the NFT + int64 serialNumber; + //The account id specifying the owner of the NFT + address ownerId; + //The epoch second at which the NFT was created + int64 creationTime; + //The unique metadata of the NFT + bytes metadata; + //The account id specifying an account that has been granted spending permissions on this NFT + address spenderId; + } + + /********************** + * Direct HTS Calls * + **********************/ + + /// Initiates a Token Transfer + /// @param tokenTransfers the list of transfers to do + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function cryptoTransfer(TokenTransferList[] memory tokenTransfers) external returns (int responseCode); + + /// Mints an amount of the token to the defined treasury account + /// @param token The token for which to mint tokens. If token does not exist, transaction results in + /// INVALID_TOKEN_ID + /// @param amount Applicable to tokens of type FUNGIBLE_COMMON. The amount to mint to the Treasury Account. + /// Amount must be a positive non-zero number represented in the lowest denomination of the + /// token. The new supply must be lower than 2^63. + /// @param metadata Applicable to tokens of type NON_FUNGIBLE_UNIQUE. A list of metadata that are being created. + /// Maximum allowed size of each metadata is 100 bytes + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return newTotalSupply The new supply of tokens. For NFTs it is the total count of NFTs + /// @return serialNumbers If the token is an NFT the newly generate serial numbers, othersise empty. + function mintToken(address token, uint64 amount, bytes[] memory metadata) external + returns (int responseCode, uint64 newTotalSupply, int64[] memory serialNumbers); + + /// Burns an amount of the token from the defined treasury account + /// @param token The token for which to burn tokens. If token does not exist, transaction results in + /// INVALID_TOKEN_ID + /// @param amount Applicable to tokens of type FUNGIBLE_COMMON. The amount to burn from the Treasury Account. + /// Amount must be a positive non-zero number, not bigger than the token balance of the treasury + /// account (0; balance], represented in the lowest denomination. + /// @param serialNumbers Applicable to tokens of type NON_FUNGIBLE_UNIQUE. The list of serial numbers to be burned. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return newTotalSupply The new supply of tokens. For NFTs it is the total count of NFTs + function burnToken(address token, uint64 amount, int64[] memory serialNumbers) external + returns (int responseCode, uint64 newTotalSupply); + + /// Associates the provided account with the provided tokens. Must be signed by the provided + /// Account's key or called from the accounts contract key + /// If the provided account is not found, the transaction will resolve to INVALID_ACCOUNT_ID. + /// If the provided account has been deleted, the transaction will resolve to ACCOUNT_DELETED. + /// If any of the provided tokens is not found, the transaction will resolve to INVALID_TOKEN_REF. + /// If any of the provided tokens has been deleted, the transaction will resolve to TOKEN_WAS_DELETED. + /// If an association between the provided account and any of the tokens already exists, the + /// transaction will resolve to TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT. + /// If the provided account's associations count exceed the constraint of maximum token associations + /// per account, the transaction will resolve to TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED. + /// On success, associations between the provided account and tokens are made and the account is + /// ready to interact with the tokens. + /// @param account The account to be associated with the provided tokens + /// @param tokens The tokens to be associated with the provided account. In the case of NON_FUNGIBLE_UNIQUE + /// Type, once an account is associated, it can hold any number of NFTs (serial numbers) of that + /// token type + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function associateTokens(address account, address[] memory tokens) external returns (int responseCode); + + /// Single-token variant of associateTokens. Will be mapped to a single entry array call of associateTokens + /// @param account The account to be associated with the provided token + /// @param token The token to be associated with the provided account + function associateToken(address account, address token) external returns (int responseCode); + + /// Dissociates the provided account with the provided tokens. Must be signed by the provided + /// Account's key. + /// If the provided account is not found, the transaction will resolve to INVALID_ACCOUNT_ID. + /// If the provided account has been deleted, the transaction will resolve to ACCOUNT_DELETED. + /// If any of the provided tokens is not found, the transaction will resolve to INVALID_TOKEN_REF. + /// If any of the provided tokens has been deleted, the transaction will resolve to TOKEN_WAS_DELETED. + /// If an association between the provided account and any of the tokens does not exist, the + /// transaction will resolve to TOKEN_NOT_ASSOCIATED_TO_ACCOUNT. + /// If a token has not been deleted and has not expired, and the user has a nonzero balance, the + /// transaction will resolve to TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES. + /// If a fungible token has expired, the user can disassociate even if their token balance is + /// not zero. + /// If a non fungible token has expired, the user can not disassociate if their token + /// balance is not zero. The transaction will resolve to TRANSACTION_REQUIRED_ZERO_TOKEN_BALANCES. + /// On success, associations between the provided account and tokens are removed. + /// @param account The account to be dissociated from the provided tokens + /// @param tokens The tokens to be dissociated from the provided account. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function dissociateTokens(address account, address[] memory tokens) external returns (int responseCode); + + /// Single-token variant of dissociateTokens. Will be mapped to a single entry array call of dissociateTokens + /// @param account The account to be associated with the provided token + /// @param token The token to be associated with the provided account + function dissociateToken(address account, address token) external returns (int responseCode); + + /// Creates a Fungible Token with the specified properties + /// @param token the basic properties of the token being created + /// @param initialTotalSupply Specifies the initial supply of tokens to be put in circulation. The + /// initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible. + /// @param decimals the number of decimal places a token is divisible by + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createFungibleToken( + HederaToken memory token, + uint initialTotalSupply, + uint decimals) + external payable returns (int responseCode, address tokenAddress); + + /// Creates a Fungible Token with the specified properties + /// @param token the basic properties of the token being created + /// @param initialTotalSupply Specifies the initial supply of tokens to be put in circulation. The + /// initial supply is sent to the Treasury Account. The supply is in the lowest denomination possible. + /// @param decimals the number of decimal places a token is divisible by. + /// @param fixedFees list of fixed fees to apply to the token + /// @param fractionalFees list of fractional fees to apply to the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createFungibleTokenWithCustomFees( + HederaToken memory token, + uint initialTotalSupply, + uint decimals, + FixedFee[] memory fixedFees, + FractionalFee[] memory fractionalFees) + external payable returns (int responseCode, address tokenAddress); + + /// Creates an Non Fungible Unique Token with the specified properties + /// @param token the basic properties of the token being created + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createNonFungibleToken(HederaToken memory token) + external payable returns (int responseCode, address tokenAddress); + + /// Creates an Non Fungible Unique Token with the specified properties + /// @param token the basic properties of the token being created + /// @param fixedFees list of fixed fees to apply to the token + /// @param royaltyFees list of royalty fees to apply to the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return tokenAddress the created token's address + function createNonFungibleTokenWithCustomFees( + HederaToken memory token, + FixedFee[] memory fixedFees, + RoyaltyFee[] memory royaltyFees) + external payable returns (int responseCode, address tokenAddress); + + /// Retrieves fungible specific token info for a fungible token + /// @param token The ID of the token as a solidity address + function getFungibleTokenInfo(address token) external returns (int responseCode, FungibleTokenInfo memory tokenInfo); + + /// Retrieves general token info for a given token + /// @param token The ID of the token as a solidity address + function getTokenInfo(address token) external returns (int responseCode, TokenInfo memory tokenInfo); + + /// Retrieves non-fungible specific token info for a given NFT + /// @param token The ID of the token as a solidity address + /// @param serialNumber The serial number of the NFT for which to retrieve information + function getNonFungibleTokenInfo(address token, int64 serialNumber) external returns (int responseCode, NonFungibleTokenInfo memory tokenInfo); + + /// Query token default freeze status + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return defaultFreezeStatus True if `token` default freeze status is frozen. + function getTokenDefaultFreezeStatus(address token) + external + returns (int64 responseCode, bool defaultFreezeStatus); + + /// Query token default kyc status + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return defaultKycStatus True if `token` default kyc status is KycNotApplicable and false if Revoked. + function getTokenDefaultKycStatus(address token) + external + returns (int64 responseCode, bool defaultKycStatus); + + /// Query if token account is frozen + /// @param token The token address to check + /// @param account The account address associated with the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return frozen True if `account` is frozen for `token` + function isFrozen(address token, address account) + external + returns (int64 responseCode, bool frozen); + + /// Query if token account has kyc granted + /// @param token The token address to check + /// @param account The account address associated with the token + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return kycGranted True if `account` has kyc granted for `token` + function isKyc(address token, address account) + external + returns (int64 responseCode, bool kycGranted); + + /// Operation to freeze token account + /// @param token The token address + /// @param account The account address to be frozen + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function freezeToken(address token, address account) + external + returns (int64 responseCode); + + /// Operation to unfreeze token account + /// @param token The token address + /// @param account The account address to be unfrozen + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function unfreezeToken(address token, address account) + external + returns (int64 responseCode); + + /// Operation to grant kyc to token account + /// @param token The token address + /// @param account The account address to grant kyc + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function grantTokenKyc(address token, address account) + external + returns (int64 responseCode); + + /// Operation to revoke kyc to token account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function revokeTokenKyc(address token, address account) + external + returns (int64 responseCode); + + /// Query token custom fees + /// @param token The token address to check + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return fixedFees Set of fixed fees for `token` + /// @return fractionalFees Set of fractional fees for `token` + /// @return royaltyFees Set of royalty fees for `token` + function getTokenCustomFees(address token) + external + returns (int64 responseCode, FixedFee[] memory fixedFees, FractionalFee[] memory fractionalFees, RoyaltyFee[] memory royaltyFees); + + /********************** + * ABIV1 calls * + **********************/ + + /// Initiates a Fungible Token Transfer + /// @param token The ID of the token as a solidity address + /// @param accountId account to do a transfer to/from + /// @param amount The amount from the accountId at the same index + function transferTokens(address token, address[] memory accountId, int64[] memory amount) external + returns (int responseCode); + + /// Initiates a Non-Fungable Token Transfer + /// @param token The ID of the token as a solidity address + /// @param sender the sender of an nft + /// @param receiver the receiver of the nft sent by the same index at sender + /// @param serialNumber the serial number of the nft sent by the same index at sender + function transferNFTs(address token, address[] memory sender, address[] memory receiver, int64[] memory serialNumber) + external returns (int responseCode); + + /// Transfers tokens where the calling account/contract is implicitly the first entry in the token transfer list, + /// where the amount is the value needed to zero balance the transfers. Regular signing rules apply for sending + /// (positive amount) or receiving (negative amount) + /// @param token The token to transfer to/from + /// @param sender The sender for the transaction + /// @param recipient The receiver of the transaction + /// @param amount Non-negative value to send. a negative value will result in a failure. + function transferToken(address token, address sender, address recipient, int64 amount) external + returns (int responseCode); + + /// Transfers tokens where the calling account/contract is implicitly the first entry in the token transfer list, + /// where the amount is the value needed to zero balance the transfers. Regular signing rules apply for sending + /// (positive amount) or receiving (negative amount) + /// @param token The token to transfer to/from + /// @param sender The sender for the transaction + /// @param recipient The receiver of the transaction + /// @param serialNumber The serial number of the NFT to transfer. + function transferNFT(address token, address sender, address recipient, int64 serialNumber) external + returns (int responseCode); + + /// Operation to pause token + /// @param token The token address to be paused + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function pauseToken(address token) external returns (int responseCode); + + /// Operation to unpause token + /// @param token The token address to be unpaused + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function unpauseToken(address token) external returns (int responseCode); + + /// Allows spender to withdraw from your account multiple times, up to the value amount. If this function is called + /// again it overwrites the current allowance with value. + /// Only Applicable to Fungible Tokens + /// @param token The hedera token address to approve + /// @param spender the account address authorized to spend + /// @param amount the amount of tokens authorized to spend. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function approve(address token, address spender, uint256 amount) external returns (int responseCode, bool success); + + /// Returns the amount which spender is still allowed to withdraw from owner. + /// Only Applicable to Fungible Tokens + /// @param token The Hedera token address to check the allowance of + /// @param owner the owner of the tokens to be spent + /// @param spender the spender of the tokens + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function allowance(address token, address owner, address spender) external returns (int responseCode); + + /// Allow or reaffirm the approved address to transfer an NFT the approved address does not own. + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to approve + /// @param approved The new approved NFT controller. To revoke approvals pass in the zero address. + /// @param serialNumber The NFT serial number to approve + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function approveNFT(address token, address approved, uint256 serialNumber) external returns (int responseCode); + + /// Get the approved address for a single NFT + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to check approval + /// @param serialNumber The NFT to find the approved address for + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return approved The approved address for this NFT, or the zero address if there is none + function getApproved(address token, uint256 serialNumber) external returns (int responseCode, address approved); + + /// Enable or disable approval for a third party ("operator") to manage + /// all of `msg.sender`'s assets + /// @param token The Hedera NFT token address to approve + /// @param operator Address to add to the set of authorized operators + /// @param approved True if the operator is approved, false to revoke approval + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function setApprovalForAll(address token, address operator, bool approved) external returns (int responseCode); + + /// Query if an address is an authorized operator for another address + /// Only Applicable to NFT Tokens + /// @param token The Hedera NFT token address to approve + /// @param owner The address that owns the NFTs + /// @param operator The address that acts on behalf of the owner + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return approved True if `operator` is an approved operator for `owner`, false otherwise + function isApprovedForAll(address token, address owner, address operator) external returns (int responseCode, bool approved); + + /// Operation to wipe fungible tokens from account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @param amount The number of tokens to wipe + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function wipeTokenAccount(address token, address account, uint32 amount) external returns (int responseCode); + + /// Operation to wipe non fungible tokens from account + /// @param token The token address + /// @param account The account address to revoke kyc + /// @param serialNumbers The serial numbers of token to wipe + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function wipeTokenAccountNFT(address token, address account, int64[] memory serialNumbers) external + returns (int responseCode); + + /// Operation to delete token + /// @param token The token address to be deleted + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function deleteToken(address token) external returns (int responseCode); + + /// Operation to get token expiry info + /// @param token The token address + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return expiryInfo The expiry info of the token + function getTokenExpiryInfo(address token) external returns (int responseCode, Expiry memory expiryInfo); + + /// Operation to update token expiry info + /// @param token The token address + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function updateTokenExpiryInfo(address token, Expiry memory expiryInfo) external returns (int responseCode); +} diff --git a/packages/server/tests/contracts/contracts_v1/KeyHelper.json b/packages/server/tests/contracts/contracts_v1/KeyHelper.json new file mode 100644 index 0000000000..b8861022e5 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/KeyHelper.json @@ -0,0 +1,49 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "KeyHelper", + "sourceName": "contracts/KeyHelper.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/packages/server/tests/contracts/contracts_v1/KeyHelper.sol b/packages/server/tests/contracts/contracts_v1/KeyHelper.sol new file mode 100644 index 0000000000..6735bd8b74 --- /dev/null +++ b/packages/server/tests/contracts/contracts_v1/KeyHelper.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./HederaTokenService.sol"; + +abstract contract KeyHelper is HederaTokenService { + + using Bits for uint; + address supplyContract; + + function getDefaultKeys() internal view returns (IHederaTokenService.TokenKey[] memory keys) { + keys = new IHederaTokenService.TokenKey[](2); + keys[0] = getSingleKey(1, 1, ""); + keys[1] = IHederaTokenService.TokenKey (getDuplexKeyType(4, 6), getKeyValueType(2, "")); + } + + function getAllTypeKeys(uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.TokenKey[] memory keys) { + keys = new IHederaTokenService.TokenKey[](1); + keys[0] = IHederaTokenService.TokenKey (getAllKeyTypes(), getKeyValueType(keyValueType, key)); + } + + function getCustomSingleTypeKeys(uint8 keyType, uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.TokenKey[] memory keys) { + keys = new IHederaTokenService.TokenKey[](1); + keys[0] = IHederaTokenService.TokenKey (getKeyType(keyType), getKeyValueType(keyValueType, key)); + } + + function getCustomDuplexTypeKeys(uint8 firstType, uint8 secondType, uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.TokenKey[] memory keys) { + keys = new IHederaTokenService.TokenKey[](1); + keys[0] = IHederaTokenService.TokenKey (getDuplexKeyType(firstType, secondType), getKeyValueType(keyValueType, key)); + } + + function getSingleKey(uint8 keyType, uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.TokenKey memory tokenKey) { + tokenKey = IHederaTokenService.TokenKey (getKeyType(keyType), getKeyValueType(keyValueType, key)); + } + + function getSingleKey(uint8 keyType, uint8 keyValueType, address key) internal pure returns (IHederaTokenService.TokenKey memory tokenKey) { + tokenKey = IHederaTokenService.TokenKey (getKeyType(keyType), getKeyValueType(keyValueType, key)); + } + + function getSingleKey(uint8 firstType, uint8 secondType, uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.TokenKey memory tokenKey) { + tokenKey = IHederaTokenService.TokenKey (getDuplexKeyType(firstType, secondType), getKeyValueType(keyValueType, key)); + } + + function getDuplexKeyType(uint8 firstType, uint8 secondType) internal pure returns (uint keyType) { + keyType = keyType.setBit(firstType); + keyType = keyType.setBit(secondType); + } + + function getAllKeyTypes() internal pure returns (uint keyType) { + keyType = keyType.setBit(0); + keyType = keyType.setBit(1); + keyType = keyType.setBit(2); + keyType = keyType.setBit(3); + keyType = keyType.setBit(4); + keyType = keyType.setBit(5); + keyType = keyType.setBit(6); + } + + function getKeyType(uint8 keyType) internal pure returns (uint) { + if (keyType == 0) { + return HederaTokenService.ADMIN_KEY_TYPE; + } else if(keyType == 1) { + return HederaTokenService.KYC_KEY_TYPE; + } else if(keyType == 2) { + return HederaTokenService.FREEZE_KEY_TYPE; + } else if(keyType == 3) { + return HederaTokenService.WIPE_KEY_TYPE; + } else if(keyType == 4) { + return HederaTokenService.SUPPLY_KEY_TYPE; + } else if(keyType == 5) { + return HederaTokenService.FEE_SCHEDULE_KEY_TYPE; + } else if(keyType == 6) { + return HederaTokenService.PAUSE_KEY_TYPE; + } + + return 0; + } + + function getKeyValueType(uint8 keyValueType, bytes memory key) internal view returns (IHederaTokenService.KeyValue memory keyValue) { + if(keyValueType == 1) { + keyValue.inheritAccountKey = true; + } else if(keyValueType == 2) { + keyValue.contractId = supplyContract; + } else if(keyValueType == 3) { + keyValue.ed25519 = key; + } else if(keyValueType == 4) { + keyValue.ECDSA_secp256k1 = key; + } else if(keyValueType == 5) { + keyValue.delegatableContractId = supplyContract; + } + } + + function getKeyValueType(uint8 keyValueType, address keyAddress) internal pure returns (IHederaTokenService.KeyValue memory keyValue) { + if (keyValueType == 2) { + keyValue.contractId = keyAddress; + } else if(keyValueType == 5) { + keyValue.delegatableContractId = keyAddress; + } + } +} + +library Bits { + + uint constant internal ONE = uint(1); + + // Sets the bit at the given 'index' in 'self' to '1'. + // Returns the modified value. + function setBit(uint self, uint8 index) internal pure returns (uint) { + return self | ONE << index; + } +}