diff --git a/.github/workflows/dapp-playground-workflow.yml b/.github/workflows/dapp-playground-workflow.yml index 6359014f2..a7de0494f 100644 --- a/.github/workflows/dapp-playground-workflow.yml +++ b/.github/workflows/dapp-playground-workflow.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 diff --git a/.github/workflows/erc-registry-indexer.yml b/.github/workflows/erc-registry-indexer.yml index 8b0439fec..1d0686c47 100644 --- a/.github/workflows/erc-registry-indexer.yml +++ b/.github/workflows/erc-registry-indexer.yml @@ -35,7 +35,7 @@ jobs: submodules: recursive - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 diff --git a/.github/workflows/erc-registry-test.yml b/.github/workflows/erc-registry-test.yml index ca0d8a52f..e3a56bade 100644 --- a/.github/workflows/erc-registry-test.yml +++ b/.github/workflows/erc-registry-test.yml @@ -25,7 +25,7 @@ jobs: submodules: recursive - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 diff --git a/.github/workflows/foundry_test.yml b/.github/workflows/foundry_test.yml index d32c17f5e..d32025332 100644 --- a/.github/workflows/foundry_test.yml +++ b/.github/workflows/foundry_test.yml @@ -27,7 +27,7 @@ jobs: submodules: recursive - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 #cache: npm Disabling this because it causes the workflow to hang and eventually timeout diff --git a/.github/workflows/migration-testing.yml b/.github/workflows/migration-testing.yml index d21efb6c0..b5c712be4 100644 --- a/.github/workflows/migration-testing.yml +++ b/.github/workflows/migration-testing.yml @@ -54,7 +54,7 @@ jobs: submodules: recursive - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 #cache: npm Disabling this because it causes the workflow to hang and eventually timeout diff --git a/.github/workflows/opcode-logger-testing.yml b/.github/workflows/opcode-logger-testing.yml index 5600b74b6..afe73a2cf 100644 --- a/.github/workflows/opcode-logger-testing.yml +++ b/.github/workflows/opcode-logger-testing.yml @@ -29,7 +29,7 @@ jobs: sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 #cache: npm Disabling this because it causes the workflow to hang and eventually timeout diff --git a/.github/workflows/pr-label-milestone-check.yml b/.github/workflows/pr-label-milestone-check.yml index d7a80f81c..f321d5371 100644 --- a/.github/workflows/pr-label-milestone-check.yml +++ b/.github/workflows/pr-label-milestone-check.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up Node.js - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '20' diff --git a/.github/workflows/release-automation.yml b/.github/workflows/release-automation.yml index 3cf07a80d..2ae15bdd7 100644 --- a/.github/workflows/release-automation.yml +++ b/.github/workflows/release-automation.yml @@ -87,7 +87,7 @@ jobs: fi - name: Set up Node.js - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '20' @@ -164,7 +164,7 @@ jobs: passphrase: ${{ secrets.GPG_KEY_PASSPHRASE }} - name: Set up Node.js - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '20' diff --git a/.github/workflows/test-workflow.yml b/.github/workflows/test-workflow.yml index 9914a2887..9b8eb1eab 100644 --- a/.github/workflows/test-workflow.yml +++ b/.github/workflows/test-workflow.yml @@ -50,7 +50,7 @@ jobs: sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose - name: Use Node.js [20] - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 #cache: npm Disabling this because it causes the workflow to hang and eventually timeout diff --git a/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json b/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json index 5549b1ed4..ccfec44f5 100644 --- a/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json +++ b/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json @@ -194,6 +194,11 @@ "internalType": "address[]", "name": "receivers", "type": "address[]" + }, + { + "internalType": "int64[]", + "name": "serials", + "type": "int64[]" } ], "name": "nftAirdropDistribute", @@ -373,8 +378,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b50611a968061001d5f395ff3fe60806040526004361061008f575f3560e01c8063618dc65e11610057578063618dc65e14610122578063913073f91461014f5780639b23d3d9146101625780639ef773bf14610181578063ba7ee6e514610194575f80fd5b8063061f87391461009357806315dacbea146100be5780631b79e5f9146100dd5780634e395634146100f057806352c0d7d41461010f575b5f80fd5b6100a66100a136600461130a565b6101a7565b60405160079190910b81526020015b60405180910390f35b3480156100c9575f80fd5b506100a66100d8366004611375565b6102e3565b6100a66100eb3660046113bd565b6103d2565b3480156100fb575f80fd5b506100a661010a36600461144a565b61049e565b6100a661011d3660046113bd565b610664565b34801561012d575f80fd5b5061014161013c3660046114ca565b6107d7565b6040516100b59291906115b7565b6100a661015d3660046115d7565b6108ee565b34801561016d575f80fd5b506100a661017c366004611375565b610b42565b6100a661018f366004611637565b610b86565b6100a66101a2366004611757565b610e66565b83515f90818167ffffffffffffffff8111156101c5576101c5611203565b60405190808252806020026020018201604052801561022257816020015b61020f60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816101e35790505b5090505f5b828110156102bd5761025b60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061026d5761026d6117b1565b60209081029190910101516001600160a01b0316815261028e888888611048565b8160200181905250808383815181106102a9576102a96117b1565b602090810291909101015250600101610227565b506102c78161112f565b9250600783900b6016146102d9575f80fd5b5050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161036191906117c5565b5f604051808303815f865af19150503d805f811461039a576040519150601f19603f3d011682016040523d82523d5f602084013e61039f565b606091505b5091509150816103b05760156103c4565b808060200190518101906103c491906117e0565b60030b979650505050505050565b6040805160018082528183019092525f91829190816020015b61041760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816103eb57905050905061045860405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038716815261046f868686611048565b816020018190525080825f8151811061048a5761048a6117b1565b60200260200101819052506102c78261112f565b83515f90818167ffffffffffffffff8111156104bc576104bc611203565b60405190808252806020026020018201604052801561051957816020015b61050660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816104da5790505b5090505f5b828110156102bd5761055260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b888281518110610564576105646117b1565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161059057905050905061061689898986815181106105db576105db6117b1565b6020026020010151604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b815f81518110610628576106286117b1565b60200260200101819052508082604001819052508184848151811061064f5761064f6117b1565b6020908102919091010152505060010161051e565b6040805160018082528183019092525f91829190816020015b6106a960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161067d5790505090506106ea60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038781168252604080516080810182525f606082018190528984168252928816602080830191909152600788900b82840152825160018082528185019094529193929082015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161073757905050905081815f8151811061077e5761077e6117b1565b602002602001018190525080836040018190525082845f815181106107a5576107a56117b1565b60200260200101819052506107b98461112f565b9450600785900b6016146107cb575f80fd5b50505050949350505050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610803929190611807565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161084191906117c5565b5f604051808303815f865af19150503d805f811461087a576040519150601f19603f3d011682016040523d82523d5f602084013e61087f565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516108b5929190611828565b60405180910390a1816108d857601560405180602001604052805f8152506108dc565b6016815b60039190910b97909650945050505050565b5f80835160016108fe9190611856565b6040805160018082528183019092529192505f9190816020015b61094460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161091857905050905061098560405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038881168252604080516060810182525f602082018190529181018290529189168252805b88518110156109ce576109c4888361186f565b91506001016109b1565b506109d88161189e565b60070b60208301525f8567ffffffffffffffff8111156109fa576109fa611203565b604051908082528060200260200182016040528015610a4357816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610a185790505b50905082815f81518110610a5957610a596117b1565b602090810291909101015260015b86811015610af157604080516060810182525f80825260208201819052918101919091528a610a976001846118c3565b81518110610aa757610aa76117b1565b6020908102919091018101516001600160a01b0316825260078b900b9082015282518190849084908110610add57610add6117b1565b602090810291909101015250600101610a67565b5080846020018190525083855f81518110610b0e57610b0e6117b1565b6020026020010181905250610b228561112f565b9650600787900b601614610b34575f80fd5b505050505050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610323565b5f8085518851610b969190611856565b90505f8167ffffffffffffffff811115610bb257610bb2611203565b604051908082528060200260200182016040528015610c0f57816020015b610bfc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610bd05790505b5090505f5b8951811015610ce057610c4960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610c5b57610c5b6117b1565b60209081029190910101516001600160a01b031681528a51610cb1908c9084908110610c8957610c896117b1565b60200260200101518b8481518110610ca357610ca36117b1565b602002602001015189611048565b816020018190525080838381518110610ccc57610ccc6117b1565b602090810291909101015250600101610c14565b5088515f5b83821015610e3b57610d1960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610d2b57610d2b6117b1565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610d57579050509050610dd48b8481518110610da057610da06117b1565b60200260200101518b8581518110610dba57610dba6117b1565b60200260200101518a86815181106105db576105db6117b1565b815f81518110610de657610de66117b1565b602002602001018190525080826040018190525081858581518110610e0d57610e0d6117b1565b60200260200101819052508380610e23906118d6565b94505050508080610e33906118d6565b915050610ce5565b50610e458261112f565b9350600784900b601614610e57575f80fd5b50505098975050505050505050565b80516040805160018082528183019092525f9291839190816020015b610eae60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610e82579050509050610eef60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b03871681525f8367ffffffffffffffff811115610f1557610f15611203565b604051908082528060200260200182016040528015610f6557816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610f335790505b50905060015f5b85811015610ff957610fc689898381518110610f8a57610f8a6117b1565b602002602001015184604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b838281518110610fd857610fd86117b1565b60200260200101819052508180610fee906118ee565b925050600101610f6c565b5081836040018190525082845f81518110611016576110166117b1565b602002602001018190525061102a8461112f565b9550600786900b60161461103c575f80fd5b50505050509392505050565b60408051606080820183525f60208301819052928201929092526001600160a01b03851681526110778361189e565b600790810b60208381019190915260408051606080820183525f828401526001600160a01b03891682529387900b818401528151600280825294810190925292909182015b604080516060810182525f80825260208083018290529282015282525f199092019101816110bc57905050925081835f815181106110fc576110fc6117b1565b6020026020010181905250808360018151811061111b5761111b6117b1565b602002602001018190525050509392505050565b5f805f6101676001600160a01b0316632f34811960e01b85604051602401611157919061197e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161119591906117c5565b5f604051808303815f865af19150503d805f81146111ce576040519150601f19603f3d011682016040523d82523d5f602084013e6111d3565b606091505b5091509150816111e45760156111f8565b808060200190518101906111f891906117e0565b60030b949350505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561124057611240611203565b604052919050565b5f67ffffffffffffffff82111561126157611261611203565b5060051b60200190565b80356001600160a01b0381168114611281575f80fd5b919050565b5f82601f830112611295575f80fd5b813560206112aa6112a583611248565b611217565b8083825260208201915060208460051b8701019350868411156112cb575f80fd5b602086015b848110156112ee576112e18161126b565b83529183019183016112d0565b509695505050505050565b8035600781900b8114611281575f80fd5b5f805f806080858703121561131d575f80fd5b843567ffffffffffffffff811115611333575f80fd5b61133f87828801611286565b94505061134e6020860161126b565b925061135c6040860161126b565b915061136a606086016112f9565b905092959194509250565b5f805f8060808587031215611388575f80fd5b6113918561126b565b935061139f6020860161126b565b92506113ad6040860161126b565b9396929550929360600135925050565b5f805f80608085870312156113d0575f80fd5b6113d98561126b565b935061134e6020860161126b565b5f82601f8301126113f6575f80fd5b813560206114066112a583611248565b8083825260208201915060208460051b870101935086841115611427575f80fd5b602086015b848110156112ee5761143d816112f9565b835291830191830161142c565b5f805f806080858703121561145d575f80fd5b843567ffffffffffffffff80821115611474575f80fd5b61148088838901611286565b955061148e6020880161126b565b945061149c6040880161126b565b935060608701359150808211156114b1575f80fd5b506114be878288016113e7565b91505092959194509250565b5f80604083850312156114db575f80fd5b6114e48361126b565b915060208084013567ffffffffffffffff80821115611501575f80fd5b818601915086601f830112611514575f80fd5b81358181111561152657611526611203565b611538601f8201601f19168501611217565b9150808252878482850101111561154d575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b8381101561158457818101518382015260200161156c565b50505f910152565b5f81518084526115a381602086016020860161156a565b601f01601f19169290920160200192915050565b828152604060208201525f6115cf604083018461158c565b949350505050565b5f805f80608085870312156115ea575f80fd5b6115f38561126b565b93506116016020860161126b565b9250604085013567ffffffffffffffff81111561161c575f80fd5b61162887828801611286565b92505061136a606086016112f9565b5f805f805f805f80610100898b03121561164f575f80fd5b883567ffffffffffffffff80821115611666575f80fd5b6116728c838d01611286565b995060208b0135915080821115611687575f80fd5b6116938c838d01611286565b985060408b01359150808211156116a8575f80fd5b6116b48c838d01611286565b975060608b01359150808211156116c9575f80fd5b6116d58c838d01611286565b965060808b01359150808211156116ea575f80fd5b6116f68c838d01611286565b955060a08b013591508082111561170b575f80fd5b6117178c838d01611286565b945061172560c08c016112f9565b935060e08b013591508082111561173a575f80fd5b506117478b828c016113e7565b9150509295985092959890939650565b5f805f60608486031215611769575f80fd5b6117728461126b565b92506117806020850161126b565b9150604084013567ffffffffffffffff81111561179b575f80fd5b6117a786828701611286565b9150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f82516117d681846020870161156a565b9190910192915050565b5f602082840312156117f0575f80fd5b81518060030b8114611800575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f6115cf604083018461158c565b8215158152604060208201525f6115cf604083018461158c565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561186957611869611842565b92915050565b600781810b9083900b01677fffffffffffffff8113677fffffffffffffff198212171561186957611869611842565b5f8160070b677fffffffffffffff1981036118bb576118bb611842565b5f0392915050565b8181038181111561186957611869611842565b5f600182016118e7576118e7611842565b5060010190565b5f8160070b677fffffffffffffff810361190a5761190a611842565b60010192915050565b5f815180845260208085019450602084015f5b8381101561197357815180516001600160a01b03908116895284820151168489015260408082015160070b9089015260609081015115159088015260809096019590820190600101611926565b509495945050505050565b5f6020808301818452808551808352604092508286019150828160051b8701018488015f5b83811015611a5257603f19898403018552815160608085016001600160a01b038084511687528a840151838c89015282815180855260808a0191508d830194505f92505b80831015611a1f5784518051851683528e81015160070b8f8401528d015115158d830152938d019360019290920191908501906119e7565b50948b0151888603898d015294611a368187611913565b9a8d019a98505050948a019450505060019190910190506119a3565b50909897505050505050505056fea2646970667358221220f3edc52973a89d7453e0eeadc6aabbc37d24f3516c1e6432c89299fa3779647164736f6c63430008180033", - "deployedBytecode": "0x60806040526004361061008f575f3560e01c8063618dc65e11610057578063618dc65e14610122578063913073f91461014f5780639b23d3d9146101625780639ef773bf14610181578063ba7ee6e514610194575f80fd5b8063061f87391461009357806315dacbea146100be5780631b79e5f9146100dd5780634e395634146100f057806352c0d7d41461010f575b5f80fd5b6100a66100a136600461130a565b6101a7565b60405160079190910b81526020015b60405180910390f35b3480156100c9575f80fd5b506100a66100d8366004611375565b6102e3565b6100a66100eb3660046113bd565b6103d2565b3480156100fb575f80fd5b506100a661010a36600461144a565b61049e565b6100a661011d3660046113bd565b610664565b34801561012d575f80fd5b5061014161013c3660046114ca565b6107d7565b6040516100b59291906115b7565b6100a661015d3660046115d7565b6108ee565b34801561016d575f80fd5b506100a661017c366004611375565b610b42565b6100a661018f366004611637565b610b86565b6100a66101a2366004611757565b610e66565b83515f90818167ffffffffffffffff8111156101c5576101c5611203565b60405190808252806020026020018201604052801561022257816020015b61020f60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816101e35790505b5090505f5b828110156102bd5761025b60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061026d5761026d6117b1565b60209081029190910101516001600160a01b0316815261028e888888611048565b8160200181905250808383815181106102a9576102a96117b1565b602090810291909101015250600101610227565b506102c78161112f565b9250600783900b6016146102d9575f80fd5b5050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161036191906117c5565b5f604051808303815f865af19150503d805f811461039a576040519150601f19603f3d011682016040523d82523d5f602084013e61039f565b606091505b5091509150816103b05760156103c4565b808060200190518101906103c491906117e0565b60030b979650505050505050565b6040805160018082528183019092525f91829190816020015b61041760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816103eb57905050905061045860405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038716815261046f868686611048565b816020018190525080825f8151811061048a5761048a6117b1565b60200260200101819052506102c78261112f565b83515f90818167ffffffffffffffff8111156104bc576104bc611203565b60405190808252806020026020018201604052801561051957816020015b61050660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816104da5790505b5090505f5b828110156102bd5761055260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b888281518110610564576105646117b1565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161059057905050905061061689898986815181106105db576105db6117b1565b6020026020010151604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b815f81518110610628576106286117b1565b60200260200101819052508082604001819052508184848151811061064f5761064f6117b1565b6020908102919091010152505060010161051e565b6040805160018082528183019092525f91829190816020015b6106a960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161067d5790505090506106ea60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038781168252604080516080810182525f606082018190528984168252928816602080830191909152600788900b82840152825160018082528185019094529193929082015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161073757905050905081815f8151811061077e5761077e6117b1565b602002602001018190525080836040018190525082845f815181106107a5576107a56117b1565b60200260200101819052506107b98461112f565b9450600785900b6016146107cb575f80fd5b50505050949350505050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610803929190611807565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161084191906117c5565b5f604051808303815f865af19150503d805f811461087a576040519150601f19603f3d011682016040523d82523d5f602084013e61087f565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516108b5929190611828565b60405180910390a1816108d857601560405180602001604052805f8152506108dc565b6016815b60039190910b97909650945050505050565b5f80835160016108fe9190611856565b6040805160018082528183019092529192505f9190816020015b61094460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161091857905050905061098560405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038881168252604080516060810182525f602082018190529181018290529189168252805b88518110156109ce576109c4888361186f565b91506001016109b1565b506109d88161189e565b60070b60208301525f8567ffffffffffffffff8111156109fa576109fa611203565b604051908082528060200260200182016040528015610a4357816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610a185790505b50905082815f81518110610a5957610a596117b1565b602090810291909101015260015b86811015610af157604080516060810182525f80825260208201819052918101919091528a610a976001846118c3565b81518110610aa757610aa76117b1565b6020908102919091018101516001600160a01b0316825260078b900b9082015282518190849084908110610add57610add6117b1565b602090810291909101015250600101610a67565b5080846020018190525083855f81518110610b0e57610b0e6117b1565b6020026020010181905250610b228561112f565b9650600787900b601614610b34575f80fd5b505050505050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610323565b5f8085518851610b969190611856565b90505f8167ffffffffffffffff811115610bb257610bb2611203565b604051908082528060200260200182016040528015610c0f57816020015b610bfc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610bd05790505b5090505f5b8951811015610ce057610c4960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610c5b57610c5b6117b1565b60209081029190910101516001600160a01b031681528a51610cb1908c9084908110610c8957610c896117b1565b60200260200101518b8481518110610ca357610ca36117b1565b602002602001015189611048565b816020018190525080838381518110610ccc57610ccc6117b1565b602090810291909101015250600101610c14565b5088515f5b83821015610e3b57610d1960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610d2b57610d2b6117b1565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610d57579050509050610dd48b8481518110610da057610da06117b1565b60200260200101518b8581518110610dba57610dba6117b1565b60200260200101518a86815181106105db576105db6117b1565b815f81518110610de657610de66117b1565b602002602001018190525080826040018190525081858581518110610e0d57610e0d6117b1565b60200260200101819052508380610e23906118d6565b94505050508080610e33906118d6565b915050610ce5565b50610e458261112f565b9350600784900b601614610e57575f80fd5b50505098975050505050505050565b80516040805160018082528183019092525f9291839190816020015b610eae60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610e82579050509050610eef60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b03871681525f8367ffffffffffffffff811115610f1557610f15611203565b604051908082528060200260200182016040528015610f6557816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610f335790505b50905060015f5b85811015610ff957610fc689898381518110610f8a57610f8a6117b1565b602002602001015184604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b838281518110610fd857610fd86117b1565b60200260200101819052508180610fee906118ee565b925050600101610f6c565b5081836040018190525082845f81518110611016576110166117b1565b602002602001018190525061102a8461112f565b9550600786900b60161461103c575f80fd5b50505050509392505050565b60408051606080820183525f60208301819052928201929092526001600160a01b03851681526110778361189e565b600790810b60208381019190915260408051606080820183525f828401526001600160a01b03891682529387900b818401528151600280825294810190925292909182015b604080516060810182525f80825260208083018290529282015282525f199092019101816110bc57905050925081835f815181106110fc576110fc6117b1565b6020026020010181905250808360018151811061111b5761111b6117b1565b602002602001018190525050509392505050565b5f805f6101676001600160a01b0316632f34811960e01b85604051602401611157919061197e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161119591906117c5565b5f604051808303815f865af19150503d805f81146111ce576040519150601f19603f3d011682016040523d82523d5f602084013e6111d3565b606091505b5091509150816111e45760156111f8565b808060200190518101906111f891906117e0565b60030b949350505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561124057611240611203565b604052919050565b5f67ffffffffffffffff82111561126157611261611203565b5060051b60200190565b80356001600160a01b0381168114611281575f80fd5b919050565b5f82601f830112611295575f80fd5b813560206112aa6112a583611248565b611217565b8083825260208201915060208460051b8701019350868411156112cb575f80fd5b602086015b848110156112ee576112e18161126b565b83529183019183016112d0565b509695505050505050565b8035600781900b8114611281575f80fd5b5f805f806080858703121561131d575f80fd5b843567ffffffffffffffff811115611333575f80fd5b61133f87828801611286565b94505061134e6020860161126b565b925061135c6040860161126b565b915061136a606086016112f9565b905092959194509250565b5f805f8060808587031215611388575f80fd5b6113918561126b565b935061139f6020860161126b565b92506113ad6040860161126b565b9396929550929360600135925050565b5f805f80608085870312156113d0575f80fd5b6113d98561126b565b935061134e6020860161126b565b5f82601f8301126113f6575f80fd5b813560206114066112a583611248565b8083825260208201915060208460051b870101935086841115611427575f80fd5b602086015b848110156112ee5761143d816112f9565b835291830191830161142c565b5f805f806080858703121561145d575f80fd5b843567ffffffffffffffff80821115611474575f80fd5b61148088838901611286565b955061148e6020880161126b565b945061149c6040880161126b565b935060608701359150808211156114b1575f80fd5b506114be878288016113e7565b91505092959194509250565b5f80604083850312156114db575f80fd5b6114e48361126b565b915060208084013567ffffffffffffffff80821115611501575f80fd5b818601915086601f830112611514575f80fd5b81358181111561152657611526611203565b611538601f8201601f19168501611217565b9150808252878482850101111561154d575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b8381101561158457818101518382015260200161156c565b50505f910152565b5f81518084526115a381602086016020860161156a565b601f01601f19169290920160200192915050565b828152604060208201525f6115cf604083018461158c565b949350505050565b5f805f80608085870312156115ea575f80fd5b6115f38561126b565b93506116016020860161126b565b9250604085013567ffffffffffffffff81111561161c575f80fd5b61162887828801611286565b92505061136a606086016112f9565b5f805f805f805f80610100898b03121561164f575f80fd5b883567ffffffffffffffff80821115611666575f80fd5b6116728c838d01611286565b995060208b0135915080821115611687575f80fd5b6116938c838d01611286565b985060408b01359150808211156116a8575f80fd5b6116b48c838d01611286565b975060608b01359150808211156116c9575f80fd5b6116d58c838d01611286565b965060808b01359150808211156116ea575f80fd5b6116f68c838d01611286565b955060a08b013591508082111561170b575f80fd5b6117178c838d01611286565b945061172560c08c016112f9565b935060e08b013591508082111561173a575f80fd5b506117478b828c016113e7565b9150509295985092959890939650565b5f805f60608486031215611769575f80fd5b6117728461126b565b92506117806020850161126b565b9150604084013567ffffffffffffffff81111561179b575f80fd5b6117a786828701611286565b9150509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f82516117d681846020870161156a565b9190910192915050565b5f602082840312156117f0575f80fd5b81518060030b8114611800575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f6115cf604083018461158c565b8215158152604060208201525f6115cf604083018461158c565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561186957611869611842565b92915050565b600781810b9083900b01677fffffffffffffff8113677fffffffffffffff198212171561186957611869611842565b5f8160070b677fffffffffffffff1981036118bb576118bb611842565b5f0392915050565b8181038181111561186957611869611842565b5f600182016118e7576118e7611842565b5060010190565b5f8160070b677fffffffffffffff810361190a5761190a611842565b60010192915050565b5f815180845260208085019450602084015f5b8381101561197357815180516001600160a01b03908116895284820151168489015260408082015160070b9089015260609081015115159088015260809096019590820190600101611926565b509495945050505050565b5f6020808301818452808551808352604092508286019150828160051b8701018488015f5b83811015611a5257603f19898403018552815160608085016001600160a01b038084511687528a840151838c89015282815180855260808a0191508d830194505f92505b80831015611a1f5784518051851683528e81015160070b8f8401528d015115158d830152938d019360019290920191908501906119e7565b50948b0151888603898d015294611a368187611913565b9a8d019a98505050948a019450505060019190910190506119a3565b50909897505050505050505056fea2646970667358221220f3edc52973a89d7453e0eeadc6aabbc37d24f3516c1e6432c89299fa3779647164736f6c63430008180033", + "bytecode": "0x608060405234801561000f575f80fd5b50611a198061001d5f395ff3fe60806040526004361061008f575f3560e01c8063618dc65e11610057578063618dc65e14610122578063913073f91461014f5780639b23d3d9146101625780639ef773bf14610181578063c4d7ff7c14610194575f80fd5b8063061f87391461009357806315dacbea146100be5780631b79e5f9146100dd5780634e395634146100f057806352c0d7d41461010f575b5f80fd5b6100a66100a13660046112ba565b6101a7565b60405160079190910b81526020015b60405180910390f35b3480156100c9575f80fd5b506100a66100d8366004611325565b6102e3565b6100a66100eb36600461136d565b6103d2565b3480156100fb575f80fd5b506100a661010a3660046113fa565b61049e565b6100a661011d36600461136d565b610664565b34801561012d575f80fd5b5061014161013c36600461147a565b6107d7565b6040516100b5929190611567565b6100a661015d366004611587565b6108ee565b34801561016d575f80fd5b506100a661017c366004611325565b610b42565b6100a661018f3660046115e7565b610b86565b6100a66101a2366004611707565b610e66565b83515f90818167ffffffffffffffff8111156101c5576101c56111b3565b60405190808252806020026020018201604052801561022257816020015b61020f60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816101e35790505b5090505f5b828110156102bd5761025b60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061026d5761026d611759565b60209081029190910101516001600160a01b0316815261028e888888610ff8565b8160200181905250808383815181106102a9576102a9611759565b602090810291909101015250600101610227565b506102c7816110df565b9250600783900b6016146102d9575f80fd5b5050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610361919061176d565b5f604051808303815f865af19150503d805f811461039a576040519150601f19603f3d011682016040523d82523d5f602084013e61039f565b606091505b5091509150816103b05760156103c4565b808060200190518101906103c49190611788565b60030b979650505050505050565b6040805160018082528183019092525f91829190816020015b61041760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816103eb57905050905061045860405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038716815261046f868686610ff8565b816020018190525080825f8151811061048a5761048a611759565b60200260200101819052506102c7826110df565b83515f90818167ffffffffffffffff8111156104bc576104bc6111b3565b60405190808252806020026020018201604052801561051957816020015b61050660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816104da5790505b5090505f5b828110156102bd5761055260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061056457610564611759565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161059057905050905061061689898986815181106105db576105db611759565b6020026020010151604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b815f8151811061062857610628611759565b60200260200101819052508082604001819052508184848151811061064f5761064f611759565b6020908102919091010152505060010161051e565b6040805160018082528183019092525f91829190816020015b6106a960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161067d5790505090506106ea60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038781168252604080516080810182525f606082018190528984168252928816602080830191909152600788900b82840152825160018082528185019094529193929082015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161073757905050905081815f8151811061077e5761077e611759565b602002602001018190525080836040018190525082845f815181106107a5576107a5611759565b60200260200101819052506107b9846110df565b9450600785900b6016146107cb575f80fd5b50505050949350505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016108039291906117af565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610841919061176d565b5f604051808303815f865af19150503d805f811461087a576040519150601f19603f3d011682016040523d82523d5f602084013e61087f565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516108b59291906117d0565b60405180910390a1816108d857601560405180602001604052805f8152506108dc565b6016815b60039190910b97909650945050505050565b5f80835160016108fe91906117fe565b6040805160018082528183019092529192505f9190816020015b61094460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161091857905050905061098560405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038881168252604080516060810182525f602082018190529181018290529189168252805b88518110156109ce576109c48883611817565b91506001016109b1565b506109d881611846565b60070b60208301525f8567ffffffffffffffff8111156109fa576109fa6111b3565b604051908082528060200260200182016040528015610a4357816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610a185790505b50905082815f81518110610a5957610a59611759565b602090810291909101015260015b86811015610af157604080516060810182525f80825260208201819052918101919091528a610a9760018461186b565b81518110610aa757610aa7611759565b6020908102919091018101516001600160a01b0316825260078b900b9082015282518190849084908110610add57610add611759565b602090810291909101015250600101610a67565b5080846020018190525083855f81518110610b0e57610b0e611759565b6020026020010181905250610b22856110df565b9650600787900b601614610b34575f80fd5b505050505050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610323565b5f8085518851610b9691906117fe565b90505f8167ffffffffffffffff811115610bb257610bb26111b3565b604051908082528060200260200182016040528015610c0f57816020015b610bfc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610bd05790505b5090505f5b8951811015610ce057610c4960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610c5b57610c5b611759565b60209081029190910101516001600160a01b031681528a51610cb1908c9084908110610c8957610c89611759565b60200260200101518b8481518110610ca357610ca3611759565b602002602001015189610ff8565b816020018190525080838381518110610ccc57610ccc611759565b602090810291909101015250600101610c14565b5088515f5b83821015610e3b57610d1960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610d2b57610d2b611759565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610d57579050509050610dd48b8481518110610da057610da0611759565b60200260200101518b8581518110610dba57610dba611759565b60200260200101518a86815181106105db576105db611759565b815f81518110610de657610de6611759565b602002602001018190525080826040018190525081858581518110610e0d57610e0d611759565b60200260200101819052508380610e239061187e565b94505050508080610e339061187e565b915050610ce5565b50610e45826110df565b9350600784900b601614610e57575f80fd5b50505098975050505050505050565b81516040805160018082528183019092525f9291839190816020015b610eae60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610e82579050509050610eef60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b03881681525f8367ffffffffffffffff811115610f1557610f156111b3565b604051908082528060200260200182016040528015610f6557816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610f335790505b5090505f5b84811015610fc757610fa289898381518110610f8857610f88611759565b60200260200101518984815181106105db576105db611759565b828281518110610fb457610fb4611759565b6020908102919091010152600101610f6a565b5080826040018190525081835f81518110610fe457610fe4611759565b60200260200101819052506107b9836110df565b60408051606080820183525f60208301819052928201929092526001600160a01b038516815261102783611846565b600790810b60208381019190915260408051606080820183525f828401526001600160a01b03891682529387900b818401528151600280825294810190925292909182015b604080516060810182525f80825260208083018290529282015282525f1990920191018161106c57905050925081835f815181106110ac576110ac611759565b602002602001018190525080836001815181106110cb576110cb611759565b602002602001018190525050509392505050565b5f805f6101676001600160a01b0316632f34811960e01b856040516024016111079190611901565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611145919061176d565b5f604051808303815f865af19150503d805f811461117e576040519150601f19603f3d011682016040523d82523d5f602084013e611183565b606091505b5091509150816111945760156111a8565b808060200190518101906111a89190611788565b60030b949350505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156111f0576111f06111b3565b604052919050565b5f67ffffffffffffffff821115611211576112116111b3565b5060051b60200190565b80356001600160a01b0381168114611231575f80fd5b919050565b5f82601f830112611245575f80fd5b8135602061125a611255836111f8565b6111c7565b8083825260208201915060208460051b87010193508684111561127b575f80fd5b602086015b8481101561129e576112918161121b565b8352918301918301611280565b509695505050505050565b8035600781900b8114611231575f80fd5b5f805f80608085870312156112cd575f80fd5b843567ffffffffffffffff8111156112e3575f80fd5b6112ef87828801611236565b9450506112fe6020860161121b565b925061130c6040860161121b565b915061131a606086016112a9565b905092959194509250565b5f805f8060808587031215611338575f80fd5b6113418561121b565b935061134f6020860161121b565b925061135d6040860161121b565b9396929550929360600135925050565b5f805f8060808587031215611380575f80fd5b6113898561121b565b93506112fe6020860161121b565b5f82601f8301126113a6575f80fd5b813560206113b6611255836111f8565b8083825260208201915060208460051b8701019350868411156113d7575f80fd5b602086015b8481101561129e576113ed816112a9565b83529183019183016113dc565b5f805f806080858703121561140d575f80fd5b843567ffffffffffffffff80821115611424575f80fd5b61143088838901611236565b955061143e6020880161121b565b945061144c6040880161121b565b93506060870135915080821115611461575f80fd5b5061146e87828801611397565b91505092959194509250565b5f806040838503121561148b575f80fd5b6114948361121b565b915060208084013567ffffffffffffffff808211156114b1575f80fd5b818601915086601f8301126114c4575f80fd5b8135818111156114d6576114d66111b3565b6114e8601f8201601f191685016111c7565b915080825287848285010111156114fd575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b8381101561153457818101518382015260200161151c565b50505f910152565b5f815180845261155381602086016020860161151a565b601f01601f19169290920160200192915050565b828152604060208201525f61157f604083018461153c565b949350505050565b5f805f806080858703121561159a575f80fd5b6115a38561121b565b93506115b16020860161121b565b9250604085013567ffffffffffffffff8111156115cc575f80fd5b6115d887828801611236565b92505061131a606086016112a9565b5f805f805f805f80610100898b0312156115ff575f80fd5b883567ffffffffffffffff80821115611616575f80fd5b6116228c838d01611236565b995060208b0135915080821115611637575f80fd5b6116438c838d01611236565b985060408b0135915080821115611658575f80fd5b6116648c838d01611236565b975060608b0135915080821115611679575f80fd5b6116858c838d01611236565b965060808b013591508082111561169a575f80fd5b6116a68c838d01611236565b955060a08b01359150808211156116bb575f80fd5b6116c78c838d01611236565b94506116d560c08c016112a9565b935060e08b01359150808211156116ea575f80fd5b506116f78b828c01611397565b9150509295985092959890939650565b5f805f806080858703121561171a575f80fd5b6117238561121b565b93506117316020860161121b565b9250604085013567ffffffffffffffff8082111561174d575f80fd5b61144c88838901611236565b634e487b7160e01b5f52603260045260245ffd5b5f825161177e81846020870161151a565b9190910192915050565b5f60208284031215611798575f80fd5b81518060030b81146117a8575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61157f604083018461153c565b8215158152604060208201525f61157f604083018461153c565b634e487b7160e01b5f52601160045260245ffd5b80820180821115611811576118116117ea565b92915050565b600781810b9083900b01677fffffffffffffff8113677fffffffffffffff1982121715611811576118116117ea565b5f8160070b677fffffffffffffff198103611863576118636117ea565b5f0392915050565b81810381811115611811576118116117ea565b5f6001820161188f5761188f6117ea565b5060010190565b5f815180845260208085019450602084015f5b838110156118f657815180516001600160a01b03908116895284820151168489015260408082015160070b90890152606090810151151590880152608090960195908201906001016118a9565b509495945050505050565b5f6020808301818452808551808352604092508286019150828160051b8701018488015f5b838110156119d557603f19898403018552815160608085016001600160a01b038084511687528a840151838c89015282815180855260808a0191508d830194505f92505b808310156119a25784518051851683528e81015160070b8f8401528d015115158d830152938d0193600192909201919085019061196a565b50948b0151888603898d0152946119b98187611896565b9a8d019a98505050948a01945050506001919091019050611926565b50909897505050505050505056fea2646970667358221220664b2810f77c2f635a1db3f825947c6b4d58c98b58f3e604b5235ff1311e657864736f6c63430008180033", + "deployedBytecode": "0x60806040526004361061008f575f3560e01c8063618dc65e11610057578063618dc65e14610122578063913073f91461014f5780639b23d3d9146101625780639ef773bf14610181578063c4d7ff7c14610194575f80fd5b8063061f87391461009357806315dacbea146100be5780631b79e5f9146100dd5780634e395634146100f057806352c0d7d41461010f575b5f80fd5b6100a66100a13660046112ba565b6101a7565b60405160079190910b81526020015b60405180910390f35b3480156100c9575f80fd5b506100a66100d8366004611325565b6102e3565b6100a66100eb36600461136d565b6103d2565b3480156100fb575f80fd5b506100a661010a3660046113fa565b61049e565b6100a661011d36600461136d565b610664565b34801561012d575f80fd5b5061014161013c36600461147a565b6107d7565b6040516100b5929190611567565b6100a661015d366004611587565b6108ee565b34801561016d575f80fd5b506100a661017c366004611325565b610b42565b6100a661018f3660046115e7565b610b86565b6100a66101a2366004611707565b610e66565b83515f90818167ffffffffffffffff8111156101c5576101c56111b3565b60405190808252806020026020018201604052801561022257816020015b61020f60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816101e35790505b5090505f5b828110156102bd5761025b60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061026d5761026d611759565b60209081029190910101516001600160a01b0316815261028e888888610ff8565b8160200181905250808383815181106102a9576102a9611759565b602090810291909101015250600101610227565b506102c7816110df565b9250600783900b6016146102d9575f80fd5b5050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610361919061176d565b5f604051808303815f865af19150503d805f811461039a576040519150601f19603f3d011682016040523d82523d5f602084013e61039f565b606091505b5091509150816103b05760156103c4565b808060200190518101906103c49190611788565b60030b979650505050505050565b6040805160018082528183019092525f91829190816020015b61041760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816103eb57905050905061045860405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038716815261046f868686610ff8565b816020018190525080825f8151811061048a5761048a611759565b60200260200101819052506102c7826110df565b83515f90818167ffffffffffffffff8111156104bc576104bc6111b3565b60405190808252806020026020018201604052801561051957816020015b61050660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816104da5790505b5090505f5b828110156102bd5761055260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b88828151811061056457610564611759565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161059057905050905061061689898986815181106105db576105db611759565b6020026020010151604080516080810182525f60608201526001600160a01b03948516815292909316602083015260070b9181019190915290565b815f8151811061062857610628611759565b60200260200101819052508082604001819052508184848151811061064f5761064f611759565b6020908102919091010152505060010161051e565b6040805160018082528183019092525f91829190816020015b6106a960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161067d5790505090506106ea60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038781168252604080516080810182525f606082018190528984168252928816602080830191909152600788900b82840152825160018082528185019094529193929082015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161073757905050905081815f8151811061077e5761077e611759565b602002602001018190525080836040018190525082845f815181106107a5576107a5611759565b60200260200101819052506107b9846110df565b9450600785900b6016146107cb575f80fd5b50505050949350505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016108039291906117af565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610841919061176d565b5f604051808303815f865af19150503d805f811461087a576040519150601f19603f3d011682016040523d82523d5f602084013e61087f565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516108b59291906117d0565b60405180910390a1816108d857601560405180602001604052805f8152506108dc565b6016815b60039190910b97909650945050505050565b5f80835160016108fe91906117fe565b6040805160018082528183019092529192505f9190816020015b61094460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161091857905050905061098560405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b038881168252604080516060810182525f602082018190529181018290529189168252805b88518110156109ce576109c48883611817565b91506001016109b1565b506109d881611846565b60070b60208301525f8567ffffffffffffffff8111156109fa576109fa6111b3565b604051908082528060200260200182016040528015610a4357816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610a185790505b50905082815f81518110610a5957610a59611759565b602090810291909101015260015b86811015610af157604080516060810182525f80825260208201819052918101919091528a610a9760018461186b565b81518110610aa757610aa7611759565b6020908102919091018101516001600160a01b0316825260078b900b9082015282518190849084908110610add57610add611759565b602090810291909101015250600101610a67565b5080846020018190525083855f81518110610b0e57610b0e611759565b6020026020010181905250610b22856110df565b9650600787900b601614610b34575f80fd5b505050505050949350505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610323565b5f8085518851610b9691906117fe565b90505f8167ffffffffffffffff811115610bb257610bb26111b3565b604051908082528060200260200182016040528015610c0f57816020015b610bfc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610bd05790505b5090505f5b8951811015610ce057610c4960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610c5b57610c5b611759565b60209081029190910101516001600160a01b031681528a51610cb1908c9084908110610c8957610c89611759565b60200260200101518b8481518110610ca357610ca3611759565b602002602001015189610ff8565b816020018190525080838381518110610ccc57610ccc611759565b602090810291909101015250600101610c14565b5088515f5b83821015610e3b57610d1960405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8c8281518110610d2b57610d2b611759565b60209081029190910101516001600160a01b031681526040805160018082528183019092525f91816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610d57579050509050610dd48b8481518110610da057610da0611759565b60200260200101518b8581518110610dba57610dba611759565b60200260200101518a86815181106105db576105db611759565b815f81518110610de657610de6611759565b602002602001018190525080826040018190525081858581518110610e0d57610e0d611759565b60200260200101819052508380610e239061187e565b94505050508080610e339061187e565b915050610ce5565b50610e45826110df565b9350600784900b601614610e57575f80fd5b50505098975050505050505050565b81516040805160018082528183019092525f9291839190816020015b610eae60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b815260200190600190039081610e82579050509050610eef60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b6001600160a01b03881681525f8367ffffffffffffffff811115610f1557610f156111b3565b604051908082528060200260200182016040528015610f6557816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610f335790505b5090505f5b84811015610fc757610fa289898381518110610f8857610f88611759565b60200260200101518984815181106105db576105db611759565b828281518110610fb457610fb4611759565b6020908102919091010152600101610f6a565b5080826040018190525081835f81518110610fe457610fe4611759565b60200260200101819052506107b9836110df565b60408051606080820183525f60208301819052928201929092526001600160a01b038516815261102783611846565b600790810b60208381019190915260408051606080820183525f828401526001600160a01b03891682529387900b818401528151600280825294810190925292909182015b604080516060810182525f80825260208083018290529282015282525f1990920191018161106c57905050925081835f815181106110ac576110ac611759565b602002602001018190525080836001815181106110cb576110cb611759565b602002602001018190525050509392505050565b5f805f6101676001600160a01b0316632f34811960e01b856040516024016111079190611901565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611145919061176d565b5f604051808303815f865af19150503d805f811461117e576040519150601f19603f3d011682016040523d82523d5f602084013e611183565b606091505b5091509150816111945760156111a8565b808060200190518101906111a89190611788565b60030b949350505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156111f0576111f06111b3565b604052919050565b5f67ffffffffffffffff821115611211576112116111b3565b5060051b60200190565b80356001600160a01b0381168114611231575f80fd5b919050565b5f82601f830112611245575f80fd5b8135602061125a611255836111f8565b6111c7565b8083825260208201915060208460051b87010193508684111561127b575f80fd5b602086015b8481101561129e576112918161121b565b8352918301918301611280565b509695505050505050565b8035600781900b8114611231575f80fd5b5f805f80608085870312156112cd575f80fd5b843567ffffffffffffffff8111156112e3575f80fd5b6112ef87828801611236565b9450506112fe6020860161121b565b925061130c6040860161121b565b915061131a606086016112a9565b905092959194509250565b5f805f8060808587031215611338575f80fd5b6113418561121b565b935061134f6020860161121b565b925061135d6040860161121b565b9396929550929360600135925050565b5f805f8060808587031215611380575f80fd5b6113898561121b565b93506112fe6020860161121b565b5f82601f8301126113a6575f80fd5b813560206113b6611255836111f8565b8083825260208201915060208460051b8701019350868411156113d7575f80fd5b602086015b8481101561129e576113ed816112a9565b83529183019183016113dc565b5f805f806080858703121561140d575f80fd5b843567ffffffffffffffff80821115611424575f80fd5b61143088838901611236565b955061143e6020880161121b565b945061144c6040880161121b565b93506060870135915080821115611461575f80fd5b5061146e87828801611397565b91505092959194509250565b5f806040838503121561148b575f80fd5b6114948361121b565b915060208084013567ffffffffffffffff808211156114b1575f80fd5b818601915086601f8301126114c4575f80fd5b8135818111156114d6576114d66111b3565b6114e8601f8201601f191685016111c7565b915080825287848285010111156114fd575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b8381101561153457818101518382015260200161151c565b50505f910152565b5f815180845261155381602086016020860161151a565b601f01601f19169290920160200192915050565b828152604060208201525f61157f604083018461153c565b949350505050565b5f805f806080858703121561159a575f80fd5b6115a38561121b565b93506115b16020860161121b565b9250604085013567ffffffffffffffff8111156115cc575f80fd5b6115d887828801611236565b92505061131a606086016112a9565b5f805f805f805f80610100898b0312156115ff575f80fd5b883567ffffffffffffffff80821115611616575f80fd5b6116228c838d01611236565b995060208b0135915080821115611637575f80fd5b6116438c838d01611236565b985060408b0135915080821115611658575f80fd5b6116648c838d01611236565b975060608b0135915080821115611679575f80fd5b6116858c838d01611236565b965060808b013591508082111561169a575f80fd5b6116a68c838d01611236565b955060a08b01359150808211156116bb575f80fd5b6116c78c838d01611236565b94506116d560c08c016112a9565b935060e08b01359150808211156116ea575f80fd5b506116f78b828c01611397565b9150509295985092959890939650565b5f805f806080858703121561171a575f80fd5b6117238561121b565b93506117316020860161121b565b9250604085013567ffffffffffffffff8082111561174d575f80fd5b61144c88838901611236565b634e487b7160e01b5f52603260045260245ffd5b5f825161177e81846020870161151a565b9190910192915050565b5f60208284031215611798575f80fd5b81518060030b81146117a8575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61157f604083018461153c565b8215158152604060208201525f61157f604083018461153c565b634e487b7160e01b5f52601160045260245ffd5b80820180821115611811576118116117ea565b92915050565b600781810b9083900b01677fffffffffffffff8113677fffffffffffffff1982121715611811576118116117ea565b5f8160070b677fffffffffffffff198103611863576118636117ea565b5f0392915050565b81810381811115611811576118116117ea565b5f6001820161188f5761188f6117ea565b5060010190565b5f815180845260208085019450602084015f5b838110156118f657815180516001600160a01b03908116895284820151168489015260408082015160070b90890152606090810151151590880152608090960195908201906001016118a9565b509495945050505050565b5f6020808301818452808551808352604092508286019150828160051b8701018488015f5b838110156119d557603f19898403018552815160608085016001600160a01b038084511687528a840151838c89015282815180855260808a0191508d830194505f92505b808310156119a25784518051851683528e81015160070b8f8401528d015115158d830152938d0193600192909201919085019061196a565b50948b0151888603898d0152946119b98187611896565b9a8d019a98505050948a01945050506001919091019050611926565b50909897505050505050505056fea2646970667358221220664b2810f77c2f635a1db3f825947c6b4d58c98b58f3e604b5235ff1311e657864736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol/TokenCreateContract.json b/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol/TokenCreateContract.json index 1af99701c..b327da2d7 100644 --- a/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol/TokenCreateContract.json +++ b/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol/TokenCreateContract.json @@ -653,8 +653,8 @@ "type": "function" } ], - "bytecode": "0x60c06040526009608090815268746f6b656e4e616d6560b81b60a0526002906200002a90826200025d565b5060408051808201909152600b81526a1d1bdad95b94de5b589bdb60aa1b60208201526003906200005c90826200025d565b50604080518082019091526004808252636d656d6f60e01b6020830152906200008690826200025d565b50600580546001600160a81b0319166c04a817c80000000002540be400179055348015620000b2575f80fd5b50600160208181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb499190915560027fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5560047fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5560087f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b5560107fedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643557fe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c5560065f5260407f8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a5562000329565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680620001e857607f821691505b6020821081036200020757634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200025857805f5260205f20601f840160051c81016020851015620002345750805b601f840160051c820191505b8181101562000255575f815560010162000240565b50505b505050565b81516001600160401b03811115620002795762000279620001bf565b62000291816200028a8454620001d3565b846200020d565b602080601f831160018114620002c7575f8415620002af5750858301515b5f19600386901b1c1916600185901b17855562000321565b5f85815260208120601f198616915b82811015620002f757888601518255948401946001909101908401620002d6565b50858210156200031557878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b613d9480620003375f395ff3fe608060405260043610610110575f3560e01c80638ba74da01161009d578063d85f74c111610062578063d85f74c1146102cf578063de84a779146102e2578063e9f7322614610301578063f4a01e5b14610314578063f848fec414610333575f80fd5b80638ba74da01461024c5780638f74a17b1461025f5780639b23d3d91461028a578063b35d417a146102a9578063cc265af4146102bc575f80fd5b806336348de3116100e357806336348de3146101ac5780634b5c6687146101cb5780634d1769d6146101de578063618dc65e1461020c57806371de370714610239575f80fd5b80630488c939146101145780630fd2601e14610129578063118741e71461016057806315dacbea1461018d575b5f80fd5b610127610122366004612dee565b610352565b005b348015610134575f80fd5b50610148610143366004612dee565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561016b575f80fd5b5061017f61017a366004612efd565b6108ff565b604051908152602001610157565b348015610198575f80fd5b506101486101a7366004612fac565b610951565b3480156101b7575f80fd5b5061017f6101c636600461325b565b610a40565b6101276101d936600461339b565b610a4b565b3480156101e9575f80fd5b506101fd6101f83660046133b6565b610e73565b604051610157939291906134c3565b348015610217575f80fd5b5061022b6102263660046134ed565b610f31565b604051610157929190613587565b6101276102473660046135a7565b611048565b61012761025a366004612dee565b6111a4565b61027261026d3660046134ed565b6115f8565b6040516001600160a01b039091168152602001610157565b348015610295575f80fd5b506101486102a4366004612fac565b6119d7565b6101276102b73660046134ed565b611a1b565b6101276102ca3660046134ed565b611dde565b6101276102dd36600461339b565b611eb2565b3480156102ed575f80fd5b506101fd6102fc3660046133b6565b612236565b61027261030f3660046134ed565b6122ce565b34801561031f575f80fd5b5061017f61032e366004612dee565b6123a5565b34801561033e575f80fd5b5061017f61034d366004613607565b6123b0565b60408051600580825260c082019092525f91816020015b610371612d6e565b8152602001906001900390816103695790505090506103a15f60065f60405180602001604052805f81525061240a565b815f815181106103b3576103b3613645565b60200260200101819052506103d860015f60405180602001604052805f815250612441565b816001815181106103eb576103eb613645565b602002602001018190525061041060025f60405180602001604052805f815250612441565b8160028151811061042357610423613645565b602002602001018190525061044860045f60405180602001604052805f815250612441565b8160038151811061045b5761045b613645565b602002602001018190525061048060035f60405180602001604052805f815250612441565b8160048151811061049357610493613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f604051806101200160405280600280546104e890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461051490613659565b801561055f5780601f106105365761010080835404028352916020019161055f565b820191905f5260205f20905b81548152906001019060200180831161054257829003601f168201915b505050505081526020016003805461057690613659565b80601f01602080910402602001604051908101604052809291908181526020018280546105a290613659565b80156105ed5780601f106105c4576101008083540402835291602001916105ed565b820191905f5260205f20905b8154815290600101906020018083116105d057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461061390613659565b80601f016020809104026020016040519081016040528092919081815260200182805461063f90613659565b801561068a5780601f106106615761010080835404028352916020019161068a565b820191905f5260205f20905b81548152906001019060200180831161066d57829003601f168201915b5050509183525050600160208201819052600554600160401b810460070b6040840152600160a01b900460ff16151560608301526080820186905260a09091018490529091505f9060405190808252806020026020018201604052801561072957816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816106f05790505b506040805160a081018252600181526001600160a01b0380891660208301525f928201839052606082018390528916608082015282519293509183919061077257610772613645565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816107935790505090506040518060c00160405280600460070b8152602001600560070b8152602001600a60070b8152602001876001600160a01b031681526020015f15158152602001886001600160a01b0316815250815f8151811061083457610834613645565b60200260200101819052505f8061084c858585612476565b90925090506016821461085d575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b5f6108af8383612596565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b6016146108f9575f80fd5b92915050565b5f61090a8383612674565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161093d91815260200190565b60405180910390a1601681146108f9575f80fd5b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109cf9190613691565b5f604051808303815f865af19150503d805f8114610a08576040519150601f19603f3d011682016040523d82523d5f602084013e610a0d565b606091505b509150915081610a1e576015610a32565b80806020019051810190610a3291906136bd565b60030b979650505050505050565b5f61090a838361269e565b60408051600680825260e082019092525f91816020015b610a6a612d6e565b815260200190600190039081610a62579050509050610a9a5f60065f60405180602001604052805f81525061240a565b815f81518110610aac57610aac613645565b6020026020010181905250610ad160015f60405180602001604052805f815250612441565b81600181518110610ae457610ae4613645565b6020026020010181905250610b0960025f60405180602001604052805f815250612441565b81600281518110610b1c57610b1c613645565b6020026020010181905250610b4160035f60405180602001604052805f815250612441565b81600381518110610b5457610b54613645565b6020026020010181905250610b7960045f60405180602001604052805f815250612441565b81600481518110610b8c57610b8c613645565b6020026020010181905250610bb160055f60405180602001604052805f815250612441565b81600581518110610bc457610bc4613645565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054610c1990613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4590613659565b8015610c905780601f10610c6757610100808354040283529160200191610c90565b820191905f5260205f20905b815481529060010190602001808311610c7357829003601f168201915b5050505050815260200160038054610ca790613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd390613659565b8015610d1e5780601f10610cf557610100808354040283529160200191610d1e565b820191905f5260205f20905b815481529060010190602001808311610d0157829003601f168201915b50505050508152602001856001600160a01b0316815260200160048054610d4490613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7090613659565b8015610dbb5780601f10610d9257610100808354040283529160200191610dbb565b820191905f5260205f20905b815481529060010190602001808311610d9e57829003601f168201915b505050918352505060016020820152600554600160401b8104600790810b604084015260ff600160a01b830416151560608401526080830187905260a09092018590529192505f918291610e1e91859181900b90600160801b900460030b6126c8565b909250905060168214610e2f575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b5f806060610e82868686612731565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610ec9575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610efa9291906136d6565b60405180910390a1610f27863033845f81518110610f1a57610f1a613645565b6020026020010151612828565b5093509350939050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610f5d9291906136f1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f9b9190613691565b5f604051808303815f865af19150503d805f8114610fd4576040519150601f19603f3d011682016040523d82523d5f602084013e610fd9565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc828260405161100f929190613712565b60405180910390a18161103257601560405180602001604052805f815250611036565b6016815b60039190910b97909650945050505050565b604051638f74a17b60e01b81525f903090638f74a17b90349061107190889088906004016136f1565b60206040518083038185885af115801561108d573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906110b2919061372c565b60405163f4a01e5b60e01b81523360048201526001600160a01b0382166024820152909150309063f4a01e5b906044016020604051808303815f875af11580156110fe573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111229190613747565b506040516307e9300f60e11b81526001600160a01b03821660048201523360248201523090630fd2601e906044016020604051808303815f875af115801561116c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611190919061375e565b5061119d8130338561286f565b5050505050565b6040805160018082528183019092525f91816020015b6111c2612d6e565b8152602001906001900390816111ba5790505090506111f15f805f60405180602001604052805f81525061240a565b815f8151811061120357611203613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461125890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461128490613659565b80156112cf5780601f106112a6576101008083540402835291602001916112cf565b820191905f5260205f20905b8154815290600101906020018083116112b257829003601f168201915b50505050508152602001600380546112e690613659565b80601f016020809104026020016040519081016040528092919081815260200182805461131290613659565b801561135d5780601f106113345761010080835404028352916020019161135d565b820191905f5260205f20905b81548152906001019060200180831161134057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461138390613659565b80601f01602080910402602001604051908101604052809291908181526020018280546113af90613659565b80156113fa5780601f106113d1576101008083540402835291602001916113fa565b820191905f5260205f20905b8154815290600101906020018083116113dd57829003601f168201915b5050509183525050600160208201819052600554600160401b900460070b6040808401919091525f606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f1990920191018161144e5750506040805160a081018252600181526001600160a01b0388811660208301525f92820183905260608201839052891660808201528251929350918391906114ce576114ce613645565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816114ef5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201525f608082018190526001600160a01b038a1660a08301528251929350909183919061158057611580613645565b60209081029190910101526005545f9081906115af908690600781900b90600160801b900460030b87876128b6565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa826040516115e491815260200190565b60405180910390a16016821461085d575f80fd5b60408051600680825260e082019092525f91829190816020015b61161a612d6e565b81526020019060019003908161161257905050905061163d5f600660038661240a565b815f8151811061164f5761164f613645565b60200260200101819052506116676001600385612441565b8160018151811061167a5761167a613645565b60200260200101819052506116926002600385612441565b816002815181106116a5576116a5613645565b60200260200101819052506116bd6004600385612441565b816003815181106116d0576116d0613645565b60200260200101819052506116e760038085612441565b816004815181106116fa576116fa613645565b60200260200101819052506117126005600385612441565b8160058151811061172557611725613645565b60200260200101819052505f60405180606001604052805f60070b8152602001866001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461177a90613659565b80601f01602080910402602001604051908101604052809291908181526020018280546117a690613659565b80156117f15780601f106117c8576101008083540402835291602001916117f1565b820191905f5260205f20905b8154815290600101906020018083116117d457829003601f168201915b505050505081526020016003805461180890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461183490613659565b801561187f5780601f106118565761010080835404028352916020019161187f565b820191905f5260205f20905b81548152906001019060200180831161186257829003601f168201915b50505050508152602001876001600160a01b03168152602001600480546118a590613659565b80601f01602080910402602001604051908101604052809291908181526020018280546118d190613659565b801561191c5780601f106118f35761010080835404028352916020019161191c565b820191905f5260205f20905b8154815290600101906020018083116118ff57829003601f168201915b505050918352505060016020820152600554600160401b8104600790810b604084015260ff600160a01b830416151560608401526080830187905260a09092018590529192505f91829161197f91859181900b90600160801b900460030b6126c8565b909250905060168214611990575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1979650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610991565b60408051600680825260e082019092525f91816020015b611a3a612d6e565b815260200190600190039081611a32579050509050611a5d5f600660038561240a565b815f81518110611a6f57611a6f613645565b6020026020010181905250611a876001600384612441565b81600181518110611a9a57611a9a613645565b6020026020010181905250611ab26002600384612441565b81600281518110611ac557611ac5613645565b6020026020010181905250611add6004600384612441565b81600381518110611af057611af0613645565b6020026020010181905250611b0760038084612441565b81600481518110611b1a57611b1a613645565b6020026020010181905250611b326005600384612441565b81600581518110611b4557611b45613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054611b9a90613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611bc690613659565b8015611c115780601f10611be857610100808354040283529160200191611c11565b820191905f5260205f20905b815481529060010190602001808311611bf457829003601f168201915b5050505050815260200160038054611c2890613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611c5490613659565b8015611c9f5780601f10611c7657610100808354040283529160200191611c9f565b820191905f5260205f20905b815481529060010190602001808311611c8257829003601f168201915b50505050508152602001866001600160a01b0316815260200160048054611cc590613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611cf190613659565b8015611d3c5780601f10611d1357610100808354040283529160200191611d3c565b820191905f5260205f20905b815481529060010190602001808311611d1f57829003601f168201915b505050918352505060016020820152600554600160401b810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290505f80611d88836129dc565b909250905060168214611d99575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050565b60408051600480825260a082019092525f91816020015b611dfd612d6e565b815260200190600190039081611df5579050509050611e205f600660038561240a565b815f81518110611e3257611e32613645565b6020026020010181905250611e4a6002600384612441565b81600181518110611e5d57611e5d613645565b6020026020010181905250611e756004600384612441565b81600281518110611e8857611e88613645565b6020026020010181905250611e9f60038084612441565b81600381518110611b4557611b45613645565b60408051600580825260c082019092525f91816020015b611ed1612d6e565b815260200190600190039081611ec9579050509050611f015f60065f60405180602001604052805f81525061240a565b815f81518110611f1357611f13613645565b6020026020010181905250611f3860015f60405180602001604052805f815250612441565b81600181518110611f4b57611f4b613645565b6020026020010181905250611f7060025f60405180602001604052805f815250612441565b81600281518110611f8357611f83613645565b6020026020010181905250611fa860045f60405180602001604052805f815250612441565b81600381518110611fbb57611fbb613645565b6020026020010181905250611fe060035f60405180602001604052805f815250612441565b81600481518110611ff357611ff3613645565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461204890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461207490613659565b80156120bf5780601f10612096576101008083540402835291602001916120bf565b820191905f5260205f20905b8154815290600101906020018083116120a257829003601f168201915b50505050508152602001600380546120d690613659565b80601f016020809104026020016040519081016040528092919081815260200182805461210290613659565b801561214d5780601f106121245761010080835404028352916020019161214d565b820191905f5260205f20905b81548152906001019060200180831161213057829003601f168201915b50505050508152602001856001600160a01b031681526020016004805461217390613659565b80601f016020809104026020016040519081016040528092919081815260200182805461219f90613659565b80156121ea5780601f106121c1576101008083540402835291602001916121ea565b820191905f5260205f20905b8154815290600101906020018083116121cd57829003601f168201915b505050918352505060016020820152600554600160401b810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290505f80610e1e836129dc565b5f806060612245868686612731565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a16016831461228c575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d82826040516122bd9291906136d6565b60405180910390a193509350939050565b60408051600480825260a082019092525f91829190816020015b6122f0612d6e565b8152602001906001900390816122e85790505090506123135f600660038661240a565b815f8151811061232557612325613645565b602002602001018190525061233d6002600385612441565b8160018151811061235057612350613645565b60200260200101819052506123686004600385612441565b8160028151811061237b5761237b613645565b602002602001018190525061239260038085612441565b8160038151811061172557611725613645565b5f61090a8383612ae4565b5f6123bc848484612b19565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa816040516123ef91815260200190565b60405180910390a160168114612403575f80fd5b9392505050565b612412612d6e565b60405180604001604052806124278787612bed565b81526020016124368585612c27565b905295945050505050565b612449612d6e565b604051806040016040528061245d86612d32565b815260200161246c8585612c27565b9052949350505050565b5f80848061010001515f015160070b5f14801561249d57506101008101516040015160070b155b156124b3576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a6040516024016124df939291906139ab565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161251d9190613691565b5f6040518083038185875af1925050503d805f8114612557576040519150601f19603f3d011682016040523d82523d5f602084013e61255c565b606091505b50915091508161256e5760155f612582565b808060200190518101906125829190613a62565b60039190910b999098509650505050505050565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516126059190613691565b5f604051808303815f865af19150503d805f811461263e576040519150601f19603f3d011682016040523d82523d5f602084013e612643565b606091505b509150915081612654576015612668565b8080602001905181019061266891906136bd565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b86866040516024016125c7929190613a8c565b5f805f6101676001600160a01b0316637d305cfa60e01b86866040516024016125c7929190613ae7565b5f80848061010001515f015160070b5f1480156126ef57506101008101516040015160070b155b15612705576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a6040516024016124df93929190613b08565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161276093929190613b36565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161279e9190613691565b5f604051808303815f865af19150503d805f81146127d7576040519150601f19603f3d011682016040523d82523d5f602084013e6127dc565b606091505b5091509150816127fe57604080515f8082526020820190925260159190612812565b808060200190518101906128129190613bb3565b60039290920b9a90995090975095505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610991565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610991565b5f80868061010001515f015160070b5f1480156128dd57506101008101516040015160070b155b156128f3576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c604051602401612923959493929190613c6d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129619190613691565b5f6040518083038185875af1925050503d805f811461299b576040519150601f19603f3d011682016040523d82523d5f602084013e6129a0565b606091505b5091509150816129b25760155f6129c6565b808060200190518101906129c69190613a62565b60039190910b9b909a5098505050505050505050565b5f80828061010001515f015160070b5f148015612a0357506101008101516040015160070b155b15612a19576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401612a419190613d38565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612a7f9190613691565b5f6040518083038185875af1925050503d805f8114612ab9576040519150601f19603f3d011682016040523d82523d5f602084013e612abe565b606091505b509150915081612ad05760155f611036565b808060200190518101906110369190613a62565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b906064016125c7565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f918291829161016791612b7d9190613691565b5f604051808303815f865af19150503d805f8114612bb6576040519150601f19603f3d011682016040523d82523d5f602084013e612bbb565b606091505b509150915081612bcc576015612be0565b80806020019051810190612be091906136bd565b60030b9695505050505050565b5f612c10836006811115612c0357612c03613d4a565b600160ff9091161b821790565b9050612403826006811115612c0357612c03613d4a565b612c6a6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f836004811115612c7d57612c7d613d4a565b03612c8b57600181526108f9565b6001836004811115612c9f57612c9f613d4a565b03612cb9575f546001600160a01b031660208201526108f9565b6002836004811115612ccd57612ccd613d4a565b03612cde57604081018290526108f9565b6003836004811115612cf257612cf2613d4a565b03612d0357606081018290526108f9565b6004836004811115612d1757612d17613d4a565b036108f9575f546001600160a01b0316608082015292915050565b5f60015f836006811115612d4857612d48613d4a565b6006811115612d5957612d59613d4a565b81526020019081526020015f20549050919050565b60405180604001604052805f8152602001612dc26040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b0381168114612ddb575f80fd5b50565b8035612de981612dc7565b919050565b5f8060408385031215612dff575f80fd5b8235612e0a81612dc7565b91506020830135612e1a81612dc7565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b60405290565b60405160a0810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b604051610120810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b604051601f8201601f1916810167ffffffffffffffff81118282101715612ed257612ed2612e25565b604052919050565b5f67ffffffffffffffff821115612ef357612ef3612e25565b5060051b60200190565b5f8060408385031215612f0e575f80fd5b8235612f1981612dc7565b915060208381013567ffffffffffffffff811115612f35575f80fd5b8401601f81018613612f45575f80fd5b8035612f58612f5382612eda565b612ea9565b81815260059190911b82018301908381019088831115612f76575f80fd5b928401925b82841015612f9d578335612f8e81612dc7565b82529284019290840190612f7b565b80955050505050509250929050565b5f805f8060808587031215612fbf575f80fd5b8435612fca81612dc7565b93506020850135612fda81612dc7565b92506040850135612fea81612dc7565b9396929550929360600135925050565b5f82601f830112613009575f80fd5b813567ffffffffffffffff81111561302357613023612e25565b613036601f8201601f1916602001612ea9565b81815284602083860101111561304a575f80fd5b816020850160208301375f918101602001919091529392505050565b80358015158114612de9575f80fd5b8060070b8114612ddb575f80fd5b8035612de981613075565b5f82601f83011261309d575f80fd5b813560206130ad612f5383612eda565b82815260059290921b840181019181810190868411156130cb575f80fd5b8286015b848110156131dc57803567ffffffffffffffff808211156130ee575f80fd5b908801906040601f19838c038101821315613107575f80fd5b61310f612e39565b8885013581528285013584811115613125575f80fd5b949094019360a0858e038301121561313b575f80fd5b613143612e62565b9150613150898601613066565b82528285013561315f81612dc7565b828a015260608581013585811115613175575f80fd5b6131838f8c838a0101612ffa565b858501525060809350838601358581111561319c575f80fd5b6131aa8f8c838a0101612ffa565b82850152505060a085013594506131c085612dc7565b91810193909352808701929092525083529183019183016130cf565b509695505050505050565b5f606082840312156131f7575f80fd5b6040516060810181811067ffffffffffffffff8211171561321a5761321a612e25565b604052905080823561322b81613075565b8152602083013561323b81612dc7565b6020820152604083013561324e81613075565b6040919091015292915050565b5f806040838503121561326c575f80fd5b823561327781612dc7565b9150602083013567ffffffffffffffff80821115613293575f80fd5b9084019061016082870312156132a7575f80fd5b6132af612e85565b8235828111156132bd575f80fd5b6132c988828601612ffa565b8252506020830135828111156132dd575f80fd5b6132e988828601612ffa565b6020830152506132fb60408401612dde565b6040820152606083013582811115613311575f80fd5b61331d88828601612ffa565b60608301525061332f60808401613066565b608082015261334060a08401613083565b60a082015261335160c08401613066565b60c082015260e083013582811115613367575f80fd5b6133738882860161308e565b60e083015250610100915061338a878385016131e7565b828201528093505050509250929050565b5f602082840312156133ab575f80fd5b813561240381612dc7565b5f805f606084860312156133c8575f80fd5b83356133d381612dc7565b92506020848101356133e481613075565b9250604085013567ffffffffffffffff80821115613400575f80fd5b818701915087601f830112613413575f80fd5b8135613421612f5382612eda565b81815260059190911b8301840190848101908a83111561343f575f80fd5b8585015b8381101561347557803585811115613459575f80fd5b6134678d89838a0101612ffa565b845250918601918601613443565b508096505050505050509250925092565b5f815180845260208085019450602084015f5b838110156134b857815160070b87529582019590820190600101613499565b509495945050505050565b8381528260070b6020820152606060408201525f6134e46060830184613486565b95945050505050565b5f80604083850312156134fe575f80fd5b823561350981612dc7565b9150602083013567ffffffffffffffff811115613524575f80fd5b61353085828601612ffa565b9150509250929050565b5f5b8381101561355457818101518382015260200161353c565b50505f910152565b5f815180845261357381602086016020860161353a565b601f01601f19169290920160200192915050565b828152604060208201525f61359f604083018461355c565b949350505050565b5f805f606084860312156135b9575f80fd5b83356135c481612dc7565b9250602084013567ffffffffffffffff8111156135df575f80fd5b6135eb86828701612ffa565b92505060408401356135fc81613075565b809150509250925092565b5f805f60608486031215613619575f80fd5b833561362481612dc7565b9250602084013561363481612dc7565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061366d57607f821691505b60208210810361368b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82516136a281846020870161353a565b9190910192915050565b8051600381900b8114612de9575f80fd5b5f602082840312156136cd575f80fd5b612403826136ac565b8260070b8152604060208201525f61359f6040830184613486565b6001600160a01b0383168152604060208201525f61359f604083018461355c565b8215158152604060208201525f61359f604083018461355c565b5f6020828403121561373c575f80fd5b815161240381612dc7565b5f60208284031215613757575f80fd5b5051919050565b5f6020828403121561376e575f80fd5b815161240381613075565b5f82825180855260208086019550808260051b8401018186015f5b8481101561383157601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a01526137f360e08a018661355c565b92860151898403603f1901858b015292945061380f858461355c565b9501511660c09790970196909652505098840198925090830190600101613794565b5090979650505050505050565b5f61016082518185526138538286018261355c565b9150506020830151848203602086015261386d828261355c565b915050604083015161388a60408601826001600160a01b03169052565b50606083015184820360608601526138a2828261355c565b91505060808301516138b8608086018215159052565b5060a08301516138cd60a086018260070b9052565b5060c08301516138e160c086018215159052565b5060e083015184820360e08601526138f98282613779565b9150506101008084015161393582870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b5f815180845260208085019450602084015f5b838110156134b8578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613952565b5f60608083526139be606084018761383e565b6020848203818601526139d1828861393f565b915060408583036040870152828751808552838501915083890194505f5b81811015613a525785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c0909201916001016139ef565b50909a9950505050505050505050565b5f8060408385031215613a73575f80fd5b613a7c836136ac565b91506020830151612e1a81612dc7565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b81811015613ad9578551851683529483019491830191600101613abb565b509098975050505050505050565b6001600160a01b0383168152604060208201525f61359f604083018461383e565b606081525f613b1a606083018661383e565b90508360070b60208301528260030b6040830152949350505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b82811015613ba457607f19888703018452613b9286835161355c565b95509284019290840190600101613b76565b50939998505050505050505050565b5f805f60608486031215613bc5575f80fd5b613bce846136ac565b9250602080850151613bdf81613075565b604086015190935067ffffffffffffffff811115613bfb575f80fd5b8501601f81018713613c0b575f80fd5b8051613c19612f5382612eda565b81815260059190911b82018301908381019089831115613c37575f80fd5b928401925b82841015613c5e578351613c4f81613075565b82529284019290840190613c3c565b80955050505050509250925092565b5f60a0808352613c8060a084018961383e565b602060078960070b8287015260408960030b604088015260608785036060890152613cab858b61393f565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015613d235788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101613cc9565b50909f9e505050505050505050505050505050565b602081525f612403602083018461383e565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220d3abc1e1b5040847d32955e5266f7d02f7e41376fd293c8d79d289c1f74bbfe164736f6c63430008180033", - "deployedBytecode": "0x608060405260043610610110575f3560e01c80638ba74da01161009d578063d85f74c111610062578063d85f74c1146102cf578063de84a779146102e2578063e9f7322614610301578063f4a01e5b14610314578063f848fec414610333575f80fd5b80638ba74da01461024c5780638f74a17b1461025f5780639b23d3d91461028a578063b35d417a146102a9578063cc265af4146102bc575f80fd5b806336348de3116100e357806336348de3146101ac5780634b5c6687146101cb5780634d1769d6146101de578063618dc65e1461020c57806371de370714610239575f80fd5b80630488c939146101145780630fd2601e14610129578063118741e71461016057806315dacbea1461018d575b5f80fd5b610127610122366004612dee565b610352565b005b348015610134575f80fd5b50610148610143366004612dee565b6108a4565b60405160079190910b81526020015b60405180910390f35b34801561016b575f80fd5b5061017f61017a366004612efd565b6108ff565b604051908152602001610157565b348015610198575f80fd5b506101486101a7366004612fac565b610951565b3480156101b7575f80fd5b5061017f6101c636600461325b565b610a40565b6101276101d936600461339b565b610a4b565b3480156101e9575f80fd5b506101fd6101f83660046133b6565b610e73565b604051610157939291906134c3565b348015610217575f80fd5b5061022b6102263660046134ed565b610f31565b604051610157929190613587565b6101276102473660046135a7565b611048565b61012761025a366004612dee565b6111a4565b61027261026d3660046134ed565b6115f8565b6040516001600160a01b039091168152602001610157565b348015610295575f80fd5b506101486102a4366004612fac565b6119d7565b6101276102b73660046134ed565b611a1b565b6101276102ca3660046134ed565b611dde565b6101276102dd36600461339b565b611eb2565b3480156102ed575f80fd5b506101fd6102fc3660046133b6565b612236565b61027261030f3660046134ed565b6122ce565b34801561031f575f80fd5b5061017f61032e366004612dee565b6123a5565b34801561033e575f80fd5b5061017f61034d366004613607565b6123b0565b60408051600580825260c082019092525f91816020015b610371612d6e565b8152602001906001900390816103695790505090506103a15f60065f60405180602001604052805f81525061240a565b815f815181106103b3576103b3613645565b60200260200101819052506103d860015f60405180602001604052805f815250612441565b816001815181106103eb576103eb613645565b602002602001018190525061041060025f60405180602001604052805f815250612441565b8160028151811061042357610423613645565b602002602001018190525061044860045f60405180602001604052805f815250612441565b8160038151811061045b5761045b613645565b602002602001018190525061048060035f60405180602001604052805f815250612441565b8160048151811061049357610493613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f604051806101200160405280600280546104e890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461051490613659565b801561055f5780601f106105365761010080835404028352916020019161055f565b820191905f5260205f20905b81548152906001019060200180831161054257829003601f168201915b505050505081526020016003805461057690613659565b80601f01602080910402602001604051908101604052809291908181526020018280546105a290613659565b80156105ed5780601f106105c4576101008083540402835291602001916105ed565b820191905f5260205f20905b8154815290600101906020018083116105d057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461061390613659565b80601f016020809104026020016040519081016040528092919081815260200182805461063f90613659565b801561068a5780601f106106615761010080835404028352916020019161068a565b820191905f5260205f20905b81548152906001019060200180831161066d57829003601f168201915b5050509183525050600160208201819052600554600160401b810460070b6040840152600160a01b900460ff16151560608301526080820186905260a09091018490529091505f9060405190808252806020026020018201604052801561072957816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816106f05790505b506040805160a081018252600181526001600160a01b0380891660208301525f928201839052606082018390528916608082015282519293509183919061077257610772613645565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816107935790505090506040518060c00160405280600460070b8152602001600560070b8152602001600a60070b8152602001876001600160a01b031681526020015f15158152602001886001600160a01b0316815250815f8151811061083457610834613645565b60200260200101819052505f8061084c858585612476565b90925090506016821461085d575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b5f6108af8383612596565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b6016146108f9575f80fd5b92915050565b5f61090a8383612674565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161093d91815260200190565b60405180910390a1601681146108f9575f80fd5b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109cf9190613691565b5f604051808303815f865af19150503d805f8114610a08576040519150601f19603f3d011682016040523d82523d5f602084013e610a0d565b606091505b509150915081610a1e576015610a32565b80806020019051810190610a3291906136bd565b60030b979650505050505050565b5f61090a838361269e565b60408051600680825260e082019092525f91816020015b610a6a612d6e565b815260200190600190039081610a62579050509050610a9a5f60065f60405180602001604052805f81525061240a565b815f81518110610aac57610aac613645565b6020026020010181905250610ad160015f60405180602001604052805f815250612441565b81600181518110610ae457610ae4613645565b6020026020010181905250610b0960025f60405180602001604052805f815250612441565b81600281518110610b1c57610b1c613645565b6020026020010181905250610b4160035f60405180602001604052805f815250612441565b81600381518110610b5457610b54613645565b6020026020010181905250610b7960045f60405180602001604052805f815250612441565b81600481518110610b8c57610b8c613645565b6020026020010181905250610bb160055f60405180602001604052805f815250612441565b81600581518110610bc457610bc4613645565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054610c1990613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4590613659565b8015610c905780601f10610c6757610100808354040283529160200191610c90565b820191905f5260205f20905b815481529060010190602001808311610c7357829003601f168201915b5050505050815260200160038054610ca790613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd390613659565b8015610d1e5780601f10610cf557610100808354040283529160200191610d1e565b820191905f5260205f20905b815481529060010190602001808311610d0157829003601f168201915b50505050508152602001856001600160a01b0316815260200160048054610d4490613659565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7090613659565b8015610dbb5780601f10610d9257610100808354040283529160200191610dbb565b820191905f5260205f20905b815481529060010190602001808311610d9e57829003601f168201915b505050918352505060016020820152600554600160401b8104600790810b604084015260ff600160a01b830416151560608401526080830187905260a09092018590529192505f918291610e1e91859181900b90600160801b900460030b6126c8565b909250905060168214610e2f575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b5f806060610e82868686612731565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610ec9575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610efa9291906136d6565b60405180910390a1610f27863033845f81518110610f1a57610f1a613645565b6020026020010151612828565b5093509350939050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610f5d9291906136f1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f9b9190613691565b5f604051808303815f865af19150503d805f8114610fd4576040519150601f19603f3d011682016040523d82523d5f602084013e610fd9565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc828260405161100f929190613712565b60405180910390a18161103257601560405180602001604052805f815250611036565b6016815b60039190910b97909650945050505050565b604051638f74a17b60e01b81525f903090638f74a17b90349061107190889088906004016136f1565b60206040518083038185885af115801561108d573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906110b2919061372c565b60405163f4a01e5b60e01b81523360048201526001600160a01b0382166024820152909150309063f4a01e5b906044016020604051808303815f875af11580156110fe573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111229190613747565b506040516307e9300f60e11b81526001600160a01b03821660048201523360248201523090630fd2601e906044016020604051808303815f875af115801561116c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611190919061375e565b5061119d8130338561286f565b5050505050565b6040805160018082528183019092525f91816020015b6111c2612d6e565b8152602001906001900390816111ba5790505090506111f15f805f60405180602001604052805f81525061240a565b815f8151811061120357611203613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461125890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461128490613659565b80156112cf5780601f106112a6576101008083540402835291602001916112cf565b820191905f5260205f20905b8154815290600101906020018083116112b257829003601f168201915b50505050508152602001600380546112e690613659565b80601f016020809104026020016040519081016040528092919081815260200182805461131290613659565b801561135d5780601f106113345761010080835404028352916020019161135d565b820191905f5260205f20905b81548152906001019060200180831161134057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461138390613659565b80601f01602080910402602001604051908101604052809291908181526020018280546113af90613659565b80156113fa5780601f106113d1576101008083540402835291602001916113fa565b820191905f5260205f20905b8154815290600101906020018083116113dd57829003601f168201915b5050509183525050600160208201819052600554600160401b900460070b6040808401919091525f606084018190526080840188905260a09093018690528051828152808201909152929350909190816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f1990920191018161144e5750506040805160a081018252600181526001600160a01b0388811660208301525f92820183905260608201839052891660808201528251929350918391906114ce576114ce613645565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816114ef5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201525f608082018190526001600160a01b038a1660a08301528251929350909183919061158057611580613645565b60209081029190910101526005545f9081906115af908690600781900b90600160801b900460030b87876128b6565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa826040516115e491815260200190565b60405180910390a16016821461085d575f80fd5b60408051600680825260e082019092525f91829190816020015b61161a612d6e565b81526020019060019003908161161257905050905061163d5f600660038661240a565b815f8151811061164f5761164f613645565b60200260200101819052506116676001600385612441565b8160018151811061167a5761167a613645565b60200260200101819052506116926002600385612441565b816002815181106116a5576116a5613645565b60200260200101819052506116bd6004600385612441565b816003815181106116d0576116d0613645565b60200260200101819052506116e760038085612441565b816004815181106116fa576116fa613645565b60200260200101819052506117126005600385612441565b8160058151811061172557611725613645565b60200260200101819052505f60405180606001604052805f60070b8152602001866001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461177a90613659565b80601f01602080910402602001604051908101604052809291908181526020018280546117a690613659565b80156117f15780601f106117c8576101008083540402835291602001916117f1565b820191905f5260205f20905b8154815290600101906020018083116117d457829003601f168201915b505050505081526020016003805461180890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461183490613659565b801561187f5780601f106118565761010080835404028352916020019161187f565b820191905f5260205f20905b81548152906001019060200180831161186257829003601f168201915b50505050508152602001876001600160a01b03168152602001600480546118a590613659565b80601f01602080910402602001604051908101604052809291908181526020018280546118d190613659565b801561191c5780601f106118f35761010080835404028352916020019161191c565b820191905f5260205f20905b8154815290600101906020018083116118ff57829003601f168201915b505050918352505060016020820152600554600160401b8104600790810b604084015260ff600160a01b830416151560608401526080830187905260a09092018590529192505f91829161197f91859181900b90600160801b900460030b6126c8565b909250905060168214611990575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1979650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610991565b60408051600680825260e082019092525f91816020015b611a3a612d6e565b815260200190600190039081611a32579050509050611a5d5f600660038561240a565b815f81518110611a6f57611a6f613645565b6020026020010181905250611a876001600384612441565b81600181518110611a9a57611a9a613645565b6020026020010181905250611ab26002600384612441565b81600281518110611ac557611ac5613645565b6020026020010181905250611add6004600384612441565b81600381518110611af057611af0613645565b6020026020010181905250611b0760038084612441565b81600481518110611b1a57611b1a613645565b6020026020010181905250611b326005600384612441565b81600581518110611b4557611b45613645565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054611b9a90613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611bc690613659565b8015611c115780601f10611be857610100808354040283529160200191611c11565b820191905f5260205f20905b815481529060010190602001808311611bf457829003601f168201915b5050505050815260200160038054611c2890613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611c5490613659565b8015611c9f5780601f10611c7657610100808354040283529160200191611c9f565b820191905f5260205f20905b815481529060010190602001808311611c8257829003601f168201915b50505050508152602001866001600160a01b0316815260200160048054611cc590613659565b80601f0160208091040260200160405190810160405280929190818152602001828054611cf190613659565b8015611d3c5780601f10611d1357610100808354040283529160200191611d3c565b820191905f5260205f20905b815481529060010190602001808311611d1f57829003601f168201915b505050918352505060016020820152600554600160401b810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290505f80611d88836129dc565b909250905060168214611d99575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050565b60408051600480825260a082019092525f91816020015b611dfd612d6e565b815260200190600190039081611df5579050509050611e205f600660038561240a565b815f81518110611e3257611e32613645565b6020026020010181905250611e4a6002600384612441565b81600181518110611e5d57611e5d613645565b6020026020010181905250611e756004600384612441565b81600281518110611e8857611e88613645565b6020026020010181905250611e9f60038084612441565b81600381518110611b4557611b45613645565b60408051600580825260c082019092525f91816020015b611ed1612d6e565b815260200190600190039081611ec9579050509050611f015f60065f60405180602001604052805f81525061240a565b815f81518110611f1357611f13613645565b6020026020010181905250611f3860015f60405180602001604052805f815250612441565b81600181518110611f4b57611f4b613645565b6020026020010181905250611f7060025f60405180602001604052805f815250612441565b81600281518110611f8357611f83613645565b6020026020010181905250611fa860045f60405180602001604052805f815250612441565b81600381518110611fbb57611fbb613645565b6020026020010181905250611fe060035f60405180602001604052805f815250612441565b81600481518110611ff357611ff3613645565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461204890613659565b80601f016020809104026020016040519081016040528092919081815260200182805461207490613659565b80156120bf5780601f10612096576101008083540402835291602001916120bf565b820191905f5260205f20905b8154815290600101906020018083116120a257829003601f168201915b50505050508152602001600380546120d690613659565b80601f016020809104026020016040519081016040528092919081815260200182805461210290613659565b801561214d5780601f106121245761010080835404028352916020019161214d565b820191905f5260205f20905b81548152906001019060200180831161213057829003601f168201915b50505050508152602001856001600160a01b031681526020016004805461217390613659565b80601f016020809104026020016040519081016040528092919081815260200182805461219f90613659565b80156121ea5780601f106121c1576101008083540402835291602001916121ea565b820191905f5260205f20905b8154815290600101906020018083116121cd57829003601f168201915b505050918352505060016020820152600554600160401b810460070b6040830152600160a01b900460ff16151560608201526080810185905260a00183905290505f80610e1e836129dc565b5f806060612245868686612731565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a16016831461228c575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d82826040516122bd9291906136d6565b60405180910390a193509350939050565b60408051600480825260a082019092525f91829190816020015b6122f0612d6e565b8152602001906001900390816122e85790505090506123135f600660038661240a565b815f8151811061232557612325613645565b602002602001018190525061233d6002600385612441565b8160018151811061235057612350613645565b60200260200101819052506123686004600385612441565b8160028151811061237b5761237b613645565b602002602001018190525061239260038085612441565b8160038151811061172557611725613645565b5f61090a8383612ae4565b5f6123bc848484612b19565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa816040516123ef91815260200190565b60405180910390a160168114612403575f80fd5b9392505050565b612412612d6e565b60405180604001604052806124278787612bed565b81526020016124368585612c27565b905295945050505050565b612449612d6e565b604051806040016040528061245d86612d32565b815260200161246c8585612c27565b9052949350505050565b5f80848061010001515f015160070b5f14801561249d57506101008101516040015160070b155b156124b3576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a6040516024016124df939291906139ab565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161251d9190613691565b5f6040518083038185875af1925050503d805f8114612557576040519150601f19603f3d011682016040523d82523d5f602084013e61255c565b606091505b50915091508161256e5760155f612582565b808060200190518101906125829190613a62565b60039190910b999098509650505050505050565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516126059190613691565b5f604051808303815f865af19150503d805f811461263e576040519150601f19603f3d011682016040523d82523d5f602084013e612643565b606091505b509150915081612654576015612668565b8080602001905181019061266891906136bd565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b86866040516024016125c7929190613a8c565b5f805f6101676001600160a01b0316637d305cfa60e01b86866040516024016125c7929190613ae7565b5f80848061010001515f015160070b5f1480156126ef57506101008101516040015160070b155b15612705576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a6040516024016124df93929190613b08565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161276093929190613b36565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161279e9190613691565b5f604051808303815f865af19150503d805f81146127d7576040519150601f19603f3d011682016040523d82523d5f602084013e6127dc565b606091505b5091509150816127fe57604080515f8082526020820190925260159190612812565b808060200190518101906128129190613bb3565b60039290920b9a90995090975095505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610991565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610991565b5f80868061010001515f015160070b5f1480156128dd57506101008101516040015160070b155b156128f3576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c604051602401612923959493929190613c6d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129619190613691565b5f6040518083038185875af1925050503d805f811461299b576040519150601f19603f3d011682016040523d82523d5f602084013e6129a0565b606091505b5091509150816129b25760155f6129c6565b808060200190518101906129c69190613a62565b60039190910b9b909a5098505050505050505050565b5f80828061010001515f015160070b5f148015612a0357506101008101516040015160070b155b15612a19576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401612a419190613d38565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612a7f9190613691565b5f6040518083038185875af1925050503d805f8114612ab9576040519150601f19603f3d011682016040523d82523d5f602084013e612abe565b606091505b509150915081612ad05760155f611036565b808060200190518101906110369190613a62565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b906064016125c7565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f918291829161016791612b7d9190613691565b5f604051808303815f865af19150503d805f8114612bb6576040519150601f19603f3d011682016040523d82523d5f602084013e612bbb565b606091505b509150915081612bcc576015612be0565b80806020019051810190612be091906136bd565b60030b9695505050505050565b5f612c10836006811115612c0357612c03613d4a565b600160ff9091161b821790565b9050612403826006811115612c0357612c03613d4a565b612c6a6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f836004811115612c7d57612c7d613d4a565b03612c8b57600181526108f9565b6001836004811115612c9f57612c9f613d4a565b03612cb9575f546001600160a01b031660208201526108f9565b6002836004811115612ccd57612ccd613d4a565b03612cde57604081018290526108f9565b6003836004811115612cf257612cf2613d4a565b03612d0357606081018290526108f9565b6004836004811115612d1757612d17613d4a565b036108f9575f546001600160a01b0316608082015292915050565b5f60015f836006811115612d4857612d48613d4a565b6006811115612d5957612d59613d4a565b81526020019081526020015f20549050919050565b60405180604001604052805f8152602001612dc26040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b0381168114612ddb575f80fd5b50565b8035612de981612dc7565b919050565b5f8060408385031215612dff575f80fd5b8235612e0a81612dc7565b91506020830135612e1a81612dc7565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b60405290565b60405160a0810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b604051610120810167ffffffffffffffff81118282101715612e5c57612e5c612e25565b604051601f8201601f1916810167ffffffffffffffff81118282101715612ed257612ed2612e25565b604052919050565b5f67ffffffffffffffff821115612ef357612ef3612e25565b5060051b60200190565b5f8060408385031215612f0e575f80fd5b8235612f1981612dc7565b915060208381013567ffffffffffffffff811115612f35575f80fd5b8401601f81018613612f45575f80fd5b8035612f58612f5382612eda565b612ea9565b81815260059190911b82018301908381019088831115612f76575f80fd5b928401925b82841015612f9d578335612f8e81612dc7565b82529284019290840190612f7b565b80955050505050509250929050565b5f805f8060808587031215612fbf575f80fd5b8435612fca81612dc7565b93506020850135612fda81612dc7565b92506040850135612fea81612dc7565b9396929550929360600135925050565b5f82601f830112613009575f80fd5b813567ffffffffffffffff81111561302357613023612e25565b613036601f8201601f1916602001612ea9565b81815284602083860101111561304a575f80fd5b816020850160208301375f918101602001919091529392505050565b80358015158114612de9575f80fd5b8060070b8114612ddb575f80fd5b8035612de981613075565b5f82601f83011261309d575f80fd5b813560206130ad612f5383612eda565b82815260059290921b840181019181810190868411156130cb575f80fd5b8286015b848110156131dc57803567ffffffffffffffff808211156130ee575f80fd5b908801906040601f19838c038101821315613107575f80fd5b61310f612e39565b8885013581528285013584811115613125575f80fd5b949094019360a0858e038301121561313b575f80fd5b613143612e62565b9150613150898601613066565b82528285013561315f81612dc7565b828a015260608581013585811115613175575f80fd5b6131838f8c838a0101612ffa565b858501525060809350838601358581111561319c575f80fd5b6131aa8f8c838a0101612ffa565b82850152505060a085013594506131c085612dc7565b91810193909352808701929092525083529183019183016130cf565b509695505050505050565b5f606082840312156131f7575f80fd5b6040516060810181811067ffffffffffffffff8211171561321a5761321a612e25565b604052905080823561322b81613075565b8152602083013561323b81612dc7565b6020820152604083013561324e81613075565b6040919091015292915050565b5f806040838503121561326c575f80fd5b823561327781612dc7565b9150602083013567ffffffffffffffff80821115613293575f80fd5b9084019061016082870312156132a7575f80fd5b6132af612e85565b8235828111156132bd575f80fd5b6132c988828601612ffa565b8252506020830135828111156132dd575f80fd5b6132e988828601612ffa565b6020830152506132fb60408401612dde565b6040820152606083013582811115613311575f80fd5b61331d88828601612ffa565b60608301525061332f60808401613066565b608082015261334060a08401613083565b60a082015261335160c08401613066565b60c082015260e083013582811115613367575f80fd5b6133738882860161308e565b60e083015250610100915061338a878385016131e7565b828201528093505050509250929050565b5f602082840312156133ab575f80fd5b813561240381612dc7565b5f805f606084860312156133c8575f80fd5b83356133d381612dc7565b92506020848101356133e481613075565b9250604085013567ffffffffffffffff80821115613400575f80fd5b818701915087601f830112613413575f80fd5b8135613421612f5382612eda565b81815260059190911b8301840190848101908a83111561343f575f80fd5b8585015b8381101561347557803585811115613459575f80fd5b6134678d89838a0101612ffa565b845250918601918601613443565b508096505050505050509250925092565b5f815180845260208085019450602084015f5b838110156134b857815160070b87529582019590820190600101613499565b509495945050505050565b8381528260070b6020820152606060408201525f6134e46060830184613486565b95945050505050565b5f80604083850312156134fe575f80fd5b823561350981612dc7565b9150602083013567ffffffffffffffff811115613524575f80fd5b61353085828601612ffa565b9150509250929050565b5f5b8381101561355457818101518382015260200161353c565b50505f910152565b5f815180845261357381602086016020860161353a565b601f01601f19169290920160200192915050565b828152604060208201525f61359f604083018461355c565b949350505050565b5f805f606084860312156135b9575f80fd5b83356135c481612dc7565b9250602084013567ffffffffffffffff8111156135df575f80fd5b6135eb86828701612ffa565b92505060408401356135fc81613075565b809150509250925092565b5f805f60608486031215613619575f80fd5b833561362481612dc7565b9250602084013561363481612dc7565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061366d57607f821691505b60208210810361368b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82516136a281846020870161353a565b9190910192915050565b8051600381900b8114612de9575f80fd5b5f602082840312156136cd575f80fd5b612403826136ac565b8260070b8152604060208201525f61359f6040830184613486565b6001600160a01b0383168152604060208201525f61359f604083018461355c565b8215158152604060208201525f61359f604083018461355c565b5f6020828403121561373c575f80fd5b815161240381612dc7565b5f60208284031215613757575f80fd5b5051919050565b5f6020828403121561376e575f80fd5b815161240381613075565b5f82825180855260208086019550808260051b8401018186015f5b8481101561383157601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a01526137f360e08a018661355c565b92860151898403603f1901858b015292945061380f858461355c565b9501511660c09790970196909652505098840198925090830190600101613794565b5090979650505050505050565b5f61016082518185526138538286018261355c565b9150506020830151848203602086015261386d828261355c565b915050604083015161388a60408601826001600160a01b03169052565b50606083015184820360608601526138a2828261355c565b91505060808301516138b8608086018215159052565b5060a08301516138cd60a086018260070b9052565b5060c08301516138e160c086018215159052565b5060e083015184820360e08601526138f98282613779565b9150506101008084015161393582870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b5f815180845260208085019450602084015f5b838110156134b8578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a09096019590820190600101613952565b5f60608083526139be606084018761383e565b6020848203818601526139d1828861393f565b915060408583036040870152828751808552838501915083890194505f5b81811015613a525785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c0909201916001016139ef565b50909a9950505050505050505050565b5f8060408385031215613a73575f80fd5b613a7c836136ac565b91506020830151612e1a81612dc7565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b81811015613ad9578551851683529483019491830191600101613abb565b509098975050505050505050565b6001600160a01b0383168152604060208201525f61359f604083018461383e565b606081525f613b1a606083018661383e565b90508360070b60208301528260030b6040830152949350505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b82811015613ba457607f19888703018452613b9286835161355c565b95509284019290840190600101613b76565b50939998505050505050505050565b5f805f60608486031215613bc5575f80fd5b613bce846136ac565b9250602080850151613bdf81613075565b604086015190935067ffffffffffffffff811115613bfb575f80fd5b8501601f81018713613c0b575f80fd5b8051613c19612f5382612eda565b81815260059190911b82018301908381019089831115613c37575f80fd5b928401925b82841015613c5e578351613c4f81613075565b82529284019290840190613c3c565b80955050505050509250925092565b5f60a0808352613c8060a084018961383e565b602060078960070b8287015260408960030b604088015260608785036060890152613cab858b61393f565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015613d235788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101613cc9565b50909f9e505050505050505050505050505050565b602081525f612403602083018461383e565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220d3abc1e1b5040847d32955e5266f7d02f7e41376fd293c8d79d289c1f74bbfe164736f6c63430008180033", + "bytecode": "0x60c06040526009608090815268746f6b656e4e616d6560b81b60a0526002906200002a908262000266565b5060408051808201909152600b81526a1d1bdad95b94de5b589bdb60aa1b60208201526003906200005c908262000266565b50604080518082019091526004808252636d656d6f60e01b60208301529062000086908262000266565b50600580546001600160b01b0319167501000000000000000004a817c80000000002540be400179055348015620000bb575f80fd5b50600160208181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb499190915560027fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5560047fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5560087f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b5560107fedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643557fe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c5560065f5260407f8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a5562000332565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680620001f157607f821691505b6020821081036200021057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200026157805f5260205f20601f840160051c810160208510156200023d5750805b601f840160051c820191505b818110156200025e575f815560010162000249565b50505b505050565b81516001600160401b03811115620002825762000282620001c8565b6200029a81620002938454620001dc565b8462000216565b602080601f831160018114620002d0575f8415620002b85750858301515b5f19600386901b1c1916600185901b1785556200032a565b5f85815260208120601f198616915b828110156200030057888601518255948401946001909101908401620002df565b50858210156200031e57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b613dce80620003405f395ff3fe608060405260043610610110575f3560e01c80638ba74da01161009d578063d85f74c111610062578063d85f74c1146102cf578063de84a779146102e2578063e9f7322614610301578063f4a01e5b14610314578063f848fec414610333575f80fd5b80638ba74da01461024c5780638f74a17b1461025f5780639b23d3d91461028a578063b35d417a146102a9578063cc265af4146102bc575f80fd5b806336348de3116100e357806336348de3146101ac5780634b5c6687146101cb5780634d1769d6146101de578063618dc65e1461020c57806371de370714610239575f80fd5b80630488c939146101145780630fd2601e14610129578063118741e71461016057806315dacbea1461018d575b5f80fd5b610127610122366004612e28565b610352565b005b348015610134575f80fd5b50610148610143366004612e28565b6108aa565b60405160079190910b81526020015b60405180910390f35b34801561016b575f80fd5b5061017f61017a366004612f37565b610905565b604051908152602001610157565b348015610198575f80fd5b506101486101a7366004612fe6565b610957565b3480156101b7575f80fd5b5061017f6101c6366004613295565b610a46565b6101276101d93660046133d5565b610a51565b3480156101e9575f80fd5b506101fd6101f83660046133f0565b610e84565b604051610157939291906134fd565b348015610217575f80fd5b5061022b610226366004613527565b610f42565b6040516101579291906135c1565b6101276102473660046135e1565b611059565b61012761025a366004612e28565b6111b5565b61027261026d366004613527565b611613565b6040516001600160a01b039091168152602001610157565b348015610295575f80fd5b506101486102a4366004612fe6565b6119fd565b6101276102b7366004613527565b611a41565b6101276102ca366004613527565b611e0e565b6101276102dd3660046133d5565b611ee2565b3480156102ed575f80fd5b506101fd6102fc3660046133f0565b612270565b61027261030f366004613527565b612308565b34801561031f575f80fd5b5061017f61032e366004612e28565b6123df565b34801561033e575f80fd5b5061017f61034d366004613641565b6123ea565b60408051600580825260c082019092525f91816020015b610371612da8565b8152602001906001900390816103695790505090506103a15f60065f60405180602001604052805f815250612444565b815f815181106103b3576103b361367f565b60200260200101819052506103d860015f60405180602001604052805f81525061247b565b816001815181106103eb576103eb61367f565b602002602001018190525061041060025f60405180602001604052805f81525061247b565b816002815181106104235761042361367f565b602002602001018190525061044860045f60405180602001604052805f81525061247b565b8160038151811061045b5761045b61367f565b602002602001018190525061048060035f60405180602001604052805f81525061247b565b816004815181106104935761049361367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f604051806101200160405280600280546104e890613693565b80601f016020809104026020016040519081016040528092919081815260200182805461051490613693565b801561055f5780601f106105365761010080835404028352916020019161055f565b820191905f5260205f20905b81548152906001019060200180831161054257829003601f168201915b505050505081526020016003805461057690613693565b80601f01602080910402602001604051908101604052809291908181526020018280546105a290613693565b80156105ed5780601f106105c4576101008083540402835291602001916105ed565b820191905f5260205f20905b8154815290600101906020018083116105d057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461061390613693565b80601f016020809104026020016040519081016040528092919081815260200182805461063f90613693565b801561068a5780601f106106615761010080835404028352916020019161068a565b820191905f5260205f20905b81548152906001019060200180831161066d57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f600160405190808252806020026020018201604052801561072f57816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816106f65790505b506040805160a081018252600181526001600160a01b0380891660208301525f92820183905260608201839052891660808201528251929350918391906107785761077861367f565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816107995790505090506040518060c00160405280600460070b8152602001600560070b8152602001600a60070b8152602001876001600160a01b031681526020015f15158152602001886001600160a01b0316815250815f8151811061083a5761083a61367f565b60200260200101819052505f806108528585856124b0565b909250905060168214610863575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b5f6108b583836125d0565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b6016146108ff575f80fd5b92915050565b5f61091083836126ae565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161094391815260200190565b60405180910390a1601681146108ff575f80fd5b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109d591906136cb565b5f604051808303815f865af19150503d805f8114610a0e576040519150601f19603f3d011682016040523d82523d5f602084013e610a13565b606091505b509150915081610a24576015610a38565b80806020019051810190610a3891906136f7565b60030b979650505050505050565b5f61091083836126d8565b60408051600680825260e082019092525f91816020015b610a70612da8565b815260200190600190039081610a68579050509050610aa05f60065f60405180602001604052805f815250612444565b815f81518110610ab257610ab261367f565b6020026020010181905250610ad760015f60405180602001604052805f81525061247b565b81600181518110610aea57610aea61367f565b6020026020010181905250610b0f60025f60405180602001604052805f81525061247b565b81600281518110610b2257610b2261367f565b6020026020010181905250610b4760035f60405180602001604052805f81525061247b565b81600381518110610b5a57610b5a61367f565b6020026020010181905250610b7f60045f60405180602001604052805f81525061247b565b81600481518110610b9257610b9261367f565b6020026020010181905250610bb760055f60405180602001604052805f81525061247b565b81600581518110610bca57610bca61367f565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054610c1f90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4b90613693565b8015610c965780601f10610c6d57610100808354040283529160200191610c96565b820191905f5260205f20905b815481529060010190602001808311610c7957829003601f168201915b5050505050815260200160038054610cad90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd990613693565b8015610d245780601f10610cfb57610100808354040283529160200191610d24565b820191905f5260205f20905b815481529060010190602001808311610d0757829003601f168201915b50505050508152602001856001600160a01b0316815260200160048054610d4a90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7690613693565b8015610dc15780601f10610d9857610100808354040283529160200191610dc1565b820191905f5260205f20905b815481529060010190602001808311610da457829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b8204600790810b6040850152600160a01b8304909116151560608401526080830187905260a09092018590529192505f918291610e2f91859181900b90600160801b900460030b612702565b909250905060168214610e40575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b5f806060610e9386868661276b565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610eda575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610f0b929190613710565b60405180910390a1610f38863033845f81518110610f2b57610f2b61367f565b6020026020010151612862565b5093509350939050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610f6e92919061372b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610fac91906136cb565b5f604051808303815f865af19150503d805f8114610fe5576040519150601f19603f3d011682016040523d82523d5f602084013e610fea565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc828260405161102092919061374c565b60405180910390a18161104357601560405180602001604052805f815250611047565b6016815b60039190910b97909650945050505050565b604051638f74a17b60e01b81525f903090638f74a17b903490611082908890889060040161372b565b60206040518083038185885af115801561109e573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906110c39190613766565b60405163f4a01e5b60e01b81523360048201526001600160a01b0382166024820152909150309063f4a01e5b906044016020604051808303815f875af115801561110f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111339190613781565b506040516307e9300f60e11b81526001600160a01b03821660048201523360248201523090630fd2601e906044016020604051808303815f875af115801561117d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a19190613798565b506111ae813033856128a9565b5050505050565b6040805160018082528183019092525f91816020015b6111d3612da8565b8152602001906001900390816111cb5790505090506112025f805f60405180602001604052805f815250612444565b815f815181106112145761121461367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461126990613693565b80601f016020809104026020016040519081016040528092919081815260200182805461129590613693565b80156112e05780601f106112b7576101008083540402835291602001916112e0565b820191905f5260205f20905b8154815290600101906020018083116112c357829003601f168201915b50505050508152602001600380546112f790613693565b80601f016020809104026020016040519081016040528092919081815260200182805461132390613693565b801561136e5780601f106113455761010080835404028352916020019161136e565b820191905f5260205f20905b81548152906001019060200180831161135157829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461139490613693565b80601f01602080910402602001604051908101604052809291908181526020018280546113c090613693565b801561140b5780601f106113e25761010080835404028352916020019161140b565b820191905f5260205f20905b8154815290600101906020018083116113ee57829003601f168201915b5050509183525050600554600160a81b810460ff1615156020830152600160401b900460070b6040808301919091525f606083018190526080830187905260a090920185905280516001808252818301909252929350909190816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816114695750506040805160a081018252600181526001600160a01b0388811660208301525f92820183905260608201839052891660808201528251929350918391906114e9576114e961367f565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f1990920191018161150a5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201525f608082018190526001600160a01b038a1660a08301528251929350909183919061159b5761159b61367f565b60209081029190910101526005545f9081906115ca908690600781900b90600160801b900460030b87876128f0565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa826040516115ff91815260200190565b60405180910390a160168214610863575f80fd5b60408051600680825260e082019092525f91829190816020015b611635612da8565b81526020019060019003908161162d5790505090506116585f6006600386612444565b815f8151811061166a5761166a61367f565b6020026020010181905250611682600160038561247b565b816001815181106116955761169561367f565b60200260200101819052506116ad600260038561247b565b816002815181106116c0576116c061367f565b60200260200101819052506116d8600460038561247b565b816003815181106116eb576116eb61367f565b60200260200101819052506117026003808561247b565b816004815181106117155761171561367f565b602002602001018190525061172d600560038561247b565b816005815181106117405761174061367f565b60200260200101819052505f60405180606001604052805f60070b8152602001866001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461179590613693565b80601f01602080910402602001604051908101604052809291908181526020018280546117c190613693565b801561180c5780601f106117e35761010080835404028352916020019161180c565b820191905f5260205f20905b8154815290600101906020018083116117ef57829003601f168201915b505050505081526020016003805461182390613693565b80601f016020809104026020016040519081016040528092919081815260200182805461184f90613693565b801561189a5780601f106118715761010080835404028352916020019161189a565b820191905f5260205f20905b81548152906001019060200180831161187d57829003601f168201915b50505050508152602001876001600160a01b03168152602001600480546118c090613693565b80601f01602080910402602001604051908101604052809291908181526020018280546118ec90613693565b80156119375780601f1061190e57610100808354040283529160200191611937565b820191905f5260205f20905b81548152906001019060200180831161191a57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b8204600790810b6040850152600160a01b8304909116151560608401526080830187905260a09092018590529192505f9182916119a591859181900b90600160801b900460030b612702565b9092509050601682146119b6575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1979650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610997565b60408051600680825260e082019092525f91816020015b611a60612da8565b815260200190600190039081611a58579050509050611a835f6006600385612444565b815f81518110611a9557611a9561367f565b6020026020010181905250611aad600160038461247b565b81600181518110611ac057611ac061367f565b6020026020010181905250611ad8600260038461247b565b81600281518110611aeb57611aeb61367f565b6020026020010181905250611b03600460038461247b565b81600381518110611b1657611b1661367f565b6020026020010181905250611b2d6003808461247b565b81600481518110611b4057611b4061367f565b6020026020010181905250611b58600560038461247b565b81600581518110611b6b57611b6b61367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054611bc090613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611bec90613693565b8015611c375780601f10611c0e57610100808354040283529160200191611c37565b820191905f5260205f20905b815481529060010190602001808311611c1a57829003601f168201915b5050505050815260200160038054611c4e90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611c7a90613693565b8015611cc55780601f10611c9c57610100808354040283529160200191611cc5565b820191905f5260205f20905b815481529060010190602001808311611ca857829003601f168201915b50505050508152602001866001600160a01b0316815260200160048054611ceb90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611d1790613693565b8015611d625780601f10611d3957610100808354040283529160200191611d62565b820191905f5260205f20905b815481529060010190602001808311611d4557829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f80611db883612a16565b909250905060168214611dc9575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050565b60408051600480825260a082019092525f91816020015b611e2d612da8565b815260200190600190039081611e25579050509050611e505f6006600385612444565b815f81518110611e6257611e6261367f565b6020026020010181905250611e7a600260038461247b565b81600181518110611e8d57611e8d61367f565b6020026020010181905250611ea5600460038461247b565b81600281518110611eb857611eb861367f565b6020026020010181905250611ecf6003808461247b565b81600381518110611b6b57611b6b61367f565b60408051600580825260c082019092525f91816020015b611f01612da8565b815260200190600190039081611ef9579050509050611f315f60065f60405180602001604052805f815250612444565b815f81518110611f4357611f4361367f565b6020026020010181905250611f6860015f60405180602001604052805f81525061247b565b81600181518110611f7b57611f7b61367f565b6020026020010181905250611fa060025f60405180602001604052805f81525061247b565b81600281518110611fb357611fb361367f565b6020026020010181905250611fd860045f60405180602001604052805f81525061247b565b81600381518110611feb57611feb61367f565b602002602001018190525061201060035f60405180602001604052805f81525061247b565b816004815181106120235761202361367f565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461207890613693565b80601f01602080910402602001604051908101604052809291908181526020018280546120a490613693565b80156120ef5780601f106120c6576101008083540402835291602001916120ef565b820191905f5260205f20905b8154815290600101906020018083116120d257829003601f168201915b505050505081526020016003805461210690613693565b80601f016020809104026020016040519081016040528092919081815260200182805461213290613693565b801561217d5780601f106121545761010080835404028352916020019161217d565b820191905f5260205f20905b81548152906001019060200180831161216057829003601f168201915b50505050508152602001856001600160a01b03168152602001600480546121a390613693565b80601f01602080910402602001604051908101604052809291908181526020018280546121cf90613693565b801561221a5780601f106121f15761010080835404028352916020019161221a565b820191905f5260205f20905b8154815290600101906020018083116121fd57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f80610e2f83612a16565b5f80606061227f86868661276b565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1601683146122c6575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d82826040516122f7929190613710565b60405180910390a193509350939050565b60408051600480825260a082019092525f91829190816020015b61232a612da8565b81526020019060019003908161232257905050905061234d5f6006600386612444565b815f8151811061235f5761235f61367f565b6020026020010181905250612377600260038561247b565b8160018151811061238a5761238a61367f565b60200260200101819052506123a2600460038561247b565b816002815181106123b5576123b561367f565b60200260200101819052506123cc6003808561247b565b816003815181106117405761174061367f565b5f6109108383612b1e565b5f6123f6848484612b53565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161242991815260200190565b60405180910390a16016811461243d575f80fd5b9392505050565b61244c612da8565b60405180604001604052806124618787612c27565b81526020016124708585612c61565b905295945050505050565b612483612da8565b604051806040016040528061249786612d6c565b81526020016124a68585612c61565b9052949350505050565b5f80848061010001515f015160070b5f1480156124d757506101008101516040015160070b155b156124ed576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401612519939291906139e5565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161255791906136cb565b5f6040518083038185875af1925050503d805f8114612591576040519150601f19603f3d011682016040523d82523d5f602084013e612596565b606091505b5091509150816125a85760155f6125bc565b808060200190518101906125bc9190613a9c565b60039190910b999098509650505050505050565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161263f91906136cb565b5f604051808303815f865af19150503d805f8114612678576040519150601f19603f3d011682016040523d82523d5f602084013e61267d565b606091505b50915091508161268e5760156126a2565b808060200190518101906126a291906136f7565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401612601929190613ac6565b5f805f6101676001600160a01b0316637d305cfa60e01b8686604051602401612601929190613b21565b5f80848061010001515f015160070b5f14801561272957506101008101516040015160070b155b1561273f576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a60405160240161251993929190613b42565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161279a93929190613b70565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516127d891906136cb565b5f604051808303815f865af19150503d805f8114612811576040519150601f19603f3d011682016040523d82523d5f602084013e612816565b606091505b50915091508161283857604080515f808252602082019092526015919061284c565b8080602001905181019061284c9190613bed565b60039290920b9a90995090975095505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610997565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610997565b5f80868061010001515f015160070b5f14801561291757506101008101516040015160070b155b1561292d576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c60405160240161295d959493929190613ca7565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161299b91906136cb565b5f6040518083038185875af1925050503d805f81146129d5576040519150601f19603f3d011682016040523d82523d5f602084013e6129da565b606091505b5091509150816129ec5760155f612a00565b80806020019051810190612a009190613a9c565b60039190910b9b909a5098505050505050505050565b5f80828061010001515f015160070b5f148015612a3d57506101008101516040015160070b155b15612a53576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401612a7b9190613d72565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612ab991906136cb565b5f6040518083038185875af1925050503d805f8114612af3576040519150601f19603f3d011682016040523d82523d5f602084013e612af8565b606091505b509150915081612b0a5760155f611047565b808060200190518101906110479190613a9c565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401612601565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f918291829161016791612bb791906136cb565b5f604051808303815f865af19150503d805f8114612bf0576040519150601f19603f3d011682016040523d82523d5f602084013e612bf5565b606091505b509150915081612c06576015612c1a565b80806020019051810190612c1a91906136f7565b60030b9695505050505050565b5f612c4a836006811115612c3d57612c3d613d84565b600160ff9091161b821790565b905061243d826006811115612c3d57612c3d613d84565b612ca46040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f836004811115612cb757612cb7613d84565b03612cc557600181526108ff565b6001836004811115612cd957612cd9613d84565b03612cf3575f546001600160a01b031660208201526108ff565b6002836004811115612d0757612d07613d84565b03612d1857604081018290526108ff565b6003836004811115612d2c57612d2c613d84565b03612d3d57606081018290526108ff565b6004836004811115612d5157612d51613d84565b036108ff575f546001600160a01b0316608082015292915050565b5f60015f836006811115612d8257612d82613d84565b6006811115612d9357612d93613d84565b81526020019081526020015f20549050919050565b60405180604001604052805f8152602001612dfc6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b0381168114612e15575f80fd5b50565b8035612e2381612e01565b919050565b5f8060408385031215612e39575f80fd5b8235612e4481612e01565b91506020830135612e5481612e01565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612e9657612e96612e5f565b60405290565b60405160a0810167ffffffffffffffff81118282101715612e9657612e96612e5f565b604051610120810167ffffffffffffffff81118282101715612e9657612e96612e5f565b604051601f8201601f1916810167ffffffffffffffff81118282101715612f0c57612f0c612e5f565b604052919050565b5f67ffffffffffffffff821115612f2d57612f2d612e5f565b5060051b60200190565b5f8060408385031215612f48575f80fd5b8235612f5381612e01565b915060208381013567ffffffffffffffff811115612f6f575f80fd5b8401601f81018613612f7f575f80fd5b8035612f92612f8d82612f14565b612ee3565b81815260059190911b82018301908381019088831115612fb0575f80fd5b928401925b82841015612fd7578335612fc881612e01565b82529284019290840190612fb5565b80955050505050509250929050565b5f805f8060808587031215612ff9575f80fd5b843561300481612e01565b9350602085013561301481612e01565b9250604085013561302481612e01565b9396929550929360600135925050565b5f82601f830112613043575f80fd5b813567ffffffffffffffff81111561305d5761305d612e5f565b613070601f8201601f1916602001612ee3565b818152846020838601011115613084575f80fd5b816020850160208301375f918101602001919091529392505050565b80358015158114612e23575f80fd5b8060070b8114612e15575f80fd5b8035612e23816130af565b5f82601f8301126130d7575f80fd5b813560206130e7612f8d83612f14565b82815260059290921b84018101918181019086841115613105575f80fd5b8286015b8481101561321657803567ffffffffffffffff80821115613128575f80fd5b908801906040601f19838c038101821315613141575f80fd5b613149612e73565b888501358152828501358481111561315f575f80fd5b949094019360a0858e0383011215613175575f80fd5b61317d612e9c565b915061318a8986016130a0565b82528285013561319981612e01565b828a0152606085810135858111156131af575f80fd5b6131bd8f8c838a0101613034565b85850152506080935083860135858111156131d6575f80fd5b6131e48f8c838a0101613034565b82850152505060a085013594506131fa85612e01565b9181019390935280870192909252508352918301918301613109565b509695505050505050565b5f60608284031215613231575f80fd5b6040516060810181811067ffffffffffffffff8211171561325457613254612e5f565b6040529050808235613265816130af565b8152602083013561327581612e01565b60208201526040830135613288816130af565b6040919091015292915050565b5f80604083850312156132a6575f80fd5b82356132b181612e01565b9150602083013567ffffffffffffffff808211156132cd575f80fd5b9084019061016082870312156132e1575f80fd5b6132e9612ebf565b8235828111156132f7575f80fd5b61330388828601613034565b825250602083013582811115613317575f80fd5b61332388828601613034565b60208301525061333560408401612e18565b604082015260608301358281111561334b575f80fd5b61335788828601613034565b606083015250613369608084016130a0565b608082015261337a60a084016130bd565b60a082015261338b60c084016130a0565b60c082015260e0830135828111156133a1575f80fd5b6133ad888286016130c8565b60e08301525061010091506133c487838501613221565b828201528093505050509250929050565b5f602082840312156133e5575f80fd5b813561243d81612e01565b5f805f60608486031215613402575f80fd5b833561340d81612e01565b925060208481013561341e816130af565b9250604085013567ffffffffffffffff8082111561343a575f80fd5b818701915087601f83011261344d575f80fd5b813561345b612f8d82612f14565b81815260059190911b8301840190848101908a831115613479575f80fd5b8585015b838110156134af57803585811115613493575f80fd5b6134a18d89838a0101613034565b84525091860191860161347d565b508096505050505050509250925092565b5f815180845260208085019450602084015f5b838110156134f257815160070b875295820195908201906001016134d3565b509495945050505050565b8381528260070b6020820152606060408201525f61351e60608301846134c0565b95945050505050565b5f8060408385031215613538575f80fd5b823561354381612e01565b9150602083013567ffffffffffffffff81111561355e575f80fd5b61356a85828601613034565b9150509250929050565b5f5b8381101561358e578181015183820152602001613576565b50505f910152565b5f81518084526135ad816020860160208601613574565b601f01601f19169290920160200192915050565b828152604060208201525f6135d96040830184613596565b949350505050565b5f805f606084860312156135f3575f80fd5b83356135fe81612e01565b9250602084013567ffffffffffffffff811115613619575f80fd5b61362586828701613034565b9250506040840135613636816130af565b809150509250925092565b5f805f60608486031215613653575f80fd5b833561365e81612e01565b9250602084013561366e81612e01565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b600181811c908216806136a757607f821691505b6020821081036136c557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82516136dc818460208701613574565b9190910192915050565b8051600381900b8114612e23575f80fd5b5f60208284031215613707575f80fd5b61243d826136e6565b8260070b8152604060208201525f6135d960408301846134c0565b6001600160a01b0383168152604060208201525f6135d96040830184613596565b8215158152604060208201525f6135d96040830184613596565b5f60208284031215613776575f80fd5b815161243d81612e01565b5f60208284031215613791575f80fd5b5051919050565b5f602082840312156137a8575f80fd5b815161243d816130af565b5f82825180855260208086019550808260051b8401018186015f5b8481101561386b57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261382d60e08a0186613596565b92860151898403603f1901858b01529294506138498584613596565b9501511660c097909701969096525050988401989250908301906001016137ce565b5090979650505050505050565b5f610160825181855261388d82860182613596565b915050602083015184820360208601526138a78282613596565b91505060408301516138c460408601826001600160a01b03169052565b50606083015184820360608601526138dc8282613596565b91505060808301516138f2608086018215159052565b5060a083015161390760a086018260070b9052565b5060c083015161391b60c086018215159052565b5060e083015184820360e086015261393382826137b3565b9150506101008084015161396f82870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b5f815180845260208085019450602084015f5b838110156134f2578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a0909601959082019060010161398c565b5f60608083526139f86060840187613878565b602084820381860152613a0b8288613979565b915060408583036040870152828751808552838501915083890194505f5b81811015613a8c5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c090920191600101613a29565b50909a9950505050505050505050565b5f8060408385031215613aad575f80fd5b613ab6836136e6565b91506020830151612e5481612e01565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b81811015613b13578551851683529483019491830191600101613af5565b509098975050505050505050565b6001600160a01b0383168152604060208201525f6135d96040830184613878565b606081525f613b546060830186613878565b90508360070b60208301528260030b6040830152949350505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b82811015613bde57607f19888703018452613bcc868351613596565b95509284019290840190600101613bb0565b50939998505050505050505050565b5f805f60608486031215613bff575f80fd5b613c08846136e6565b9250602080850151613c19816130af565b604086015190935067ffffffffffffffff811115613c35575f80fd5b8501601f81018713613c45575f80fd5b8051613c53612f8d82612f14565b81815260059190911b82018301908381019089831115613c71575f80fd5b928401925b82841015613c98578351613c89816130af565b82529284019290840190613c76565b80955050505050509250925092565b5f60a0808352613cba60a0840189613878565b602060078960070b8287015260408960030b604088015260608785036060890152613ce5858b613979565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015613d5d5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101613d03565b50909f9e505050505050505050505050505050565b602081525f61243d6020830184613878565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220bde982ed61fd25cf9c5b9be5447911c6410d7ca4a16c083fdf466877d0a76f3d64736f6c63430008180033", + "deployedBytecode": "0x608060405260043610610110575f3560e01c80638ba74da01161009d578063d85f74c111610062578063d85f74c1146102cf578063de84a779146102e2578063e9f7322614610301578063f4a01e5b14610314578063f848fec414610333575f80fd5b80638ba74da01461024c5780638f74a17b1461025f5780639b23d3d91461028a578063b35d417a146102a9578063cc265af4146102bc575f80fd5b806336348de3116100e357806336348de3146101ac5780634b5c6687146101cb5780634d1769d6146101de578063618dc65e1461020c57806371de370714610239575f80fd5b80630488c939146101145780630fd2601e14610129578063118741e71461016057806315dacbea1461018d575b5f80fd5b610127610122366004612e28565b610352565b005b348015610134575f80fd5b50610148610143366004612e28565b6108aa565b60405160079190910b81526020015b60405180910390f35b34801561016b575f80fd5b5061017f61017a366004612f37565b610905565b604051908152602001610157565b348015610198575f80fd5b506101486101a7366004612fe6565b610957565b3480156101b7575f80fd5b5061017f6101c6366004613295565b610a46565b6101276101d93660046133d5565b610a51565b3480156101e9575f80fd5b506101fd6101f83660046133f0565b610e84565b604051610157939291906134fd565b348015610217575f80fd5b5061022b610226366004613527565b610f42565b6040516101579291906135c1565b6101276102473660046135e1565b611059565b61012761025a366004612e28565b6111b5565b61027261026d366004613527565b611613565b6040516001600160a01b039091168152602001610157565b348015610295575f80fd5b506101486102a4366004612fe6565b6119fd565b6101276102b7366004613527565b611a41565b6101276102ca366004613527565b611e0e565b6101276102dd3660046133d5565b611ee2565b3480156102ed575f80fd5b506101fd6102fc3660046133f0565b612270565b61027261030f366004613527565b612308565b34801561031f575f80fd5b5061017f61032e366004612e28565b6123df565b34801561033e575f80fd5b5061017f61034d366004613641565b6123ea565b60408051600580825260c082019092525f91816020015b610371612da8565b8152602001906001900390816103695790505090506103a15f60065f60405180602001604052805f815250612444565b815f815181106103b3576103b361367f565b60200260200101819052506103d860015f60405180602001604052805f81525061247b565b816001815181106103eb576103eb61367f565b602002602001018190525061041060025f60405180602001604052805f81525061247b565b816002815181106104235761042361367f565b602002602001018190525061044860045f60405180602001604052805f81525061247b565b8160038151811061045b5761045b61367f565b602002602001018190525061048060035f60405180602001604052805f81525061247b565b816004815181106104935761049361367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f604051806101200160405280600280546104e890613693565b80601f016020809104026020016040519081016040528092919081815260200182805461051490613693565b801561055f5780601f106105365761010080835404028352916020019161055f565b820191905f5260205f20905b81548152906001019060200180831161054257829003601f168201915b505050505081526020016003805461057690613693565b80601f01602080910402602001604051908101604052809291908181526020018280546105a290613693565b80156105ed5780601f106105c4576101008083540402835291602001916105ed565b820191905f5260205f20905b8154815290600101906020018083116105d057829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461061390613693565b80601f016020809104026020016040519081016040528092919081815260200182805461063f90613693565b801561068a5780601f106106615761010080835404028352916020019161068a565b820191905f5260205f20905b81548152906001019060200180831161066d57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f600160405190808252806020026020018201604052801561072f57816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816106f65790505b506040805160a081018252600181526001600160a01b0380891660208301525f92820183905260608201839052891660808201528251929350918391906107785761077861367f565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816107995790505090506040518060c00160405280600460070b8152602001600560070b8152602001600a60070b8152602001876001600160a01b031681526020015f15158152602001886001600160a01b0316815250815f8151811061083a5761083a61367f565b60200260200101819052505f806108528585856124b0565b909250905060168214610863575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050565b5f6108b583836125d0565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b6016146108ff575f80fd5b92915050565b5f61091083836126ae565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161094391815260200190565b60405180910390a1601681146108ff575f80fd5b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516109d591906136cb565b5f604051808303815f865af19150503d805f8114610a0e576040519150601f19603f3d011682016040523d82523d5f602084013e610a13565b606091505b509150915081610a24576015610a38565b80806020019051810190610a3891906136f7565b60030b979650505050505050565b5f61091083836126d8565b60408051600680825260e082019092525f91816020015b610a70612da8565b815260200190600190039081610a68579050509050610aa05f60065f60405180602001604052805f815250612444565b815f81518110610ab257610ab261367f565b6020026020010181905250610ad760015f60405180602001604052805f81525061247b565b81600181518110610aea57610aea61367f565b6020026020010181905250610b0f60025f60405180602001604052805f81525061247b565b81600281518110610b2257610b2261367f565b6020026020010181905250610b4760035f60405180602001604052805f81525061247b565b81600381518110610b5a57610b5a61367f565b6020026020010181905250610b7f60045f60405180602001604052805f81525061247b565b81600481518110610b9257610b9261367f565b6020026020010181905250610bb760055f60405180602001604052805f81525061247b565b81600581518110610bca57610bca61367f565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054610c1f90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4b90613693565b8015610c965780601f10610c6d57610100808354040283529160200191610c96565b820191905f5260205f20905b815481529060010190602001808311610c7957829003601f168201915b5050505050815260200160038054610cad90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd990613693565b8015610d245780601f10610cfb57610100808354040283529160200191610d24565b820191905f5260205f20905b815481529060010190602001808311610d0757829003601f168201915b50505050508152602001856001600160a01b0316815260200160048054610d4a90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7690613693565b8015610dc15780601f10610d9857610100808354040283529160200191610dc1565b820191905f5260205f20905b815481529060010190602001808311610da457829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b8204600790810b6040850152600160a01b8304909116151560608401526080830187905260a09092018590529192505f918291610e2f91859181900b90600160801b900460030b612702565b909250905060168214610e40575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050565b5f806060610e9386868661276b565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610eda575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610f0b929190613710565b60405180910390a1610f38863033845f81518110610f2b57610f2b61367f565b6020026020010151612862565b5093509350939050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610f6e92919061372b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610fac91906136cb565b5f604051808303815f865af19150503d805f8114610fe5576040519150601f19603f3d011682016040523d82523d5f602084013e610fea565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc828260405161102092919061374c565b60405180910390a18161104357601560405180602001604052805f815250611047565b6016815b60039190910b97909650945050505050565b604051638f74a17b60e01b81525f903090638f74a17b903490611082908890889060040161372b565b60206040518083038185885af115801561109e573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906110c39190613766565b60405163f4a01e5b60e01b81523360048201526001600160a01b0382166024820152909150309063f4a01e5b906044016020604051808303815f875af115801561110f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111339190613781565b506040516307e9300f60e11b81526001600160a01b03821660048201523360248201523090630fd2601e906044016020604051808303815f875af115801561117d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a19190613798565b506111ae813033856128a9565b5050505050565b6040805160018082528183019092525f91816020015b6111d3612da8565b8152602001906001900390816111cb5790505090506112025f805f60405180602001604052805f815250612444565b815f815181106112145761121461367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461126990613693565b80601f016020809104026020016040519081016040528092919081815260200182805461129590613693565b80156112e05780601f106112b7576101008083540402835291602001916112e0565b820191905f5260205f20905b8154815290600101906020018083116112c357829003601f168201915b50505050508152602001600380546112f790613693565b80601f016020809104026020016040519081016040528092919081815260200182805461132390613693565b801561136e5780601f106113455761010080835404028352916020019161136e565b820191905f5260205f20905b81548152906001019060200180831161135157829003601f168201915b50505050508152602001866001600160a01b031681526020016004805461139490613693565b80601f01602080910402602001604051908101604052809291908181526020018280546113c090613693565b801561140b5780601f106113e25761010080835404028352916020019161140b565b820191905f5260205f20905b8154815290600101906020018083116113ee57829003601f168201915b5050509183525050600554600160a81b810460ff1615156020830152600160401b900460070b6040808301919091525f606083018190526080830187905260a090920185905280516001808252818301909252929350909190816020015b6040805160a0810182525f808252602080830182905292820181905260608201819052608082015282525f199092019101816114695750506040805160a081018252600181526001600160a01b0388811660208301525f92820183905260608201839052891660808201528251929350918391906114e9576114e961367f565b60209081029190910101526040805160018082528183019092525f91816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f1990920191018161150a5750506040805160c0810182526004815260056020820152600a91810191909152601e60608201525f608082018190526001600160a01b038a1660a08301528251929350909183919061159b5761159b61367f565b60209081029190910101526005545f9081906115ca908690600781900b90600160801b900460030b87876128f0565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa826040516115ff91815260200190565b60405180910390a160168214610863575f80fd5b60408051600680825260e082019092525f91829190816020015b611635612da8565b81526020019060019003908161162d5790505090506116585f6006600386612444565b815f8151811061166a5761166a61367f565b6020026020010181905250611682600160038561247b565b816001815181106116955761169561367f565b60200260200101819052506116ad600260038561247b565b816002815181106116c0576116c061367f565b60200260200101819052506116d8600460038561247b565b816003815181106116eb576116eb61367f565b60200260200101819052506117026003808561247b565b816004815181106117155761171561367f565b602002602001018190525061172d600560038561247b565b816005815181106117405761174061367f565b60200260200101819052505f60405180606001604052805f60070b8152602001866001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461179590613693565b80601f01602080910402602001604051908101604052809291908181526020018280546117c190613693565b801561180c5780601f106117e35761010080835404028352916020019161180c565b820191905f5260205f20905b8154815290600101906020018083116117ef57829003601f168201915b505050505081526020016003805461182390613693565b80601f016020809104026020016040519081016040528092919081815260200182805461184f90613693565b801561189a5780601f106118715761010080835404028352916020019161189a565b820191905f5260205f20905b81548152906001019060200180831161187d57829003601f168201915b50505050508152602001876001600160a01b03168152602001600480546118c090613693565b80601f01602080910402602001604051908101604052809291908181526020018280546118ec90613693565b80156119375780601f1061190e57610100808354040283529160200191611937565b820191905f5260205f20905b81548152906001019060200180831161191a57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b8204600790810b6040850152600160a01b8304909116151560608401526080830187905260a09092018590529192505f9182916119a591859181900b90600160801b900460030b612702565b9092509050601682146119b6575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1979650505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610997565b60408051600680825260e082019092525f91816020015b611a60612da8565b815260200190600190039081611a58579050509050611a835f6006600385612444565b815f81518110611a9557611a9561367f565b6020026020010181905250611aad600160038461247b565b81600181518110611ac057611ac061367f565b6020026020010181905250611ad8600260038461247b565b81600281518110611aeb57611aeb61367f565b6020026020010181905250611b03600460038461247b565b81600381518110611b1657611b1661367f565b6020026020010181905250611b2d6003808461247b565b81600481518110611b4057611b4061367f565b6020026020010181905250611b58600560038461247b565b81600581518110611b6b57611b6b61367f565b60200260200101819052505f60405180606001604052805f60070b8152602001856001600160a01b03168152602001627a120060070b81525090505f60405180610120016040528060028054611bc090613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611bec90613693565b8015611c375780601f10611c0e57610100808354040283529160200191611c37565b820191905f5260205f20905b815481529060010190602001808311611c1a57829003601f168201915b5050505050815260200160038054611c4e90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611c7a90613693565b8015611cc55780601f10611c9c57610100808354040283529160200191611cc5565b820191905f5260205f20905b815481529060010190602001808311611ca857829003601f168201915b50505050508152602001866001600160a01b0316815260200160048054611ceb90613693565b80601f0160208091040260200160405190810160405280929190818152602001828054611d1790613693565b8015611d625780601f10611d3957610100808354040283529160200191611d62565b820191905f5260205f20905b815481529060010190602001808311611d4557829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f80611db883612a16565b909250905060168214611dc9575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050565b60408051600480825260a082019092525f91816020015b611e2d612da8565b815260200190600190039081611e25579050509050611e505f6006600385612444565b815f81518110611e6257611e6261367f565b6020026020010181905250611e7a600260038461247b565b81600181518110611e8d57611e8d61367f565b6020026020010181905250611ea5600460038461247b565b81600281518110611eb857611eb861367f565b6020026020010181905250611ecf6003808461247b565b81600381518110611b6b57611b6b61367f565b60408051600580825260c082019092525f91816020015b611f01612da8565b815260200190600190039081611ef9579050509050611f315f60065f60405180602001604052805f815250612444565b815f81518110611f4357611f4361367f565b6020026020010181905250611f6860015f60405180602001604052805f81525061247b565b81600181518110611f7b57611f7b61367f565b6020026020010181905250611fa060025f60405180602001604052805f81525061247b565b81600281518110611fb357611fb361367f565b6020026020010181905250611fd860045f60405180602001604052805f81525061247b565b81600381518110611feb57611feb61367f565b602002602001018190525061201060035f60405180602001604052805f81525061247b565b816004815181106120235761202361367f565b60200260200101819052505f60405180606001604052805f60070b8152602001846001600160a01b03168152602001627a120060070b81525090505f6040518061012001604052806002805461207890613693565b80601f01602080910402602001604051908101604052809291908181526020018280546120a490613693565b80156120ef5780601f106120c6576101008083540402835291602001916120ef565b820191905f5260205f20905b8154815290600101906020018083116120d257829003601f168201915b505050505081526020016003805461210690613693565b80601f016020809104026020016040519081016040528092919081815260200182805461213290613693565b801561217d5780601f106121545761010080835404028352916020019161217d565b820191905f5260205f20905b81548152906001019060200180831161216057829003601f168201915b50505050508152602001856001600160a01b03168152602001600480546121a390613693565b80601f01602080910402602001604051908101604052809291908181526020018280546121cf90613693565b801561221a5780601f106121f15761010080835404028352916020019161221a565b820191905f5260205f20905b8154815290600101906020018083116121fd57829003601f168201915b505050918352505060055460ff600160a81b8204811615156020840152600160401b820460070b6040840152600160a01b90910416151560608201526080810185905260a00183905290505f80610e2f83612a16565b5f80606061227f86868661276b565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1601683146122c6575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d82826040516122f7929190613710565b60405180910390a193509350939050565b60408051600480825260a082019092525f91829190816020015b61232a612da8565b81526020019060019003908161232257905050905061234d5f6006600386612444565b815f8151811061235f5761235f61367f565b6020026020010181905250612377600260038561247b565b8160018151811061238a5761238a61367f565b60200260200101819052506123a2600460038561247b565b816002815181106123b5576123b561367f565b60200260200101819052506123cc6003808561247b565b816003815181106117405761174061367f565b5f6109108383612b1e565b5f6123f6848484612b53565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161242991815260200190565b60405180910390a16016811461243d575f80fd5b9392505050565b61244c612da8565b60405180604001604052806124618787612c27565b81526020016124708585612c61565b905295945050505050565b612483612da8565b604051806040016040528061249786612d6c565b81526020016124a68585612c61565b9052949350505050565b5f80848061010001515f015160070b5f1480156124d757506101008101516040015160070b155b156124ed576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401612519939291906139e5565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161255791906136cb565b5f6040518083038185875af1925050503d805f8114612591576040519150601f19603f3d011682016040523d82523d5f602084013e612596565b606091505b5091509150816125a85760155f6125bc565b808060200190518101906125bc9190613a9c565b60039190910b999098509650505050505050565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161263f91906136cb565b5f604051808303815f865af19150503d805f8114612678576040519150601f19603f3d011682016040523d82523d5f602084013e61267d565b606091505b50915091508161268e5760156126a2565b808060200190518101906126a291906136f7565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401612601929190613ac6565b5f805f6101676001600160a01b0316637d305cfa60e01b8686604051602401612601929190613b21565b5f80848061010001515f015160070b5f14801561272957506101008101516040015160070b155b1561273f576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a60405160240161251993929190613b42565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161279a93929190613b70565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516127d891906136cb565b5f604051808303815f865af19150503d805f8114612811576040519150601f19603f3d011682016040523d82523d5f602084013e612816565b606091505b50915091508161283857604080515f808252602082019092526015919061284c565b8080602001905181019061284c9190613bed565b60039290920b9a90995090975095505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610997565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610997565b5f80868061010001515f015160070b5f14801561291757506101008101516040015160070b155b1561292d576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c60405160240161295d959493929190613ca7565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161299b91906136cb565b5f6040518083038185875af1925050503d805f81146129d5576040519150601f19603f3d011682016040523d82523d5f602084013e6129da565b606091505b5091509150816129ec5760155f612a00565b80806020019051810190612a009190613a9c565b60039190910b9b909a5098505050505050505050565b5f80828061010001515f015160070b5f148015612a3d57506101008101516040015160070b155b15612a53576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401612a7b9190613d72565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612ab991906136cb565b5f6040518083038185875af1925050503d805f8114612af3576040519150601f19603f3d011682016040523d82523d5f602084013e612af8565b606091505b509150915081612b0a5760155f611047565b808060200190518101906110479190613a9c565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401612601565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f918291829161016791612bb791906136cb565b5f604051808303815f865af19150503d805f8114612bf0576040519150601f19603f3d011682016040523d82523d5f602084013e612bf5565b606091505b509150915081612c06576015612c1a565b80806020019051810190612c1a91906136f7565b60030b9695505050505050565b5f612c4a836006811115612c3d57612c3d613d84565b600160ff9091161b821790565b905061243d826006811115612c3d57612c3d613d84565b612ca46040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f836004811115612cb757612cb7613d84565b03612cc557600181526108ff565b6001836004811115612cd957612cd9613d84565b03612cf3575f546001600160a01b031660208201526108ff565b6002836004811115612d0757612d07613d84565b03612d1857604081018290526108ff565b6003836004811115612d2c57612d2c613d84565b03612d3d57606081018290526108ff565b6004836004811115612d5157612d51613d84565b036108ff575f546001600160a01b0316608082015292915050565b5f60015f836006811115612d8257612d82613d84565b6006811115612d9357612d93613d84565b81526020019081526020015f20549050919050565b60405180604001604052805f8152602001612dfc6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b0381168114612e15575f80fd5b50565b8035612e2381612e01565b919050565b5f8060408385031215612e39575f80fd5b8235612e4481612e01565b91506020830135612e5481612e01565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715612e9657612e96612e5f565b60405290565b60405160a0810167ffffffffffffffff81118282101715612e9657612e96612e5f565b604051610120810167ffffffffffffffff81118282101715612e9657612e96612e5f565b604051601f8201601f1916810167ffffffffffffffff81118282101715612f0c57612f0c612e5f565b604052919050565b5f67ffffffffffffffff821115612f2d57612f2d612e5f565b5060051b60200190565b5f8060408385031215612f48575f80fd5b8235612f5381612e01565b915060208381013567ffffffffffffffff811115612f6f575f80fd5b8401601f81018613612f7f575f80fd5b8035612f92612f8d82612f14565b612ee3565b81815260059190911b82018301908381019088831115612fb0575f80fd5b928401925b82841015612fd7578335612fc881612e01565b82529284019290840190612fb5565b80955050505050509250929050565b5f805f8060808587031215612ff9575f80fd5b843561300481612e01565b9350602085013561301481612e01565b9250604085013561302481612e01565b9396929550929360600135925050565b5f82601f830112613043575f80fd5b813567ffffffffffffffff81111561305d5761305d612e5f565b613070601f8201601f1916602001612ee3565b818152846020838601011115613084575f80fd5b816020850160208301375f918101602001919091529392505050565b80358015158114612e23575f80fd5b8060070b8114612e15575f80fd5b8035612e23816130af565b5f82601f8301126130d7575f80fd5b813560206130e7612f8d83612f14565b82815260059290921b84018101918181019086841115613105575f80fd5b8286015b8481101561321657803567ffffffffffffffff80821115613128575f80fd5b908801906040601f19838c038101821315613141575f80fd5b613149612e73565b888501358152828501358481111561315f575f80fd5b949094019360a0858e0383011215613175575f80fd5b61317d612e9c565b915061318a8986016130a0565b82528285013561319981612e01565b828a0152606085810135858111156131af575f80fd5b6131bd8f8c838a0101613034565b85850152506080935083860135858111156131d6575f80fd5b6131e48f8c838a0101613034565b82850152505060a085013594506131fa85612e01565b9181019390935280870192909252508352918301918301613109565b509695505050505050565b5f60608284031215613231575f80fd5b6040516060810181811067ffffffffffffffff8211171561325457613254612e5f565b6040529050808235613265816130af565b8152602083013561327581612e01565b60208201526040830135613288816130af565b6040919091015292915050565b5f80604083850312156132a6575f80fd5b82356132b181612e01565b9150602083013567ffffffffffffffff808211156132cd575f80fd5b9084019061016082870312156132e1575f80fd5b6132e9612ebf565b8235828111156132f7575f80fd5b61330388828601613034565b825250602083013582811115613317575f80fd5b61332388828601613034565b60208301525061333560408401612e18565b604082015260608301358281111561334b575f80fd5b61335788828601613034565b606083015250613369608084016130a0565b608082015261337a60a084016130bd565b60a082015261338b60c084016130a0565b60c082015260e0830135828111156133a1575f80fd5b6133ad888286016130c8565b60e08301525061010091506133c487838501613221565b828201528093505050509250929050565b5f602082840312156133e5575f80fd5b813561243d81612e01565b5f805f60608486031215613402575f80fd5b833561340d81612e01565b925060208481013561341e816130af565b9250604085013567ffffffffffffffff8082111561343a575f80fd5b818701915087601f83011261344d575f80fd5b813561345b612f8d82612f14565b81815260059190911b8301840190848101908a831115613479575f80fd5b8585015b838110156134af57803585811115613493575f80fd5b6134a18d89838a0101613034565b84525091860191860161347d565b508096505050505050509250925092565b5f815180845260208085019450602084015f5b838110156134f257815160070b875295820195908201906001016134d3565b509495945050505050565b8381528260070b6020820152606060408201525f61351e60608301846134c0565b95945050505050565b5f8060408385031215613538575f80fd5b823561354381612e01565b9150602083013567ffffffffffffffff81111561355e575f80fd5b61356a85828601613034565b9150509250929050565b5f5b8381101561358e578181015183820152602001613576565b50505f910152565b5f81518084526135ad816020860160208601613574565b601f01601f19169290920160200192915050565b828152604060208201525f6135d96040830184613596565b949350505050565b5f805f606084860312156135f3575f80fd5b83356135fe81612e01565b9250602084013567ffffffffffffffff811115613619575f80fd5b61362586828701613034565b9250506040840135613636816130af565b809150509250925092565b5f805f60608486031215613653575f80fd5b833561365e81612e01565b9250602084013561366e81612e01565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b600181811c908216806136a757607f821691505b6020821081036136c557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82516136dc818460208701613574565b9190910192915050565b8051600381900b8114612e23575f80fd5b5f60208284031215613707575f80fd5b61243d826136e6565b8260070b8152604060208201525f6135d960408301846134c0565b6001600160a01b0383168152604060208201525f6135d96040830184613596565b8215158152604060208201525f6135d96040830184613596565b5f60208284031215613776575f80fd5b815161243d81612e01565b5f60208284031215613791575f80fd5b5051919050565b5f602082840312156137a8575f80fd5b815161243d816130af565b5f82825180855260208086019550808260051b8401018186015f5b8481101561386b57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261382d60e08a0186613596565b92860151898403603f1901858b01529294506138498584613596565b9501511660c097909701969096525050988401989250908301906001016137ce565b5090979650505050505050565b5f610160825181855261388d82860182613596565b915050602083015184820360208601526138a78282613596565b91505060408301516138c460408601826001600160a01b03169052565b50606083015184820360608601526138dc8282613596565b91505060808301516138f2608086018215159052565b5060a083015161390760a086018260070b9052565b5060c083015161391b60c086018215159052565b5060e083015184820360e086015261393382826137b3565b9150506101008084015161396f82870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b5f815180845260208085019450602084015f5b838110156134f2578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a0909601959082019060010161398c565b5f60608083526139f86060840187613878565b602084820381860152613a0b8288613979565b915060408583036040870152828751808552838501915083890194505f5b81811015613a8c5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c090920191600101613a29565b50909a9950505050505050505050565b5f8060408385031215613aad575f80fd5b613ab6836136e6565b91506020830151612e5481612e01565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b81811015613b13578551851683529483019491830191600101613af5565b509098975050505050505050565b6001600160a01b0383168152604060208201525f6135d96040830184613878565b606081525f613b546060830186613878565b90508360070b60208301528260030b6040830152949350505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b82811015613bde57607f19888703018452613bcc868351613596565b95509284019290840190600101613bb0565b50939998505050505050505050565b5f805f60608486031215613bff575f80fd5b613c08846136e6565b9250602080850151613c19816130af565b604086015190935067ffffffffffffffff811115613c35575f80fd5b8501601f81018713613c45575f80fd5b8051613c53612f8d82612f14565b81815260059190911b82018301908381019089831115613c71575f80fd5b928401925b82841015613c98578351613c89816130af565b82529284019290840190613c76565b80955050505050509250925092565b5f60a0808352613cba60a0840189613878565b602060078960070b8287015260408960030b604088015260608785036060890152613ce5858b613979565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015613d5d5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101613d03565b50909f9e505050505050505050505050505050565b602081525f61243d6020830184613878565b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220bde982ed61fd25cf9c5b9be5447911c6410d7ca4a16c083fdf466877d0a76f3d64736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol/TokenCreateCustomContract.json b/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol/TokenCreateCustomContract.json index 97d1f782b..56035bdeb 100644 --- a/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol/TokenCreateCustomContract.json +++ b/artifacts/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol/TokenCreateCustomContract.json @@ -937,8 +937,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b50600160208181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb499190915560027fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5560047fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5560087f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b5560107fedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643557fe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c5560065f5260407f8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a55612b4d806101235f395ff3fe6080604052600436106100e4575f3560e01c8063618dc65e11610087578063e36f755511610057578063e36f755514610252578063f4a01e5b14610265578063f848fec414610284578063fec394da146102a3575f80fd5b8063618dc65e146101b95780639b23d3d9146101e6578063c827bd3214610205578063de84a77914610233575f80fd5b806315dacbea116100c257806315dacbea1461016157806329fc46e614610180578063424f165e1461019357806355a0d9a3146101a6575f80fd5b80630fd2601e146100e8578063118741e71461011f57806311ba467f1461014c575b5f80fd5b3480156100f3575f80fd5b506101076101023660046116bf565b6102c2565b60405160079190910b81526020015b60405180910390f35b34801561012a575f80fd5b5061013e6101393660046117cd565b61031d565b604051908152602001610116565b61015f61015a366004611929565b61036f565b005b34801561016c575f80fd5b5061010761017b3660046119fd565b6105ce565b61015f61018e366004611ba4565b6106bd565b61015f6101a1366004611c9b565b610739565b61015f6101b4366004611f00565b61080b565b3480156101c4575f80fd5b506101d86101d336600461200d565b6108e1565b6040516101169291906120a7565b3480156101f1575f80fd5b506101076102003660046119fd565b6109f8565b348015610210575f80fd5b5061022461021f366004612142565b610a3c565b604051610116939291906121f0565b34801561023e575f80fd5b5061022461024d36600461221a565b610ad4565b61015f61026036600461234c565b610b6c565b348015610270575f80fd5b5061013e61027f3660046116bf565b610c7e565b34801561028f575f80fd5b5061013e61029e36600461247b565b610c89565b3480156102ae575f80fd5b506102246102bd366004612142565b610ce3565b5f6102cd8383610d05565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b601614610317575f80fd5b92915050565b5f6103288383610de3565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161035b91815260200190565b60405180910390a160168114610317575f80fd5b60408051600680825260e082019092525f91816020015b61038e61163f565b8152602001906001900390816103865790505090506103be5f60065f60405180602001604052805f815250610e0d565b815f815181106103d0576103d06124b9565b60200260200101819052506103f560015f60405180602001604052805f815250610e44565b81600181518110610408576104086124b9565b602002602001018190525061042d60025f60405180602001604052805f815250610e44565b81600281518110610440576104406124b9565b602002602001018190525061046560035f60405180602001604052805f815250610e44565b81600381518110610478576104786124b9565b602002602001018190525061049d60045f60405180602001604052805f815250610e44565b816004815181106104b0576104b06124b9565b60200260200101819052506104d560055f60405180602001604052805f815250610e44565b816005815181106104e8576104e86124b9565b60209081029190910181019190915260408051606080820183525f8083526001600160a01b038716838601819052627a1200848601528451610120810186528f81529586018e90529385019390935283018a905260016080840152600788900b60a084015285151560c084015260e083018490526101008301819052919080610572838b8a610e79565b909250905060168214610583575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161064c91906124cd565b5f604051808303815f865af19150503d805f8114610685576040519150601f19603f3d011682016040523d82523d5f602084013e61068a565b606091505b50915091508161069b5760156106af565b808060200190518101906106af91906124e8565b60030b979650505050505050565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260016080840152600788900b60a084015285151560c084015260e08301849052610100830182905290919080610572838b8a610e79565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528c81529081018b90529485015290830187905260016080840152600786900b60a084015260c0830181905260e083018490526101008301829052909190806107b283610f99565b9092509050601682146107c3575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050565b60408051606080820183525f8083526001600160a01b038c166020808501829052627a1200858701528551610120810187528d81529081018c90529485015290830188905260016080840152600787900b60a084015260c0830181905260e083018490526101008301829052909190806108868388886110a1565b909250905060168214610897575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b878760405160240161090d929190612503565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161094b91906124cd565b5f604051808303815f865af19150503d805f8114610984576040519150601f19603f3d011682016040523d82523d5f602084013e610989565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516109bf929190612524565b60405180910390a1816109e257601560405180602001604052805f8152506109e6565b6016815b60039190910b97909650945050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161060e565b5f806060610a4b878686610ad4565b809350819450829550505050610a7c873088845f81518110610a6f57610a6f6124b9565b602002602001015161110a565b50604080516001600160a01b03898116825288166020820152600787900b8183015290517f215c8eec9aa8fa57cdc8525400a046bf00ff93b20cc529980e01c1ef114fc2289181900360600190a19450945094915050565b5f806060610ae3868686611151565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610b2a575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610b5b92919061253e565b60405180910390a193509350939050565b60408051606080820183525f8083526001600160a01b038e166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260016080840152600788900b60a084015260c0830181905260e08301849052610100830182905290919080610be9838b8a8a8a611248565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c1e91815260200190565b60405180910390a160168214610c32575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a15050505050505050505050505050565b5f610328838361136e565b5f610c958484846113a3565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa81604051610cc891815260200190565b60405180910390a160168114610cdc575f80fd5b9392505050565b5f806060610cf2878686610ad4565b91945092509050610a7c87308888611477565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610d7491906124cd565b5f604051808303815f865af19150503d805f8114610dad576040519150601f19603f3d011682016040523d82523d5f602084013e610db2565b606091505b509150915081610dc3576015610dd7565b80806020019051810190610dd791906124e8565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401610d36929190612559565b610e1561163f565b6040518060400160405280610e2a87876114be565b8152602001610e3985856114f8565b905295945050505050565b610e4c61163f565b6040518060400160405280610e6086611603565b8152602001610e6f85856114f8565b9052949350505050565b5f80848061010001515f015160070b5f148015610ea057506101008101516040015160070b155b15610eb6576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a604051602401610ee29392919061276d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f2091906124cd565b5f6040518083038185875af1925050503d805f8114610f5a576040519150601f19603f3d011682016040523d82523d5f602084013e610f5f565b606091505b509150915081610f715760155f610f85565b80806020019051810190610f85919061279b565b60039190910b999098509650505050505050565b5f80828061010001515f015160070b5f148015610fc057506101008101516040015160070b155b15610fd6576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401610ffe91906127c8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161103c91906124cd565b5f6040518083038185875af1925050503d805f8114611076576040519150601f19603f3d011682016040523d82523d5f602084013e61107b565b606091505b50915091508161108d5760155f6109e6565b808060200190518101906109e6919061279b565b5f80848061010001515f015160070b5f1480156110c857506101008101516040015160070b155b156110de576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401610ee293929190612846565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a40161060e565b5f8060605f806101676001600160a01b031663e0f4059a60e01b898989604051602401611180939291906128fd565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111be91906124cd565b5f604051808303815f865af19150503d805f81146111f7576040519150601f19603f3d011682016040523d82523d5f602084013e6111fc565b606091505b50915091508161121e57604080515f8082526020820190925260159190611232565b80806020019051810190611232919061297a565b60039290920b9a90995090975095505050505050565b5f80868061010001515f015160070b5f14801561126f57506101008101516040015160070b155b15611285576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c6040516024016112b5959493929190612a38565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112f391906124cd565b5f6040518083038185875af1925050503d805f811461132d576040519150601f19603f3d011682016040523d82523d5f602084013e611332565b606091505b5091509150816113445760155f611358565b80806020019051810190611358919061279b565b60039190910b9b909a5098505050505050505050565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401610d36565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f91829182916101679161140791906124cd565b5f604051808303815f865af19150503d805f8114611440576040519150601f19603f3d011682016040523d82523d5f602084013e611445565b606091505b50915091508161145657601561146a565b8080602001905181019061146a91906124e8565b60030b9695505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a40161060e565b5f6114e18360068111156114d4576114d4612b03565b600160ff9091161b821790565b9050610cdc8260068111156114d4576114d4612b03565b61153b6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f83600481111561154e5761154e612b03565b0361155c5760018152610317565b600183600481111561157057611570612b03565b0361158a575f546001600160a01b03166020820152610317565b600283600481111561159e5761159e612b03565b036115af5760408101829052610317565b60038360048111156115c3576115c3612b03565b036115d45760608101829052610317565b60048360048111156115e8576115e8612b03565b03610317575f546001600160a01b0316608082015292915050565b5f60015f83600681111561161957611619612b03565b600681111561162a5761162a612b03565b81526020019081526020015f20549050919050565b60405180604001604052805f81526020016116936040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b03811681146116ac575f80fd5b50565b80356116ba81611698565b919050565b5f80604083850312156116d0575f80fd5b82356116db81611698565b915060208301356116eb81611698565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff8111828210171561172d5761172d6116f6565b60405290565b60405160a0810167ffffffffffffffff8111828210171561172d5761172d6116f6565b60405160c0810167ffffffffffffffff8111828210171561172d5761172d6116f6565b604051601f8201601f1916810167ffffffffffffffff811182821017156117a2576117a26116f6565b604052919050565b5f67ffffffffffffffff8211156117c3576117c36116f6565b5060051b60200190565b5f80604083850312156117de575f80fd5b82356117e981611698565b915060208381013567ffffffffffffffff811115611805575f80fd5b8401601f81018613611815575f80fd5b8035611828611823826117aa565b611779565b81815260059190911b82018301908381019088831115611846575f80fd5b928401925b8284101561186d57833561185e81611698565b8252928401929084019061184b565b80955050505050509250929050565b5f82601f83011261188b575f80fd5b813567ffffffffffffffff8111156118a5576118a56116f6565b6118b8601f8201601f1916602001611779565b8181528460208386010111156118cc575f80fd5b816020850160208301375f918101602001919091529392505050565b8060070b81146116ac575f80fd5b80356116ba816118e8565b8060030b81146116ac575f80fd5b80356116ba81611901565b803580151581146116ba575f80fd5b5f805f805f805f80610100898b031215611941575f80fd5b883567ffffffffffffffff80821115611958575f80fd5b6119648c838d0161187c565b995060208b0135915080821115611979575f80fd5b6119858c838d0161187c565b985060408b013591508082111561199a575f80fd5b506119a78b828c0161187c565b9650506119b660608a016118f6565b94506119c460808a016118f6565b93506119d260a08a0161190f565b92506119e060c08a0161191a565b91506119ee60e08a016116af565b90509295985092959890939650565b5f805f8060808587031215611a10575f80fd5b8435611a1b81611698565b93506020850135611a2b81611698565b92506040850135611a3b81611698565b9396929550929360600135925050565b5f82601f830112611a5a575f80fd5b81356020611a6a611823836117aa565b82815260059290921b84018101918181019086841115611a88575f80fd5b8286015b84811015611b9957803567ffffffffffffffff80821115611aab575f80fd5b908801906040601f19838c038101821315611ac4575f80fd5b611acc61170a565b8885013581528285013584811115611ae2575f80fd5b949094019360a0858e0383011215611af8575f80fd5b611b00611733565b9150611b0d89860161191a565b825282850135611b1c81611698565b828a015260608581013585811115611b32575f80fd5b611b408f8c838a010161187c565b8585015250608093508386013585811115611b59575f80fd5b611b678f8c838a010161187c565b82850152505060a08501359450611b7d85611698565b9181019390935280870192909252508352918301918301611a8c565b509695505050505050565b5f805f805f805f805f6101208a8c031215611bbd575f80fd5b893567ffffffffffffffff80821115611bd4575f80fd5b611be08d838e0161187c565b9a5060208c0135915080821115611bf5575f80fd5b611c018d838e0161187c565b995060408c0135915080821115611c16575f80fd5b611c228d838e0161187c565b9850611c3060608d016118f6565b9750611c3e60808d016118f6565b9650611c4c60a08d0161190f565b9550611c5a60c08d0161191a565b9450611c6860e08d016116af565b93506101008c0135915080821115611c7e575f80fd5b50611c8b8c828d01611a4b565b9150509295985092959850929598565b5f805f805f8060c08789031215611cb0575f80fd5b863567ffffffffffffffff80821115611cc7575f80fd5b611cd38a838b0161187c565b97506020890135915080821115611ce8575f80fd5b611cf48a838b0161187c565b96506040890135915080821115611d09575f80fd5b611d158a838b0161187c565b9550611d2360608a016118f6565b9450611d3160808a016116af565b935060a0890135915080821115611d46575f80fd5b50611d5389828a01611a4b565b9150509295509295509295565b5f82601f830112611d6f575f80fd5b81356020611d7f611823836117aa565b82815260a09283028501820192828201919087851115611d9d575f80fd5b8387015b85811015611e1f5781818a031215611db7575f80fd5b611dbf611733565b8135611dca816118e8565b815281860135611dd981611698565b818701526040611dea83820161191a565b908201526060611dfb83820161191a565b90820152608082810135611e0e81611698565b908201528452928401928101611da1565b5090979650505050505050565b5f82601f830112611e3b575f80fd5b81356020611e4b611823836117aa565b82815260c09283028501820192828201919087851115611e69575f80fd5b8387015b85811015611e1f5781818a031215611e83575f80fd5b611e8b611756565b8135611e96816118e8565b815281860135611ea5816118e8565b81870152604082810135611eb8816118e8565b90820152606082810135611ecb81611698565b908201526080611edc83820161191a565b9082015260a082810135611eef81611698565b908201528452928401928101611e6d565b5f805f805f805f80610100898b031215611f18575f80fd5b611f21896116af565b9750602089013567ffffffffffffffff80821115611f3d575f80fd5b611f498c838d0161187c565b985060408b0135915080821115611f5e575f80fd5b611f6a8c838d0161187c565b975060608b0135915080821115611f7f575f80fd5b611f8b8c838d0161187c565b9650611f9960808c016118f6565b955060a08b0135915080821115611fae575f80fd5b611fba8c838d01611d60565b945060c08b0135915080821115611fcf575f80fd5b611fdb8c838d01611e2c565b935060e08b0135915080821115611ff0575f80fd5b50611ffd8b828c01611a4b565b9150509295985092959890939650565b5f806040838503121561201e575f80fd5b823561202981611698565b9150602083013567ffffffffffffffff811115612044575f80fd5b6120508582860161187c565b9150509250929050565b5f5b8381101561207457818101518382015260200161205c565b50505f910152565b5f815180845261209381602086016020860161205a565b601f01601f19169290920160200192915050565b828152604060208201525f6120bf604083018461207c565b949350505050565b5f82601f8301126120d6575f80fd5b813560206120e6611823836117aa565b82815260059290921b84018101918181019086841115612104575f80fd5b8286015b84811015611b9957803567ffffffffffffffff811115612126575f80fd5b6121348986838b010161187c565b845250918301918301612108565b5f805f8060808587031215612155575f80fd5b843561216081611698565b9350602085013561217081611698565b92506040850135612180816118e8565b9150606085013567ffffffffffffffff81111561219b575f80fd5b6121a7878288016120c7565b91505092959194509250565b5f815180845260208085019450602084015f5b838110156121e557815160070b875295820195908201906001016121c6565b509495945050505050565b8381528260070b6020820152606060408201525f61221160608301846121b3565b95945050505050565b5f805f6060848603121561222c575f80fd5b833561223781611698565b92506020840135612247816118e8565b9150604084013567ffffffffffffffff811115612262575f80fd5b61226e868287016120c7565b9150509250925092565b5f82601f830112612287575f80fd5b81356020612297611823836117aa565b82815260c092830285018201928282019190878511156122b5575f80fd5b8387015b85811015611e1f5781818a0312156122cf575f80fd5b6122d7611756565b81356122e2816118e8565b8152818601356122f1816118e8565b81870152604082810135612304816118e8565b90820152606082810135612317816118e8565b90820152608061232883820161191a565b9082015260a08281013561233b81611698565b9082015284529284019281016122b9565b5f805f805f805f805f806101408b8d031215612366575f80fd5b61236f8b6116af565b995060208b013567ffffffffffffffff8082111561238b575f80fd5b6123978e838f0161187c565b9a5060408d01359150808211156123ac575f80fd5b6123b88e838f0161187c565b995060608d01359150808211156123cd575f80fd5b6123d98e838f0161187c565b98506123e760808e016118f6565b97506123f560a08e016118f6565b965061240360c08e0161190f565b955060e08d0135915080821115612418575f80fd5b6124248e838f01611d60565b94506101008d013591508082111561243a575f80fd5b6124468e838f01612278565b93506101208d013591508082111561245c575f80fd5b506124698d828e01611a4b565b9150509295989b9194979a5092959850565b5f805f6060848603121561248d575f80fd5b833561249881611698565b925060208401356124a881611698565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b5f82516124de81846020870161205a565b9190910192915050565b5f602082840312156124f8575f80fd5b8151610cdc81611901565b6001600160a01b0383168152604060208201525f6120bf604083018461207c565b8215158152604060208201525f6120bf604083018461207c565b8260070b8152604060208201525f6120bf60408301846121b3565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b818110156125a6578551851683529483019491830191600101612588565b509098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611e1f57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261262e60e08a018661207c565b92860151898403603f1901858b015292945061264a858461207c565b9501511660c097909701969096525050988401989250908301906001016125cf565b5f61016082518185526126818286018261207c565b9150506020830151848203602086015261269b828261207c565b91505060408301516126b860408601826001600160a01b03169052565b50606083015184820360608601526126d0828261207c565b91505060808301516126e6608086018215159052565b5060a08301516126fb60a086018260070b9052565b5060c083015161270f60c086018215159052565b5060e083015184820360e086015261272782826125b4565b9150506101008084015161276382870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b606081525f61277f606083018661266c565b90508360070b60208301528260030b6040830152949350505050565b5f80604083850312156127ac575f80fd5b82516127b781611901565b60208401519092506116eb81611698565b602081525f610cdc602083018461266c565b5f815180845260208085019450602084015f5b838110156121e5578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a090960195908201906001016127ed565b5f6060808352612859606084018761266c565b60208482038186015261286c82886127da565b915060408583036040870152828751808552838501915083890194505f5b818110156128ed5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c09092019160010161288a565b50909a9950505050505050505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b8281101561296b57607f1988870301845261295986835161207c565b9550928401929084019060010161293d565b50939998505050505050505050565b5f805f6060848603121561298c575f80fd5b835161299781611901565b809350506020808501516129aa816118e8565b604086015190935067ffffffffffffffff8111156129c6575f80fd5b8501601f810187136129d6575f80fd5b80516129e4611823826117aa565b81815260059190911b82018301908381019089831115612a02575f80fd5b928401925b82841015612a29578351612a1a816118e8565b82529284019290840190612a07565b80955050505050509250925092565b5f60a0808352612a4b60a084018961266c565b602060078960070b8287015260408960030b604088015260608785036060890152612a76858b6127da565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015612aee5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101612a94565b50909f9e505050505050505050505050505050565b634e487b7160e01b5f52602160045260245ffdfea264697066735822122041984361aa3ab1583bb0415f3a0b87a1ac062c72b3297b443024847ca025840764736f6c63430008180033", - "deployedBytecode": "0x6080604052600436106100e4575f3560e01c8063618dc65e11610087578063e36f755511610057578063e36f755514610252578063f4a01e5b14610265578063f848fec414610284578063fec394da146102a3575f80fd5b8063618dc65e146101b95780639b23d3d9146101e6578063c827bd3214610205578063de84a77914610233575f80fd5b806315dacbea116100c257806315dacbea1461016157806329fc46e614610180578063424f165e1461019357806355a0d9a3146101a6575f80fd5b80630fd2601e146100e8578063118741e71461011f57806311ba467f1461014c575b5f80fd5b3480156100f3575f80fd5b506101076101023660046116bf565b6102c2565b60405160079190910b81526020015b60405180910390f35b34801561012a575f80fd5b5061013e6101393660046117cd565b61031d565b604051908152602001610116565b61015f61015a366004611929565b61036f565b005b34801561016c575f80fd5b5061010761017b3660046119fd565b6105ce565b61015f61018e366004611ba4565b6106bd565b61015f6101a1366004611c9b565b610739565b61015f6101b4366004611f00565b61080b565b3480156101c4575f80fd5b506101d86101d336600461200d565b6108e1565b6040516101169291906120a7565b3480156101f1575f80fd5b506101076102003660046119fd565b6109f8565b348015610210575f80fd5b5061022461021f366004612142565b610a3c565b604051610116939291906121f0565b34801561023e575f80fd5b5061022461024d36600461221a565b610ad4565b61015f61026036600461234c565b610b6c565b348015610270575f80fd5b5061013e61027f3660046116bf565b610c7e565b34801561028f575f80fd5b5061013e61029e36600461247b565b610c89565b3480156102ae575f80fd5b506102246102bd366004612142565b610ce3565b5f6102cd8383610d05565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b601614610317575f80fd5b92915050565b5f6103288383610de3565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161035b91815260200190565b60405180910390a160168114610317575f80fd5b60408051600680825260e082019092525f91816020015b61038e61163f565b8152602001906001900390816103865790505090506103be5f60065f60405180602001604052805f815250610e0d565b815f815181106103d0576103d06124b9565b60200260200101819052506103f560015f60405180602001604052805f815250610e44565b81600181518110610408576104086124b9565b602002602001018190525061042d60025f60405180602001604052805f815250610e44565b81600281518110610440576104406124b9565b602002602001018190525061046560035f60405180602001604052805f815250610e44565b81600381518110610478576104786124b9565b602002602001018190525061049d60045f60405180602001604052805f815250610e44565b816004815181106104b0576104b06124b9565b60200260200101819052506104d560055f60405180602001604052805f815250610e44565b816005815181106104e8576104e86124b9565b60209081029190910181019190915260408051606080820183525f8083526001600160a01b038716838601819052627a1200848601528451610120810186528f81529586018e90529385019390935283018a905260016080840152600788900b60a084015285151560c084015260e083018490526101008301819052919080610572838b8a610e79565b909250905060168214610583575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161064c91906124cd565b5f604051808303815f865af19150503d805f8114610685576040519150601f19603f3d011682016040523d82523d5f602084013e61068a565b606091505b50915091508161069b5760156106af565b808060200190518101906106af91906124e8565b60030b979650505050505050565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260016080840152600788900b60a084015285151560c084015260e08301849052610100830182905290919080610572838b8a610e79565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528c81529081018b90529485015290830187905260016080840152600786900b60a084015260c0830181905260e083018490526101008301829052909190806107b283610f99565b9092509050601682146107c3575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050565b60408051606080820183525f8083526001600160a01b038c166020808501829052627a1200858701528551610120810187528d81529081018c90529485015290830188905260016080840152600787900b60a084015260c0830181905260e083018490526101008301829052909190806108868388886110a1565b909250905060168214610897575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b878760405160240161090d929190612503565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161094b91906124cd565b5f604051808303815f865af19150503d805f8114610984576040519150601f19603f3d011682016040523d82523d5f602084013e610989565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516109bf929190612524565b60405180910390a1816109e257601560405180602001604052805f8152506109e6565b6016815b60039190910b97909650945050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161060e565b5f806060610a4b878686610ad4565b809350819450829550505050610a7c873088845f81518110610a6f57610a6f6124b9565b602002602001015161110a565b50604080516001600160a01b03898116825288166020820152600787900b8183015290517f215c8eec9aa8fa57cdc8525400a046bf00ff93b20cc529980e01c1ef114fc2289181900360600190a19450945094915050565b5f806060610ae3868686611151565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610b2a575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610b5b92919061253e565b60405180910390a193509350939050565b60408051606080820183525f8083526001600160a01b038e166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260016080840152600788900b60a084015260c0830181905260e08301849052610100830182905290919080610be9838b8a8a8a611248565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c1e91815260200190565b60405180910390a160168214610c32575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a15050505050505050505050505050565b5f610328838361136e565b5f610c958484846113a3565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa81604051610cc891815260200190565b60405180910390a160168114610cdc575f80fd5b9392505050565b5f806060610cf2878686610ad4565b91945092509050610a7c87308888611477565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610d7491906124cd565b5f604051808303815f865af19150503d805f8114610dad576040519150601f19603f3d011682016040523d82523d5f602084013e610db2565b606091505b509150915081610dc3576015610dd7565b80806020019051810190610dd791906124e8565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401610d36929190612559565b610e1561163f565b6040518060400160405280610e2a87876114be565b8152602001610e3985856114f8565b905295945050505050565b610e4c61163f565b6040518060400160405280610e6086611603565b8152602001610e6f85856114f8565b9052949350505050565b5f80848061010001515f015160070b5f148015610ea057506101008101516040015160070b155b15610eb6576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a604051602401610ee29392919061276d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f2091906124cd565b5f6040518083038185875af1925050503d805f8114610f5a576040519150601f19603f3d011682016040523d82523d5f602084013e610f5f565b606091505b509150915081610f715760155f610f85565b80806020019051810190610f85919061279b565b60039190910b999098509650505050505050565b5f80828061010001515f015160070b5f148015610fc057506101008101516040015160070b155b15610fd6576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b88604051602401610ffe91906127c8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161103c91906124cd565b5f6040518083038185875af1925050503d805f8114611076576040519150601f19603f3d011682016040523d82523d5f602084013e61107b565b606091505b50915091508161108d5760155f6109e6565b808060200190518101906109e6919061279b565b5f80848061010001515f015160070b5f1480156110c857506101008101516040015160070b155b156110de576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401610ee293929190612846565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a40161060e565b5f8060605f806101676001600160a01b031663e0f4059a60e01b898989604051602401611180939291906128fd565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111be91906124cd565b5f604051808303815f865af19150503d805f81146111f7576040519150601f19603f3d011682016040523d82523d5f602084013e6111fc565b606091505b50915091508161121e57604080515f8082526020820190925260159190611232565b80806020019051810190611232919061297a565b60039290920b9a90995090975095505050505050565b5f80868061010001515f015160070b5f14801561126f57506101008101516040015160070b155b15611285576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c6040516024016112b5959493929190612a38565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112f391906124cd565b5f6040518083038185875af1925050503d805f811461132d576040519150601f19603f3d011682016040523d82523d5f602084013e611332565b606091505b5091509150816113445760155f611358565b80806020019051810190611358919061279b565b60039190910b9b909a5098505050505050505050565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401610d36565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f91829182916101679161140791906124cd565b5f604051808303815f865af19150503d805f8114611440576040519150601f19603f3d011682016040523d82523d5f602084013e611445565b606091505b50915091508161145657601561146a565b8080602001905181019061146a91906124e8565b60030b9695505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a40161060e565b5f6114e18360068111156114d4576114d4612b03565b600160ff9091161b821790565b9050610cdc8260068111156114d4576114d4612b03565b61153b6040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f83600481111561154e5761154e612b03565b0361155c5760018152610317565b600183600481111561157057611570612b03565b0361158a575f546001600160a01b03166020820152610317565b600283600481111561159e5761159e612b03565b036115af5760408101829052610317565b60038360048111156115c3576115c3612b03565b036115d45760608101829052610317565b60048360048111156115e8576115e8612b03565b03610317575f546001600160a01b0316608082015292915050565b5f60015f83600681111561161957611619612b03565b600681111561162a5761162a612b03565b81526020019081526020015f20549050919050565b60405180604001604052805f81526020016116936040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b03811681146116ac575f80fd5b50565b80356116ba81611698565b919050565b5f80604083850312156116d0575f80fd5b82356116db81611698565b915060208301356116eb81611698565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff8111828210171561172d5761172d6116f6565b60405290565b60405160a0810167ffffffffffffffff8111828210171561172d5761172d6116f6565b60405160c0810167ffffffffffffffff8111828210171561172d5761172d6116f6565b604051601f8201601f1916810167ffffffffffffffff811182821017156117a2576117a26116f6565b604052919050565b5f67ffffffffffffffff8211156117c3576117c36116f6565b5060051b60200190565b5f80604083850312156117de575f80fd5b82356117e981611698565b915060208381013567ffffffffffffffff811115611805575f80fd5b8401601f81018613611815575f80fd5b8035611828611823826117aa565b611779565b81815260059190911b82018301908381019088831115611846575f80fd5b928401925b8284101561186d57833561185e81611698565b8252928401929084019061184b565b80955050505050509250929050565b5f82601f83011261188b575f80fd5b813567ffffffffffffffff8111156118a5576118a56116f6565b6118b8601f8201601f1916602001611779565b8181528460208386010111156118cc575f80fd5b816020850160208301375f918101602001919091529392505050565b8060070b81146116ac575f80fd5b80356116ba816118e8565b8060030b81146116ac575f80fd5b80356116ba81611901565b803580151581146116ba575f80fd5b5f805f805f805f80610100898b031215611941575f80fd5b883567ffffffffffffffff80821115611958575f80fd5b6119648c838d0161187c565b995060208b0135915080821115611979575f80fd5b6119858c838d0161187c565b985060408b013591508082111561199a575f80fd5b506119a78b828c0161187c565b9650506119b660608a016118f6565b94506119c460808a016118f6565b93506119d260a08a0161190f565b92506119e060c08a0161191a565b91506119ee60e08a016116af565b90509295985092959890939650565b5f805f8060808587031215611a10575f80fd5b8435611a1b81611698565b93506020850135611a2b81611698565b92506040850135611a3b81611698565b9396929550929360600135925050565b5f82601f830112611a5a575f80fd5b81356020611a6a611823836117aa565b82815260059290921b84018101918181019086841115611a88575f80fd5b8286015b84811015611b9957803567ffffffffffffffff80821115611aab575f80fd5b908801906040601f19838c038101821315611ac4575f80fd5b611acc61170a565b8885013581528285013584811115611ae2575f80fd5b949094019360a0858e0383011215611af8575f80fd5b611b00611733565b9150611b0d89860161191a565b825282850135611b1c81611698565b828a015260608581013585811115611b32575f80fd5b611b408f8c838a010161187c565b8585015250608093508386013585811115611b59575f80fd5b611b678f8c838a010161187c565b82850152505060a08501359450611b7d85611698565b9181019390935280870192909252508352918301918301611a8c565b509695505050505050565b5f805f805f805f805f6101208a8c031215611bbd575f80fd5b893567ffffffffffffffff80821115611bd4575f80fd5b611be08d838e0161187c565b9a5060208c0135915080821115611bf5575f80fd5b611c018d838e0161187c565b995060408c0135915080821115611c16575f80fd5b611c228d838e0161187c565b9850611c3060608d016118f6565b9750611c3e60808d016118f6565b9650611c4c60a08d0161190f565b9550611c5a60c08d0161191a565b9450611c6860e08d016116af565b93506101008c0135915080821115611c7e575f80fd5b50611c8b8c828d01611a4b565b9150509295985092959850929598565b5f805f805f8060c08789031215611cb0575f80fd5b863567ffffffffffffffff80821115611cc7575f80fd5b611cd38a838b0161187c565b97506020890135915080821115611ce8575f80fd5b611cf48a838b0161187c565b96506040890135915080821115611d09575f80fd5b611d158a838b0161187c565b9550611d2360608a016118f6565b9450611d3160808a016116af565b935060a0890135915080821115611d46575f80fd5b50611d5389828a01611a4b565b9150509295509295509295565b5f82601f830112611d6f575f80fd5b81356020611d7f611823836117aa565b82815260a09283028501820192828201919087851115611d9d575f80fd5b8387015b85811015611e1f5781818a031215611db7575f80fd5b611dbf611733565b8135611dca816118e8565b815281860135611dd981611698565b818701526040611dea83820161191a565b908201526060611dfb83820161191a565b90820152608082810135611e0e81611698565b908201528452928401928101611da1565b5090979650505050505050565b5f82601f830112611e3b575f80fd5b81356020611e4b611823836117aa565b82815260c09283028501820192828201919087851115611e69575f80fd5b8387015b85811015611e1f5781818a031215611e83575f80fd5b611e8b611756565b8135611e96816118e8565b815281860135611ea5816118e8565b81870152604082810135611eb8816118e8565b90820152606082810135611ecb81611698565b908201526080611edc83820161191a565b9082015260a082810135611eef81611698565b908201528452928401928101611e6d565b5f805f805f805f80610100898b031215611f18575f80fd5b611f21896116af565b9750602089013567ffffffffffffffff80821115611f3d575f80fd5b611f498c838d0161187c565b985060408b0135915080821115611f5e575f80fd5b611f6a8c838d0161187c565b975060608b0135915080821115611f7f575f80fd5b611f8b8c838d0161187c565b9650611f9960808c016118f6565b955060a08b0135915080821115611fae575f80fd5b611fba8c838d01611d60565b945060c08b0135915080821115611fcf575f80fd5b611fdb8c838d01611e2c565b935060e08b0135915080821115611ff0575f80fd5b50611ffd8b828c01611a4b565b9150509295985092959890939650565b5f806040838503121561201e575f80fd5b823561202981611698565b9150602083013567ffffffffffffffff811115612044575f80fd5b6120508582860161187c565b9150509250929050565b5f5b8381101561207457818101518382015260200161205c565b50505f910152565b5f815180845261209381602086016020860161205a565b601f01601f19169290920160200192915050565b828152604060208201525f6120bf604083018461207c565b949350505050565b5f82601f8301126120d6575f80fd5b813560206120e6611823836117aa565b82815260059290921b84018101918181019086841115612104575f80fd5b8286015b84811015611b9957803567ffffffffffffffff811115612126575f80fd5b6121348986838b010161187c565b845250918301918301612108565b5f805f8060808587031215612155575f80fd5b843561216081611698565b9350602085013561217081611698565b92506040850135612180816118e8565b9150606085013567ffffffffffffffff81111561219b575f80fd5b6121a7878288016120c7565b91505092959194509250565b5f815180845260208085019450602084015f5b838110156121e557815160070b875295820195908201906001016121c6565b509495945050505050565b8381528260070b6020820152606060408201525f61221160608301846121b3565b95945050505050565b5f805f6060848603121561222c575f80fd5b833561223781611698565b92506020840135612247816118e8565b9150604084013567ffffffffffffffff811115612262575f80fd5b61226e868287016120c7565b9150509250925092565b5f82601f830112612287575f80fd5b81356020612297611823836117aa565b82815260c092830285018201928282019190878511156122b5575f80fd5b8387015b85811015611e1f5781818a0312156122cf575f80fd5b6122d7611756565b81356122e2816118e8565b8152818601356122f1816118e8565b81870152604082810135612304816118e8565b90820152606082810135612317816118e8565b90820152608061232883820161191a565b9082015260a08281013561233b81611698565b9082015284529284019281016122b9565b5f805f805f805f805f806101408b8d031215612366575f80fd5b61236f8b6116af565b995060208b013567ffffffffffffffff8082111561238b575f80fd5b6123978e838f0161187c565b9a5060408d01359150808211156123ac575f80fd5b6123b88e838f0161187c565b995060608d01359150808211156123cd575f80fd5b6123d98e838f0161187c565b98506123e760808e016118f6565b97506123f560a08e016118f6565b965061240360c08e0161190f565b955060e08d0135915080821115612418575f80fd5b6124248e838f01611d60565b94506101008d013591508082111561243a575f80fd5b6124468e838f01612278565b93506101208d013591508082111561245c575f80fd5b506124698d828e01611a4b565b9150509295989b9194979a5092959850565b5f805f6060848603121561248d575f80fd5b833561249881611698565b925060208401356124a881611698565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b5f82516124de81846020870161205a565b9190910192915050565b5f602082840312156124f8575f80fd5b8151610cdc81611901565b6001600160a01b0383168152604060208201525f6120bf604083018461207c565b8215158152604060208201525f6120bf604083018461207c565b8260070b8152604060208201525f6120bf60408301846121b3565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b818110156125a6578551851683529483019491830191600101612588565b509098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611e1f57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261262e60e08a018661207c565b92860151898403603f1901858b015292945061264a858461207c565b9501511660c097909701969096525050988401989250908301906001016125cf565b5f61016082518185526126818286018261207c565b9150506020830151848203602086015261269b828261207c565b91505060408301516126b860408601826001600160a01b03169052565b50606083015184820360608601526126d0828261207c565b91505060808301516126e6608086018215159052565b5060a08301516126fb60a086018260070b9052565b5060c083015161270f60c086018215159052565b5060e083015184820360e086015261272782826125b4565b9150506101008084015161276382870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b606081525f61277f606083018661266c565b90508360070b60208301528260030b6040830152949350505050565b5f80604083850312156127ac575f80fd5b82516127b781611901565b60208401519092506116eb81611698565b602081525f610cdc602083018461266c565b5f815180845260208085019450602084015f5b838110156121e5578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a090960195908201906001016127ed565b5f6060808352612859606084018761266c565b60208482038186015261286c82886127da565b915060408583036040870152828751808552838501915083890194505f5b818110156128ed5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c09092019160010161288a565b50909a9950505050505050505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b8281101561296b57607f1988870301845261295986835161207c565b9550928401929084019060010161293d565b50939998505050505050505050565b5f805f6060848603121561298c575f80fd5b835161299781611901565b809350506020808501516129aa816118e8565b604086015190935067ffffffffffffffff8111156129c6575f80fd5b8501601f810187136129d6575f80fd5b80516129e4611823826117aa565b81815260059190911b82018301908381019089831115612a02575f80fd5b928401925b82841015612a29578351612a1a816118e8565b82529284019290840190612a07565b80955050505050509250925092565b5f60a0808352612a4b60a084018961266c565b602060078960070b8287015260408960030b604088015260608785036060890152612a76858b6127da565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015612aee5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101612a94565b50909f9e505050505050505050505050505050565b634e487b7160e01b5f52602160045260245ffdfea264697066735822122041984361aa3ab1583bb0415f3a0b87a1ac062c72b3297b443024847ca025840764736f6c63430008180033", + "bytecode": "0x60806040526002805460ff1916600117905534801561001c575f80fd5b50600160208181527fa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb499190915560027fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5560047fd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f5560087f7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b5560107fedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643557fe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c5560065f5260407f8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a55612b6b806101305f395ff3fe6080604052600436106100e4575f3560e01c8063618dc65e11610087578063e36f755511610057578063e36f755514610252578063f4a01e5b14610265578063f848fec414610284578063fec394da146102a3575f80fd5b8063618dc65e146101b95780639b23d3d9146101e6578063c827bd3214610205578063de84a77914610233575f80fd5b806315dacbea116100c257806315dacbea1461016157806329fc46e614610180578063424f165e1461019357806355a0d9a3146101a6575f80fd5b80630fd2601e146100e8578063118741e71461011f57806311ba467f1461014c575b5f80fd5b3480156100f3575f80fd5b506101076101023660046116dd565b6102c2565b60405160079190910b81526020015b60405180910390f35b34801561012a575f80fd5b5061013e6101393660046117eb565b61031d565b604051908152602001610116565b61015f61015a366004611947565b61036f565b005b34801561016c575f80fd5b5061010761017b366004611a1b565b6105d4565b61015f61018e366004611bc2565b6106c3565b61015f6101a1366004611cb9565b610745565b61015f6101b4366004611f1e565b61081d565b3480156101c4575f80fd5b506101d86101d336600461202b565b6108f9565b6040516101169291906120c5565b3480156101f1575f80fd5b50610107610200366004611a1b565b610a10565b348015610210575f80fd5b5061022461021f366004612160565b610a54565b6040516101169392919061220e565b34801561023e575f80fd5b5061022461024d366004612238565b610aec565b61015f61026036600461236a565b610b84565b348015610270575f80fd5b5061013e61027f3660046116dd565b610c9c565b34801561028f575f80fd5b5061013e61029e366004612499565b610ca7565b3480156102ae575f80fd5b506102246102bd366004612160565b610d01565b5f6102cd8383610d23565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b601614610317575f80fd5b92915050565b5f6103288383610e01565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161035b91815260200190565b60405180910390a160168114610317575f80fd5b60408051600680825260e082019092525f91816020015b61038e61165d565b8152602001906001900390816103865790505090506103be5f60065f60405180602001604052805f815250610e2b565b815f815181106103d0576103d06124d7565b60200260200101819052506103f560015f60405180602001604052805f815250610e62565b81600181518110610408576104086124d7565b602002602001018190525061042d60025f60405180602001604052805f815250610e62565b81600281518110610440576104406124d7565b602002602001018190525061046560035f60405180602001604052805f815250610e62565b81600381518110610478576104786124d7565b602002602001018190525061049d60045f60405180602001604052805f815250610e62565b816004815181106104b0576104b06124d7565b60200260200101819052506104d560055f60405180602001604052805f815250610e62565b816005815181106104e8576104e86124d7565b60209081029190910181019190915260408051606080820183525f8083526001600160a01b038716838601819052627a1200848601528451610120810186528f81529586018e90529385019390935283018a905260025460ff1615156080840152600788900b60a084015285151560c084015260e083018490526101008301819052919080610578838b8a610e97565b909250905060168214610589575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161065291906124eb565b5f604051808303815f865af19150503d805f811461068b576040519150601f19603f3d011682016040523d82523d5f602084013e610690565b606091505b5091509150816106a15760156106b5565b808060200190518101906106b59190612506565b60030b979650505050505050565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260025460ff1615156080840152600788900b60a084015285151560c084015260e08301849052610100830182905290919080610578838b8a610e97565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528c81529081018b90529485015290830187905260025460ff1615156080840152600786900b60a084015260c0830181905260e083018490526101008301829052909190806107c483610fb7565b9092509050601682146107d5575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050565b60408051606080820183525f8083526001600160a01b038c166020808501829052627a1200858701528551610120810187528d81529081018c90529485015290830188905260025460ff1615156080840152600787900b60a084015260c0830181905260e0830184905261010083018290529091908061089e8388886110bf565b9092509050601682146108af575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610925929190612521565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161096391906124eb565b5f604051808303815f865af19150503d805f811461099c576040519150601f19603f3d011682016040523d82523d5f602084013e6109a1565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516109d7929190612542565b60405180910390a1816109fa57601560405180602001604052805f8152506109fe565b6016815b60039190910b97909650945050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610614565b5f806060610a63878686610aec565b809350819450829550505050610a94873088845f81518110610a8757610a876124d7565b6020026020010151611128565b50604080516001600160a01b03898116825288166020820152600787900b8183015290517f215c8eec9aa8fa57cdc8525400a046bf00ff93b20cc529980e01c1ef114fc2289181900360600190a19450945094915050565b5f806060610afb86868661116f565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610b42575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610b7392919061255c565b60405180910390a193509350939050565b60408051606080820183525f8083526001600160a01b038e166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260025460ff1615156080840152600788900b60a084015260c0830181905260e08301849052610100830182905290919080610c07838b8a8a8a611266565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c3c91815260200190565b60405180910390a160168214610c50575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a15050505050505050505050505050565b5f610328838361138c565b5f610cb38484846113c1565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa81604051610ce691815260200190565b60405180910390a160168114610cfa575f80fd5b9392505050565b5f806060610d10878686610aec565b91945092509050610a9487308888611495565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610d9291906124eb565b5f604051808303815f865af19150503d805f8114610dcb576040519150601f19603f3d011682016040523d82523d5f602084013e610dd0565b606091505b509150915081610de1576015610df5565b80806020019051810190610df59190612506565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401610d54929190612577565b610e3361165d565b6040518060400160405280610e4887876114dc565b8152602001610e578585611516565b905295945050505050565b610e6a61165d565b6040518060400160405280610e7e86611621565b8152602001610e8d8585611516565b9052949350505050565b5f80848061010001515f015160070b5f148015610ebe57506101008101516040015160070b155b15610ed4576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a604051602401610f009392919061278b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f3e91906124eb565b5f6040518083038185875af1925050503d805f8114610f78576040519150601f19603f3d011682016040523d82523d5f602084013e610f7d565b606091505b509150915081610f8f5760155f610fa3565b80806020019051810190610fa391906127b9565b60039190910b999098509650505050505050565b5f80828061010001515f015160070b5f148015610fde57506101008101516040015160070b155b15610ff4576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b8860405160240161101c91906127e6565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161105a91906124eb565b5f6040518083038185875af1925050503d805f8114611094576040519150601f19603f3d011682016040523d82523d5f602084013e611099565b606091505b5091509150816110ab5760155f6109fe565b808060200190518101906109fe91906127b9565b5f80848061010001515f015160070b5f1480156110e657506101008101516040015160070b155b156110fc576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401610f0093929190612864565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610614565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161119e9392919061291b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111dc91906124eb565b5f604051808303815f865af19150503d805f8114611215576040519150601f19603f3d011682016040523d82523d5f602084013e61121a565b606091505b50915091508161123c57604080515f8082526020820190925260159190611250565b808060200190518101906112509190612998565b60039290920b9a90995090975095505050505050565b5f80868061010001515f015160070b5f14801561128d57506101008101516040015160070b155b156112a3576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c6040516024016112d3959493929190612a56565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161131191906124eb565b5f6040518083038185875af1925050503d805f811461134b576040519150601f19603f3d011682016040523d82523d5f602084013e611350565b606091505b5091509150816113625760155f611376565b8080602001905181019061137691906127b9565b60039190910b9b909a5098505050505050505050565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401610d54565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f91829182916101679161142591906124eb565b5f604051808303815f865af19150503d805f811461145e576040519150601f19603f3d011682016040523d82523d5f602084013e611463565b606091505b509150915081611474576015611488565b808060200190518101906114889190612506565b60030b9695505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610614565b5f6114ff8360068111156114f2576114f2612b21565b600160ff9091161b821790565b9050610cfa8260068111156114f2576114f2612b21565b6115596040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f83600481111561156c5761156c612b21565b0361157a5760018152610317565b600183600481111561158e5761158e612b21565b036115a8575f546001600160a01b03166020820152610317565b60028360048111156115bc576115bc612b21565b036115cd5760408101829052610317565b60038360048111156115e1576115e1612b21565b036115f25760608101829052610317565b600483600481111561160657611606612b21565b03610317575f546001600160a01b0316608082015292915050565b5f60015f83600681111561163757611637612b21565b600681111561164857611648612b21565b81526020019081526020015f20549050919050565b60405180604001604052805f81526020016116b16040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b03811681146116ca575f80fd5b50565b80356116d8816116b6565b919050565b5f80604083850312156116ee575f80fd5b82356116f9816116b6565b91506020830135611709816116b6565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff8111828210171561174b5761174b611714565b60405290565b60405160a0810167ffffffffffffffff8111828210171561174b5761174b611714565b60405160c0810167ffffffffffffffff8111828210171561174b5761174b611714565b604051601f8201601f1916810167ffffffffffffffff811182821017156117c0576117c0611714565b604052919050565b5f67ffffffffffffffff8211156117e1576117e1611714565b5060051b60200190565b5f80604083850312156117fc575f80fd5b8235611807816116b6565b915060208381013567ffffffffffffffff811115611823575f80fd5b8401601f81018613611833575f80fd5b8035611846611841826117c8565b611797565b81815260059190911b82018301908381019088831115611864575f80fd5b928401925b8284101561188b57833561187c816116b6565b82529284019290840190611869565b80955050505050509250929050565b5f82601f8301126118a9575f80fd5b813567ffffffffffffffff8111156118c3576118c3611714565b6118d6601f8201601f1916602001611797565b8181528460208386010111156118ea575f80fd5b816020850160208301375f918101602001919091529392505050565b8060070b81146116ca575f80fd5b80356116d881611906565b8060030b81146116ca575f80fd5b80356116d88161191f565b803580151581146116d8575f80fd5b5f805f805f805f80610100898b03121561195f575f80fd5b883567ffffffffffffffff80821115611976575f80fd5b6119828c838d0161189a565b995060208b0135915080821115611997575f80fd5b6119a38c838d0161189a565b985060408b01359150808211156119b8575f80fd5b506119c58b828c0161189a565b9650506119d460608a01611914565b94506119e260808a01611914565b93506119f060a08a0161192d565b92506119fe60c08a01611938565b9150611a0c60e08a016116cd565b90509295985092959890939650565b5f805f8060808587031215611a2e575f80fd5b8435611a39816116b6565b93506020850135611a49816116b6565b92506040850135611a59816116b6565b9396929550929360600135925050565b5f82601f830112611a78575f80fd5b81356020611a88611841836117c8565b82815260059290921b84018101918181019086841115611aa6575f80fd5b8286015b84811015611bb757803567ffffffffffffffff80821115611ac9575f80fd5b908801906040601f19838c038101821315611ae2575f80fd5b611aea611728565b8885013581528285013584811115611b00575f80fd5b949094019360a0858e0383011215611b16575f80fd5b611b1e611751565b9150611b2b898601611938565b825282850135611b3a816116b6565b828a015260608581013585811115611b50575f80fd5b611b5e8f8c838a010161189a565b8585015250608093508386013585811115611b77575f80fd5b611b858f8c838a010161189a565b82850152505060a08501359450611b9b856116b6565b9181019390935280870192909252508352918301918301611aaa565b509695505050505050565b5f805f805f805f805f6101208a8c031215611bdb575f80fd5b893567ffffffffffffffff80821115611bf2575f80fd5b611bfe8d838e0161189a565b9a5060208c0135915080821115611c13575f80fd5b611c1f8d838e0161189a565b995060408c0135915080821115611c34575f80fd5b611c408d838e0161189a565b9850611c4e60608d01611914565b9750611c5c60808d01611914565b9650611c6a60a08d0161192d565b9550611c7860c08d01611938565b9450611c8660e08d016116cd565b93506101008c0135915080821115611c9c575f80fd5b50611ca98c828d01611a69565b9150509295985092959850929598565b5f805f805f8060c08789031215611cce575f80fd5b863567ffffffffffffffff80821115611ce5575f80fd5b611cf18a838b0161189a565b97506020890135915080821115611d06575f80fd5b611d128a838b0161189a565b96506040890135915080821115611d27575f80fd5b611d338a838b0161189a565b9550611d4160608a01611914565b9450611d4f60808a016116cd565b935060a0890135915080821115611d64575f80fd5b50611d7189828a01611a69565b9150509295509295509295565b5f82601f830112611d8d575f80fd5b81356020611d9d611841836117c8565b82815260a09283028501820192828201919087851115611dbb575f80fd5b8387015b85811015611e3d5781818a031215611dd5575f80fd5b611ddd611751565b8135611de881611906565b815281860135611df7816116b6565b818701526040611e08838201611938565b908201526060611e19838201611938565b90820152608082810135611e2c816116b6565b908201528452928401928101611dbf565b5090979650505050505050565b5f82601f830112611e59575f80fd5b81356020611e69611841836117c8565b82815260c09283028501820192828201919087851115611e87575f80fd5b8387015b85811015611e3d5781818a031215611ea1575f80fd5b611ea9611774565b8135611eb481611906565b815281860135611ec381611906565b81870152604082810135611ed681611906565b90820152606082810135611ee9816116b6565b908201526080611efa838201611938565b9082015260a082810135611f0d816116b6565b908201528452928401928101611e8b565b5f805f805f805f80610100898b031215611f36575f80fd5b611f3f896116cd565b9750602089013567ffffffffffffffff80821115611f5b575f80fd5b611f678c838d0161189a565b985060408b0135915080821115611f7c575f80fd5b611f888c838d0161189a565b975060608b0135915080821115611f9d575f80fd5b611fa98c838d0161189a565b9650611fb760808c01611914565b955060a08b0135915080821115611fcc575f80fd5b611fd88c838d01611d7e565b945060c08b0135915080821115611fed575f80fd5b611ff98c838d01611e4a565b935060e08b013591508082111561200e575f80fd5b5061201b8b828c01611a69565b9150509295985092959890939650565b5f806040838503121561203c575f80fd5b8235612047816116b6565b9150602083013567ffffffffffffffff811115612062575f80fd5b61206e8582860161189a565b9150509250929050565b5f5b8381101561209257818101518382015260200161207a565b50505f910152565b5f81518084526120b1816020860160208601612078565b601f01601f19169290920160200192915050565b828152604060208201525f6120dd604083018461209a565b949350505050565b5f82601f8301126120f4575f80fd5b81356020612104611841836117c8565b82815260059290921b84018101918181019086841115612122575f80fd5b8286015b84811015611bb757803567ffffffffffffffff811115612144575f80fd5b6121528986838b010161189a565b845250918301918301612126565b5f805f8060808587031215612173575f80fd5b843561217e816116b6565b9350602085013561218e816116b6565b9250604085013561219e81611906565b9150606085013567ffffffffffffffff8111156121b9575f80fd5b6121c5878288016120e5565b91505092959194509250565b5f815180845260208085019450602084015f5b8381101561220357815160070b875295820195908201906001016121e4565b509495945050505050565b8381528260070b6020820152606060408201525f61222f60608301846121d1565b95945050505050565b5f805f6060848603121561224a575f80fd5b8335612255816116b6565b9250602084013561226581611906565b9150604084013567ffffffffffffffff811115612280575f80fd5b61228c868287016120e5565b9150509250925092565b5f82601f8301126122a5575f80fd5b813560206122b5611841836117c8565b82815260c092830285018201928282019190878511156122d3575f80fd5b8387015b85811015611e3d5781818a0312156122ed575f80fd5b6122f5611774565b813561230081611906565b81528186013561230f81611906565b8187015260408281013561232281611906565b9082015260608281013561233581611906565b908201526080612346838201611938565b9082015260a082810135612359816116b6565b9082015284529284019281016122d7565b5f805f805f805f805f806101408b8d031215612384575f80fd5b61238d8b6116cd565b995060208b013567ffffffffffffffff808211156123a9575f80fd5b6123b58e838f0161189a565b9a5060408d01359150808211156123ca575f80fd5b6123d68e838f0161189a565b995060608d01359150808211156123eb575f80fd5b6123f78e838f0161189a565b985061240560808e01611914565b975061241360a08e01611914565b965061242160c08e0161192d565b955060e08d0135915080821115612436575f80fd5b6124428e838f01611d7e565b94506101008d0135915080821115612458575f80fd5b6124648e838f01612296565b93506101208d013591508082111561247a575f80fd5b506124878d828e01611a69565b9150509295989b9194979a5092959850565b5f805f606084860312156124ab575f80fd5b83356124b6816116b6565b925060208401356124c6816116b6565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b5f82516124fc818460208701612078565b9190910192915050565b5f60208284031215612516575f80fd5b8151610cfa8161191f565b6001600160a01b0383168152604060208201525f6120dd604083018461209a565b8215158152604060208201525f6120dd604083018461209a565b8260070b8152604060208201525f6120dd60408301846121d1565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b818110156125c45785518516835294830194918301916001016125a6565b509098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611e3d57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261264c60e08a018661209a565b92860151898403603f1901858b0152929450612668858461209a565b9501511660c097909701969096525050988401989250908301906001016125ed565b5f610160825181855261269f8286018261209a565b915050602083015184820360208601526126b9828261209a565b91505060408301516126d660408601826001600160a01b03169052565b50606083015184820360608601526126ee828261209a565b9150506080830151612704608086018215159052565b5060a083015161271960a086018260070b9052565b5060c083015161272d60c086018215159052565b5060e083015184820360e086015261274582826125d2565b9150506101008084015161278182870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b606081525f61279d606083018661268a565b90508360070b60208301528260030b6040830152949350505050565b5f80604083850312156127ca575f80fd5b82516127d58161191f565b6020840151909250611709816116b6565b602081525f610cfa602083018461268a565b5f815180845260208085019450602084015f5b83811015612203578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a0909601959082019060010161280b565b5f6060808352612877606084018761268a565b60208482038186015261288a82886127f8565b915060408583036040870152828751808552838501915083890194505f5b8181101561290b5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c0909201916001016128a8565b50909a9950505050505050505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b8281101561298957607f1988870301845261297786835161209a565b9550928401929084019060010161295b565b50939998505050505050505050565b5f805f606084860312156129aa575f80fd5b83516129b58161191f565b809350506020808501516129c881611906565b604086015190935067ffffffffffffffff8111156129e4575f80fd5b8501601f810187136129f4575f80fd5b8051612a02611841826117c8565b81815260059190911b82018301908381019089831115612a20575f80fd5b928401925b82841015612a47578351612a3881611906565b82529284019290840190612a25565b80955050505050509250925092565b5f60a0808352612a6960a084018961268a565b602060078960070b8287015260408960030b604088015260608785036060890152612a94858b6127f8565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015612b0c5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101612ab2565b50909f9e505050505050505050505050505050565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212200e1ef617cb2df316ead8f1287166e15db10bb2e54b25f229ad19cd7ce115c4e564736f6c63430008180033", + "deployedBytecode": "0x6080604052600436106100e4575f3560e01c8063618dc65e11610087578063e36f755511610057578063e36f755514610252578063f4a01e5b14610265578063f848fec414610284578063fec394da146102a3575f80fd5b8063618dc65e146101b95780639b23d3d9146101e6578063c827bd3214610205578063de84a77914610233575f80fd5b806315dacbea116100c257806315dacbea1461016157806329fc46e614610180578063424f165e1461019357806355a0d9a3146101a6575f80fd5b80630fd2601e146100e8578063118741e71461011f57806311ba467f1461014c575b5f80fd5b3480156100f3575f80fd5b506101076101023660046116dd565b6102c2565b60405160079190910b81526020015b60405180910390f35b34801561012a575f80fd5b5061013e6101393660046117eb565b61031d565b604051908152602001610116565b61015f61015a366004611947565b61036f565b005b34801561016c575f80fd5b5061010761017b366004611a1b565b6105d4565b61015f61018e366004611bc2565b6106c3565b61015f6101a1366004611cb9565b610745565b61015f6101b4366004611f1e565b61081d565b3480156101c4575f80fd5b506101d86101d336600461202b565b6108f9565b6040516101169291906120c5565b3480156101f1575f80fd5b50610107610200366004611a1b565b610a10565b348015610210575f80fd5b5061022461021f366004612160565b610a54565b6040516101169392919061220e565b34801561023e575f80fd5b5061022461024d366004612238565b610aec565b61015f61026036600461236a565b610b84565b348015610270575f80fd5b5061013e61027f3660046116dd565b610c9c565b34801561028f575f80fd5b5061013e61029e366004612499565b610ca7565b3480156102ae575f80fd5b506102246102bd366004612160565b610d01565b5f6102cd8383610d23565b604051600782900b81529091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a1600781900b601614610317575f80fd5b92915050565b5f6103288383610e01565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa8160405161035b91815260200190565b60405180910390a160168114610317575f80fd5b60408051600680825260e082019092525f91816020015b61038e61165d565b8152602001906001900390816103865790505090506103be5f60065f60405180602001604052805f815250610e2b565b815f815181106103d0576103d06124d7565b60200260200101819052506103f560015f60405180602001604052805f815250610e62565b81600181518110610408576104086124d7565b602002602001018190525061042d60025f60405180602001604052805f815250610e62565b81600281518110610440576104406124d7565b602002602001018190525061046560035f60405180602001604052805f815250610e62565b81600381518110610478576104786124d7565b602002602001018190525061049d60045f60405180602001604052805f815250610e62565b816004815181106104b0576104b06124d7565b60200260200101819052506104d560055f60405180602001604052805f815250610e62565b816005815181106104e8576104e86124d7565b60209081029190910181019190915260408051606080820183525f8083526001600160a01b038716838601819052627a1200848601528451610120810186528f81529586018e90529385019390935283018a905260025460ff1615156080840152600788900b60a084015285151560c084015260e083018490526101008301819052919080610578838b8a610e97565b909250905060168214610589575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161065291906124eb565b5f604051808303815f865af19150503d805f811461068b576040519150601f19603f3d011682016040523d82523d5f602084013e610690565b606091505b5091509150816106a15760156106b5565b808060200190518101906106b59190612506565b60030b979650505050505050565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260025460ff1615156080840152600788900b60a084015285151560c084015260e08301849052610100830182905290919080610578838b8a610e97565b60408051606080820183525f8083526001600160a01b0386166020808501829052627a1200858701528551610120810187528c81529081018b90529485015290830187905260025460ff1615156080840152600786900b60a084015260c0830181905260e083018490526101008301829052909190806107c483610fb7565b9092509050601682146107d5575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a150505050505050505050565b60408051606080820183525f8083526001600160a01b038c166020808501829052627a1200858701528551610120810187528d81529081018c90529485015290830188905260025460ff1615156080840152600787900b60a084015260c0830181905260e0830184905261010083018290529091908061089e8388886110bf565b9092509050601682146108af575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a1505050505050505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b8787604051602401610925929190612521565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161096391906124eb565b5f604051808303815f865af19150503d805f811461099c576040519150601f19603f3d011682016040523d82523d5f602084013e6109a1565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc82826040516109d7929190612542565b60405180910390a1816109fa57601560405180602001604052805f8152506109fe565b6016815b60039190910b97909650945050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a401610614565b5f806060610a63878686610aec565b809350819450829550505050610a94873088845f81518110610a8757610a876124d7565b6020026020010151611128565b50604080516001600160a01b03898116825288166020820152600787900b8183015290517f215c8eec9aa8fa57cdc8525400a046bf00ff93b20cc529980e01c1ef114fc2289181900360600190a19450945094915050565b5f806060610afb86868661116f565b60405183815292955090935091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa9060200160405180910390a160168314610b42575f80fd5b7ffc6b20023c4bac8ff1c48c1693e0cea5cd3c2163e9c2da41c58f17dd6d9f163d8282604051610b7392919061255c565b60405180910390a193509350939050565b60408051606080820183525f8083526001600160a01b038e166020808501829052627a1200858701528551610120810187528f81529081018e9052948501529083018a905260025460ff1615156080840152600788900b60a084015260c0830181905260e08301849052610100830182905290919080610c07838b8a8a8a611266565b915091507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa82604051610c3c91815260200190565b60405180910390a160168214610c50575f80fd5b6040516001600160a01b03821681527f7bb17726df1f3adee8aa00ba8e8bc5d6f182af3bbf77604639cb7f008dd3b4ed9060200160405180910390a15050505050505050505050505050565b5f610328838361138c565b5f610cb38484846113c1565b90507f90a5cf4cffe88b4edbb041cfc7a8a812c48a5ec30b84640fb37690875168e3aa81604051610ce691815260200190565b60405180910390a160168114610cfa575f80fd5b9392505050565b5f806060610d10878686610aec565b91945092509050610a9487308888611495565b6040516001600160a01b038381166024830152821660448201525f908190819061016790638f8d7f9960e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610d9291906124eb565b5f604051808303815f865af19150503d805f8114610dcb576040519150601f19603f3d011682016040523d82523d5f602084013e610dd0565b606091505b509150915081610de1576015610df5565b80806020019051810190610df59190612506565b60030b95945050505050565b5f805f6101676001600160a01b0316632e63879b60e01b8686604051602401610d54929190612577565b610e3361165d565b6040518060400160405280610e4887876114dc565b8152602001610e578585611516565b905295945050505050565b610e6a61165d565b6040518060400160405280610e7e86611621565b8152602001610e8d8585611516565b9052949350505050565b5f80848061010001515f015160070b5f148015610ebe57506101008101516040015160070b155b15610ed4576101008101516276a7006040909101525b5f806101676001600160a01b031634630fb65bf360e01b8a8a8a604051602401610f009392919061278b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f3e91906124eb565b5f6040518083038185875af1925050503d805f8114610f78576040519150601f19603f3d011682016040523d82523d5f602084013e610f7d565b606091505b509150915081610f8f5760155f610fa3565b80806020019051810190610fa391906127b9565b60039190910b999098509650505050505050565b5f80828061010001515f015160070b5f148015610fde57506101008101516040015160070b155b15610ff4576101008101516276a7006040909101525b5f806101676001600160a01b03163463ea83f29360e01b8860405160240161101c91906127e6565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161105a91906124eb565b5f6040518083038185875af1925050503d805f8114611094576040519150601f19603f3d011682016040523d82523d5f602084013e611099565b606091505b5091509150816110ab5760155f6109fe565b808060200190518101906109fe91906127b9565b5f80848061010001515f015160070b5f1480156110e657506101008101516040015160070b155b156110fc576101008101516276a7006040909101525b5f806101676001600160a01b03163463abb54eb560e01b8a8a8a604051602401610f0093929190612864565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f908190819061016790635cfc901160e01b9060a401610614565b5f8060605f806101676001600160a01b031663e0f4059a60e01b89898960405160240161119e9392919061291b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516111dc91906124eb565b5f604051808303815f865af19150503d805f8114611215576040519150601f19603f3d011682016040523d82523d5f602084013e61121a565b606091505b50915091508161123c57604080515f8082526020820190925260159190611250565b808060200190518101906112509190612998565b60039290920b9a90995090975095505050505050565b5f80868061010001515f015160070b5f14801561128d57506101008101516040015160070b155b156112a3576101008101516276a7006040909101525b5f806101676001600160a01b031634632af0c59a60e01b8c8c8c8c8c6040516024016112d3959493929190612a56565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161131191906124eb565b5f6040518083038185875af1925050503d805f811461134b576040519150601f19603f3d011682016040523d82523d5f602084013e611350565b606091505b5091509150816113625760155f611376565b8080602001905181019061137691906127b9565b60039190910b9b909a5098505050505050505050565b6040516001600160a01b038381166024830152821660448201525f90819081906101679063248a35ef60e11b90606401610d54565b604080516001600160a01b03858116602483015284166044820152606480820184905282518083039091018152608490910182526020810180516001600160e01b031663e1f21c6760e01b17905290515f91829182916101679161142591906124eb565b5f604051808303815f865af19150503d805f811461145e576040519150601f19603f3d011682016040523d82523d5f602084013e611463565b606091505b509150915081611474576015611488565b808060200190518101906114889190612506565b60030b9695505050505050565b6040516001600160a01b038581166024830152848116604483015283166064820152600782900b60848201525f90819081906101679063eca3691760e01b9060a401610614565b5f6114ff8360068111156114f2576114f2612b21565b600160ff9091161b821790565b9050610cfa8260068111156114f2576114f2612b21565b6115596040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b5f83600481111561156c5761156c612b21565b0361157a5760018152610317565b600183600481111561158e5761158e612b21565b036115a8575f546001600160a01b03166020820152610317565b60028360048111156115bc576115bc612b21565b036115cd5760408101829052610317565b60038360048111156115e1576115e1612b21565b036115f25760608101829052610317565b600483600481111561160657611606612b21565b03610317575f546001600160a01b0316608082015292915050565b5f60015f83600681111561163757611637612b21565b600681111561164857611648612b21565b81526020019081526020015f20549050919050565b60405180604001604052805f81526020016116b16040518060a001604052805f151581526020015f6001600160a01b0316815260200160608152602001606081526020015f6001600160a01b031681525090565b905290565b6001600160a01b03811681146116ca575f80fd5b50565b80356116d8816116b6565b919050565b5f80604083850312156116ee575f80fd5b82356116f9816116b6565b91506020830135611709816116b6565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff8111828210171561174b5761174b611714565b60405290565b60405160a0810167ffffffffffffffff8111828210171561174b5761174b611714565b60405160c0810167ffffffffffffffff8111828210171561174b5761174b611714565b604051601f8201601f1916810167ffffffffffffffff811182821017156117c0576117c0611714565b604052919050565b5f67ffffffffffffffff8211156117e1576117e1611714565b5060051b60200190565b5f80604083850312156117fc575f80fd5b8235611807816116b6565b915060208381013567ffffffffffffffff811115611823575f80fd5b8401601f81018613611833575f80fd5b8035611846611841826117c8565b611797565b81815260059190911b82018301908381019088831115611864575f80fd5b928401925b8284101561188b57833561187c816116b6565b82529284019290840190611869565b80955050505050509250929050565b5f82601f8301126118a9575f80fd5b813567ffffffffffffffff8111156118c3576118c3611714565b6118d6601f8201601f1916602001611797565b8181528460208386010111156118ea575f80fd5b816020850160208301375f918101602001919091529392505050565b8060070b81146116ca575f80fd5b80356116d881611906565b8060030b81146116ca575f80fd5b80356116d88161191f565b803580151581146116d8575f80fd5b5f805f805f805f80610100898b03121561195f575f80fd5b883567ffffffffffffffff80821115611976575f80fd5b6119828c838d0161189a565b995060208b0135915080821115611997575f80fd5b6119a38c838d0161189a565b985060408b01359150808211156119b8575f80fd5b506119c58b828c0161189a565b9650506119d460608a01611914565b94506119e260808a01611914565b93506119f060a08a0161192d565b92506119fe60c08a01611938565b9150611a0c60e08a016116cd565b90509295985092959890939650565b5f805f8060808587031215611a2e575f80fd5b8435611a39816116b6565b93506020850135611a49816116b6565b92506040850135611a59816116b6565b9396929550929360600135925050565b5f82601f830112611a78575f80fd5b81356020611a88611841836117c8565b82815260059290921b84018101918181019086841115611aa6575f80fd5b8286015b84811015611bb757803567ffffffffffffffff80821115611ac9575f80fd5b908801906040601f19838c038101821315611ae2575f80fd5b611aea611728565b8885013581528285013584811115611b00575f80fd5b949094019360a0858e0383011215611b16575f80fd5b611b1e611751565b9150611b2b898601611938565b825282850135611b3a816116b6565b828a015260608581013585811115611b50575f80fd5b611b5e8f8c838a010161189a565b8585015250608093508386013585811115611b77575f80fd5b611b858f8c838a010161189a565b82850152505060a08501359450611b9b856116b6565b9181019390935280870192909252508352918301918301611aaa565b509695505050505050565b5f805f805f805f805f6101208a8c031215611bdb575f80fd5b893567ffffffffffffffff80821115611bf2575f80fd5b611bfe8d838e0161189a565b9a5060208c0135915080821115611c13575f80fd5b611c1f8d838e0161189a565b995060408c0135915080821115611c34575f80fd5b611c408d838e0161189a565b9850611c4e60608d01611914565b9750611c5c60808d01611914565b9650611c6a60a08d0161192d565b9550611c7860c08d01611938565b9450611c8660e08d016116cd565b93506101008c0135915080821115611c9c575f80fd5b50611ca98c828d01611a69565b9150509295985092959850929598565b5f805f805f8060c08789031215611cce575f80fd5b863567ffffffffffffffff80821115611ce5575f80fd5b611cf18a838b0161189a565b97506020890135915080821115611d06575f80fd5b611d128a838b0161189a565b96506040890135915080821115611d27575f80fd5b611d338a838b0161189a565b9550611d4160608a01611914565b9450611d4f60808a016116cd565b935060a0890135915080821115611d64575f80fd5b50611d7189828a01611a69565b9150509295509295509295565b5f82601f830112611d8d575f80fd5b81356020611d9d611841836117c8565b82815260a09283028501820192828201919087851115611dbb575f80fd5b8387015b85811015611e3d5781818a031215611dd5575f80fd5b611ddd611751565b8135611de881611906565b815281860135611df7816116b6565b818701526040611e08838201611938565b908201526060611e19838201611938565b90820152608082810135611e2c816116b6565b908201528452928401928101611dbf565b5090979650505050505050565b5f82601f830112611e59575f80fd5b81356020611e69611841836117c8565b82815260c09283028501820192828201919087851115611e87575f80fd5b8387015b85811015611e3d5781818a031215611ea1575f80fd5b611ea9611774565b8135611eb481611906565b815281860135611ec381611906565b81870152604082810135611ed681611906565b90820152606082810135611ee9816116b6565b908201526080611efa838201611938565b9082015260a082810135611f0d816116b6565b908201528452928401928101611e8b565b5f805f805f805f80610100898b031215611f36575f80fd5b611f3f896116cd565b9750602089013567ffffffffffffffff80821115611f5b575f80fd5b611f678c838d0161189a565b985060408b0135915080821115611f7c575f80fd5b611f888c838d0161189a565b975060608b0135915080821115611f9d575f80fd5b611fa98c838d0161189a565b9650611fb760808c01611914565b955060a08b0135915080821115611fcc575f80fd5b611fd88c838d01611d7e565b945060c08b0135915080821115611fed575f80fd5b611ff98c838d01611e4a565b935060e08b013591508082111561200e575f80fd5b5061201b8b828c01611a69565b9150509295985092959890939650565b5f806040838503121561203c575f80fd5b8235612047816116b6565b9150602083013567ffffffffffffffff811115612062575f80fd5b61206e8582860161189a565b9150509250929050565b5f5b8381101561209257818101518382015260200161207a565b50505f910152565b5f81518084526120b1816020860160208601612078565b601f01601f19169290920160200192915050565b828152604060208201525f6120dd604083018461209a565b949350505050565b5f82601f8301126120f4575f80fd5b81356020612104611841836117c8565b82815260059290921b84018101918181019086841115612122575f80fd5b8286015b84811015611bb757803567ffffffffffffffff811115612144575f80fd5b6121528986838b010161189a565b845250918301918301612126565b5f805f8060808587031215612173575f80fd5b843561217e816116b6565b9350602085013561218e816116b6565b9250604085013561219e81611906565b9150606085013567ffffffffffffffff8111156121b9575f80fd5b6121c5878288016120e5565b91505092959194509250565b5f815180845260208085019450602084015f5b8381101561220357815160070b875295820195908201906001016121e4565b509495945050505050565b8381528260070b6020820152606060408201525f61222f60608301846121d1565b95945050505050565b5f805f6060848603121561224a575f80fd5b8335612255816116b6565b9250602084013561226581611906565b9150604084013567ffffffffffffffff811115612280575f80fd5b61228c868287016120e5565b9150509250925092565b5f82601f8301126122a5575f80fd5b813560206122b5611841836117c8565b82815260c092830285018201928282019190878511156122d3575f80fd5b8387015b85811015611e3d5781818a0312156122ed575f80fd5b6122f5611774565b813561230081611906565b81528186013561230f81611906565b8187015260408281013561232281611906565b9082015260608281013561233581611906565b908201526080612346838201611938565b9082015260a082810135612359816116b6565b9082015284529284019281016122d7565b5f805f805f805f805f806101408b8d031215612384575f80fd5b61238d8b6116cd565b995060208b013567ffffffffffffffff808211156123a9575f80fd5b6123b58e838f0161189a565b9a5060408d01359150808211156123ca575f80fd5b6123d68e838f0161189a565b995060608d01359150808211156123eb575f80fd5b6123f78e838f0161189a565b985061240560808e01611914565b975061241360a08e01611914565b965061242160c08e0161192d565b955060e08d0135915080821115612436575f80fd5b6124428e838f01611d7e565b94506101008d0135915080821115612458575f80fd5b6124648e838f01612296565b93506101208d013591508082111561247a575f80fd5b506124878d828e01611a69565b9150509295989b9194979a5092959850565b5f805f606084860312156124ab575f80fd5b83356124b6816116b6565b925060208401356124c6816116b6565b929592945050506040919091013590565b634e487b7160e01b5f52603260045260245ffd5b5f82516124fc818460208701612078565b9190910192915050565b5f60208284031215612516575f80fd5b8151610cfa8161191f565b6001600160a01b0383168152604060208201525f6120dd604083018461209a565b8215158152604060208201525f6120dd604083018461209a565b8260070b8152604060208201525f6120dd60408301846121d1565b5f604082016001600160a01b0380861684526020604060208601528286518085526060870191506020880194505f5b818110156125c45785518516835294830194918301916001016125a6565b509098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611e3d57601f198684030189528151604081518552858201519150808686015281511515818601528582015160606001600160a01b038083168289015283850151935060a09250608083818a015261264c60e08a018661209a565b92860151898403603f1901858b0152929450612668858461209a565b9501511660c097909701969096525050988401989250908301906001016125ed565b5f610160825181855261269f8286018261209a565b915050602083015184820360208601526126b9828261209a565b91505060408301516126d660408601826001600160a01b03169052565b50606083015184820360608601526126ee828261209a565b9150506080830151612704608086018215159052565b5060a083015161271960a086018260070b9052565b5060c083015161272d60c086018215159052565b5060e083015184820360e086015261274582826125d2565b9150506101008084015161278182870182805160070b82526001600160a01b036020820151166020830152604081015160070b60408301525050565b5090949350505050565b606081525f61279d606083018661268a565b90508360070b60208301528260030b6040830152949350505050565b5f80604083850312156127ca575f80fd5b82516127d58161191f565b6020840151909250611709816116b6565b602081525f610cfa602083018461268a565b5f815180845260208085019450602084015f5b83811015612203578151805160070b8852838101516001600160a01b03908116858a01526040808301511515908a01526060808301511515908a0152608091820151169088015260a0909601959082019060010161280b565b5f6060808352612877606084018761268a565b60208482038186015261288a82886127f8565b915060408583036040870152828751808552838501915083890194505f5b8181101561290b5785518051600790810b855286820151810b8786015285820151900b85850152878101516001600160a01b039081168986015260808083015115159086015260a09182015116908401529484019460c0909201916001016128a8565b50909a9950505050505050505050565b5f606082016001600160a01b038616835260208560070b60208501526060604085015281855180845260808601915060808160051b8701019350602087015f5b8281101561298957607f1988870301845261297786835161209a565b9550928401929084019060010161295b565b50939998505050505050505050565b5f805f606084860312156129aa575f80fd5b83516129b58161191f565b809350506020808501516129c881611906565b604086015190935067ffffffffffffffff8111156129e4575f80fd5b8501601f810187136129f4575f80fd5b8051612a02611841826117c8565b81815260059190911b82018301908381019089831115612a20575f80fd5b928401925b82841015612a47578351612a3881611906565b82529284019290840190612a25565b80955050505050509250925092565b5f60a0808352612a6960a084018961268a565b602060078960070b8287015260408960030b604088015260608785036060890152612a94858b6127f8565b9450608088860360808a0152858a518088528688019150868c0197505f5b81811015612b0c5788518051880b845288810151880b8985015286810151880b8785015285810151880b86850152848101511515858501528a01516001600160a01b03168a8401529787019760c090920191600101612ab2565b50909f9e505050505050505050505050505050565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212200e1ef617cb2df316ead8f1287166e15db10bb2e54b25f229ad19cd7ce115c4e564736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts-abi/contracts/solidity/opcode-logger/OpcodeLogger.sol/OpcodeLogger.json b/contracts-abi/contracts/solidity/opcode-logger/OpcodeLogger.sol/OpcodeLogger.json index 27c6e6e74..c43e7a36e 100644 --- a/contracts-abi/contracts/solidity/opcode-logger/OpcodeLogger.sol/OpcodeLogger.json +++ b/contracts-abi/contracts/solidity/opcode-logger/OpcodeLogger.sol/OpcodeLogger.json @@ -100,6 +100,142 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "amounts", + "type": "int64[]" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "executeHtsMintTokenRevertingCalls", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "amounts", + "type": "int64[]" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "executeHtsMintTokenRevertingCallsAndFailToAssociate", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "int64", + "name": "amount", + "type": "int64" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "mintTokenExternalCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "amounts", + "type": "int64[]" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "nestEverySecondHtsMintTokenCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "owner", diff --git a/contracts-abi/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol/TokenCreateOpcodeLogger.json b/contracts-abi/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol/TokenCreateOpcodeLogger.json new file mode 100644 index 000000000..e3b4abe88 --- /dev/null +++ b/contracts-abi/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol/TokenCreateOpcodeLogger.json @@ -0,0 +1,265 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "CallResponseEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "CreatedToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "kycGranted", + "type": "bool" + } + ], + "name": "KycGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int64", + "name": "newTotalSupply", + "type": "int64" + }, + { + "indexed": false, + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + } + ], + "name": "MintedToken", + "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" + } + ], + "name": "createNonFungibleTokenPublic", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "int64", + "name": "amount", + "type": "int64" + }, + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "name": "mintTokenPublic", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "int64", + "name": "newTotalSupply", + "type": "int64" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bytes", + "name": "encodedFunctionSelector", + "type": "bytes" + } + ], + "name": "redirectForToken", + "outputs": [ + { + "internalType": "int256", + "name": "responseCode", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serialNumber", + "type": "uint256" + } + ], + "name": "transferFromNFT", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json b/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json index 89d222489..2bb988720 100644 --- a/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json +++ b/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol/Airdrop.json @@ -190,6 +190,11 @@ "internalType": "address[]", "name": "receivers", "type": "address[]" + }, + { + "internalType": "int64[]", + "name": "serials", + "type": "int64[]" } ], "name": "nftAirdropDistribute", diff --git a/contracts-abi/contracts/wrapped-tokens/WHBAR.sol/WHBAR.json b/contracts-abi/contracts/wrapped-tokens/WHBAR.sol/WHBAR.json index 1c0d3920d..22b565218 100644 --- a/contracts-abi/contracts/wrapped-tokens/WHBAR.sol/WHBAR.json +++ b/contracts-abi/contracts/wrapped-tokens/WHBAR.sol/WHBAR.json @@ -1,4 +1,14 @@ [ + { + "inputs": [], + "name": "InsufficientAllowance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -95,12 +105,12 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "owner", "type": "address" }, { "internalType": "address", - "name": "", + "name": "spender", "type": "address" } ], @@ -108,7 +118,7 @@ "outputs": [ { "internalType": "uint256", - "name": "", + "name": "amount", "type": "uint256" } ], @@ -143,7 +153,7 @@ "inputs": [ { "internalType": "address", - "name": "", + "name": "user", "type": "address" } ], @@ -151,7 +161,7 @@ "outputs": [ { "internalType": "uint256", - "name": "", + "name": "balance", "type": "uint256" } ], diff --git a/contracts/solidity/opcode-logger/OpcodeLogger.sol b/contracts/solidity/opcode-logger/OpcodeLogger.sol index 6ca1ab3a5..67f9c3ada 100644 --- a/contracts/solidity/opcode-logger/OpcodeLogger.sol +++ b/contracts/solidity/opcode-logger/OpcodeLogger.sol @@ -74,4 +74,51 @@ contract OpcodeLogger { return isSuccess; } + + function executeHtsMintTokenRevertingCalls(address contractAddress, address tokenAddress, int64[] memory amounts, bytes[] memory metadata) external returns (bool success) { + for (uint i = 0; i < amounts.length; i++) { + if (amounts[i] < 0){ + // reverts with 'Minting reverted with INVALID_TOKEN_ID' + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(contractAddress, 0, metadata)); + } else { + // reverts with 'Minting tokens reverted with TOKEN_MAX_SUPPLY_REACHED' + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(tokenAddress, amounts[i], metadata)); + } + } + } + + function executeHtsMintTokenRevertingCallsAndFailToAssociate(address contractAddress, address tokenAddress, int64[] memory amounts, bytes[] memory metadata) external returns (bool success) { + for (uint i = 0; i < amounts.length; i++) { + if (amounts[i] < 0){ + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(contractAddress, 0, metadata)); + } else { + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(tokenAddress, amounts[i], metadata)); + } + } + + // reverts with 'Association reverted with TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT' + (success,) = address(contractAddress).call(abiEncodeAssociateTokenPublic(contractAddress, tokenAddress)); + } + + function nestEverySecondHtsMintTokenCall(address contractAddress, address token, int64[] memory amounts, bytes[] memory metadata) external returns (bool success) { + for (uint i = 0; i < amounts.length; i++) { + if (i % 2 == 0){ + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(token, amounts[i], metadata)); + } else { + this.mintTokenExternalCall(contractAddress, token, amounts[i], metadata); + } + } + } + + function mintTokenExternalCall(address contractAddress, address token, int64 amount, bytes[] memory metadata) external returns (bool success) { + (success,) = address(contractAddress).call(abiEncodeMintTokenPublic(token, amount, metadata)); + } + + function abiEncodeMintTokenPublic(address token, int64 amount, bytes[] memory metadata) internal pure returns (bytes memory abiEncodedData) { + return abi.encodeWithSignature("mintTokenPublic(address,int64,bytes[])", token, amount, metadata); + } + + function abiEncodeAssociateTokenPublic(address account, address token) internal pure returns (bytes memory abiEncodedData) { + return abi.encodeWithSignature("associateTokenPublic(address,address)", account, token); + } } diff --git a/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol b/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol new file mode 100644 index 000000000..eae8d284a --- /dev/null +++ b/contracts/solidity/opcode-logger/TokenCreateOpcodeLogger.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "contracts/system-contracts/hedera-token-service/HederaTokenService.sol"; +import "contracts/system-contracts/hedera-token-service/ExpiryHelper.sol"; +import "contracts/system-contracts/hedera-token-service/KeyHelper.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract TokenCreateOpcodeLogger is HederaTokenService, ExpiryHelper, KeyHelper { + + string name = "tokenName"; + string symbol = "tokenSymbol"; + string memo = "memo"; + int64 initialTotalSupply = 10000; + int64 maxSupply = 10000; + int32 decimals = 8; + bool freezeDefaultStatus = false; + + event ResponseCode(int responseCode); + event CreatedToken(address tokenAddress); + event MintedToken(int64 newTotalSupply, int64[] serialNumbers); + event KycGranted(bool kycGranted); + + function createFungibleTokenPublic( + address treasury + ) public payable { + IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](5); + keys[0] = getSingleKey(KeyType.ADMIN, KeyType.PAUSE, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[1] = getSingleKey(KeyType.KYC, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[2] = getSingleKey(KeyType.FREEZE, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[3] = getSingleKey(KeyType.WIPE, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[4] = getSingleKey(KeyType.SUPPLY, KeyValueType.INHERIT_ACCOUNT_KEY, 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(KeyType.ADMIN, KeyType.PAUSE, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[1] = getSingleKey(KeyType.KYC, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[2] = getSingleKey(KeyType.FREEZE, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[3] = getSingleKey(KeyType.SUPPLY, KeyValueType.INHERIT_ACCOUNT_KEY, bytes("")); + keys[4] = getSingleKey(KeyType.WIPE, KeyValueType.INHERIT_ACCOUNT_KEY, 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 mintTokenPublic(address token, int64 amount, bytes[] memory metadata) public + returns (int responseCode, int64 newTotalSupply, int64[] memory serialNumbers) { + (responseCode, newTotalSupply, serialNumbers) = HederaTokenService.mintToken(token, amount, metadata); + emit ResponseCode(responseCode); + + if (responseCode != HederaResponseCodes.SUCCESS) { + if (responseCode == HederaResponseCodes.INVALID_TOKEN_ID) { + revert(string(abi.encodePacked("Minting reverted with INVALID_TOKEN_ID"))); + } else if (responseCode == HederaResponseCodes.TOKEN_MAX_SUPPLY_REACHED) { + revert(string(abi.encodePacked("Minting ", Strings.toString((uint256(uint64(amount)))), " tokens reverted with TOKEN_MAX_SUPPLY_REACHED"))); + } + + revert (string(abi.encodePacked("Minting was reverted with responseCode: ", Strings.toString(uint256(responseCode))))); + } + emit MintedToken(newTotalSupply, serialNumbers); + } + + function associateTokenPublic(address account, address token) public returns (int responseCode) { + responseCode = HederaTokenService.associateToken(account, token); + emit ResponseCode(responseCode); + + if (responseCode != HederaResponseCodes.SUCCESS) { + if (responseCode == HederaResponseCodes.TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT) { + revert(string(abi.encodePacked("Association reverted with TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT"))); + } + revert ("Default associateTokenPublic() revert reason"); + } + } +} diff --git a/contracts/system-contracts/HederaResponseCodes.sol b/contracts/system-contracts/HederaResponseCodes.sol index 36bbd6486..7dfc7a8e8 100644 --- a/contracts/system-contracts/HederaResponseCodes.sol +++ b/contracts/system-contracts/HederaResponseCodes.sol @@ -308,4 +308,62 @@ library HederaResponseCodes { int32 internal constant INSUFFICIENT_BALANCES_FOR_STORAGE_RENT = 327; // The combined balances of a contract and its auto-renew account (if any) did not cover the rent charged for net new storage used in a transaction. int32 internal constant MAX_CHILD_RECORDS_EXCEEDED = 328; // A contract transaction tried to use more than the allowed number of child records, via either system contract records or internal contract creations. int32 internal constant INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES = 329; // The combined balances of a contract and its auto-renew account (if any) or balance of an account did not cover the auto-renewal fees in a transaction. + int32 internal constant TRANSACTION_HAS_UNKNOWN_FIELDS = 330; // A transaction's protobuf message includes unknown fields; could mean that a client expects not-yet-released functionality to be available. + int32 internal constant ACCOUNT_IS_IMMUTABLE = 331; // The account cannot be modified. Account's key is not set + int32 internal constant ALIAS_ALREADY_ASSIGNED = 332; // An alias that is assigned to an account or contract cannot be assigned to another account or contract. + int32 internal constant INVALID_METADATA_KEY = 333; // A provided metadata key was invalid. Verification includes, for example, checking the size of Ed25519 and ECDSA(secp256k1) public keys. + int32 internal constant TOKEN_HAS_NO_METADATA_KEY = 334; // Metadata key is not set on token + int32 internal constant MISSING_TOKEN_METADATA = 335; // Token Metadata is not provided + int32 internal constant MISSING_SERIAL_NUMBERS = 336; // NFT serial numbers are missing in the TokenUpdateNftsTransactionBody + int32 internal constant TOKEN_HAS_NO_ADMIN_KEY = 337; // Admin key is not set on token + int32 internal constant NODE_DELETED = 338; // A transaction failed because the consensus node identified is deleted from the address book. + int32 internal constant INVALID_NODE_ID = 339; // A transaction failed because the consensus node identified is not valid or does not exist in state. + int32 internal constant INVALID_GOSSIP_ENDPOINT = 340; // A transaction failed because one or more entries in the list of service endpoints for the `gossip_endpoint` field is invalid.
The most common cause for this response is a service endpoint that has the domain name (DNS) set rather than address and port. + int32 internal constant INVALID_NODE_ACCOUNT_ID = 341; // A transaction failed because the node account identifier provided does not exist or is not valid. One common source of this error is providing a node account identifier using the "alias" form rather than "numeric" form. + int32 internal constant INVALID_NODE_DESCRIPTION = 342; // A transaction failed because the description field cannot be encoded as UTF-8 or is more than 100 bytes when encoded. + int32 internal constant INVALID_SERVICE_ENDPOINT = 343; // A transaction failed because one or more entries in the list of service endpoints for the `service_endpoint` field is invalid.
The most common cause for this response is a service endpoint that has the domain name (DNS) set rather than address and port. + int32 internal constant INVALID_GOSSIP_CA_CERTIFICATE = 344; // A transaction failed because the TLS certificate provided for the node is missing or invalid. + int32 internal constant INVALID_GRPC_CERTIFICATE = 345; // A transaction failed because the hash provided for the gRPC certificate is present but invalid. + int32 internal constant INVALID_MAX_AUTO_ASSOCIATIONS = 346; // The maximum automatic associations value is not valid. The most common cause for this error is a value less than `-1`. + int32 internal constant MAX_NODES_CREATED = 347; // The maximum number of nodes allowed in the address book have been created. + int32 internal constant IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT = 348; // In ServiceEndpoint, domain_name and ipAddressV4 are mutually exclusive. + int32 internal constant GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN = 349; // Fully qualified domain name is not allowed in gossip_endpoint. + int32 internal constant FQDN_SIZE_TOO_LARGE = 350; // In ServiceEndpoint, domain_name size too large. + int32 internal constant INVALID_ENDPOINT = 351; // ServiceEndpoint is invalid. + int32 internal constant GOSSIP_ENDPOINTS_EXCEEDED_LIMIT = 352; // The number of gossip endpoints exceeds the limit. + int32 internal constant TOKEN_REFERENCE_REPEATED = 353; // The transaction attempted to use duplicate `TokenReference`. This affects `TokenReject` attempting to reject same token reference more than once. + int32 internal constant INVALID_OWNER_ID = 354; // The account id specified as the owner in `TokenReject` is invalid or does not exist. + int32 internal constant TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED = 355; // The transaction attempted to use more than the allowed number of `TokenReference`. + int32 internal constant SERVICE_ENDPOINTS_EXCEEDED_LIMIT = 356; // The number of service endpoints exceeds the limit. + int32 internal constant INVALID_IPV4_ADDRESS = 357; // The IPv4 address is invalid. + int32 internal constant EMPTY_TOKEN_REFERENCE_LIST = 358; // The transaction attempted to use empty `TokenReference` list. + int32 internal constant UPDATE_NODE_ACCOUNT_NOT_ALLOWED = 359; // The node account is not allowed to be updated. + int32 internal constant TOKEN_HAS_NO_METADATA_OR_SUPPLY_KEY = 360; // The token has no metadata or supply key. + int32 internal constant EMPTY_PENDING_AIRDROP_ID_LIST = 361; // The list of `PendingAirdropId`s is empty and MUST NOT be empty. + int32 internal constant PENDING_AIRDROP_ID_REPEATED = 362; // A `PendingAirdropId` is repeated in a `claim` or `cancel` transaction. + int32 internal constant PENDING_AIRDROP_ID_LIST_TOO_LONG = 363; // The number of `PendingAirdropId` values in the list exceeds the maximum allowable number. + int32 internal constant PENDING_NFT_AIRDROP_ALREADY_EXISTS = 364; // A pending airdrop already exists for the specified NFT. + int32 internal constant ACCOUNT_HAS_PENDING_AIRDROPS = 365; // The identified account is sender for one or more pending airdrop(s) and cannot be deleted. The requester SHOULD cancel all pending airdrops before resending this transaction. + int32 internal constant THROTTLED_AT_CONSENSUS = 366; // Consensus throttle did not allow execution of this transaction. The transaction should be retried after a modest delay. + int32 internal constant INVALID_PENDING_AIRDROP_ID = 367; // The provided pending airdrop id is invalid. This pending airdrop MAY already be claimed or cancelled. The client SHOULD query a mirror node to determine the current status of the pending airdrop. + int32 internal constant TOKEN_AIRDROP_WITH_FALLBACK_ROYALTY = 368; // The token to be airdropped has a fallback royalty fee and cannot be sent or claimed via an airdrop transaction. + int32 internal constant INVALID_TOKEN_IN_PENDING_AIRDROP = 369; // This airdrop claim is for a pending airdrop with an invalid token. The token might be deleted, or the sender may not have enough tokens to fulfill the offer. The client SHOULD query mirror node to determine the status of the pending airdrop and whether the sender can fulfill the offer. + int32 internal constant SCHEDULE_EXPIRY_IS_BUSY = 370; // A scheduled transaction configured to wait for expiry to execute was given an expiry time at which there is already too many transactions scheduled to expire; its creation must be retried with a different expiry. + int32 internal constant INVALID_GRPC_CERTIFICATE_HASH = 371; // The provided gRPC certificate hash is invalid. + int32 internal constant MISSING_EXPIRY_TIME = 372; // A scheduled transaction configured to wait for expiry to execute was not given an explicit expiration time. + int32 internal constant NO_SCHEDULING_ALLOWED_AFTER_SCHEDULED_RECURSION = 373; // A contract operation attempted to schedule another transaction after it had already scheduled a recursive contract call. + int32 internal constant RECURSIVE_SCHEDULING_LIMIT_REACHED = 374; // A contract can schedule recursive calls a finite number of times (this is approximately four million times with typical network configuration). + int32 internal constant WAITING_FOR_LEDGER_ID = 375; // The target network is waiting for the ledger ID to be set, which is a side effect of finishing the network's TSS construction. + int32 internal constant MAX_ENTRIES_FOR_FEE_EXEMPT_KEY_LIST_EXCEEDED = 376; // The provided fee exempt key list size exceeded the limit. + int32 internal constant FEE_EXEMPT_KEY_LIST_CONTAINS_DUPLICATED_KEYS = 377; // The provided fee exempt key list contains duplicated keys. + int32 internal constant INVALID_KEY_IN_FEE_EXEMPT_KEY_LIST = 378; // The provided fee exempt key list contains an invalid key. + int32 internal constant INVALID_FEE_SCHEDULE_KEY = 379; // The provided fee schedule key contains an invalid key. + int32 internal constant FEE_SCHEDULE_KEY_CANNOT_BE_UPDATED = 380; // If a fee schedule key is not set when we create a topic we cannot add it on update. + int32 internal constant FEE_SCHEDULE_KEY_NOT_SET = 381; // If the topic's custom fees are updated the topic SHOULD have a fee schedule key. + int32 internal constant MAX_CUSTOM_FEE_LIMIT_EXCEEDED = 382; // The fee amount is exceeding the amount that the payer is willing to pay. + int32 internal constant NO_VALID_MAX_CUSTOM_FEE = 383; // There are no corresponding custom fees. + int32 internal constant INVALID_MAX_CUSTOM_FEES = 384; // The provided list contains invalid max custom fee. + int32 internal constant DUPLICATE_DENOMINATION_IN_MAX_CUSTOM_FEE_LIST = 385; // The provided max custom fee list contains fees with duplicate denominations. + int32 internal constant DUPLICATE_ACCOUNT_ID_IN_MAX_CUSTOM_FEE_LIST = 386; // The provided max custom fee list contains fees with duplicate account id. + int32 internal constant MAX_CUSTOM_FEES_IS_NOT_SUPPORTED = 387; // Max custom fees list is not supported for this operation. } diff --git a/contracts/system-contracts/hedera-schedule-service/HederaScheduleService.sol b/contracts/system-contracts/hedera-schedule-service/HederaScheduleService.sol new file mode 100644 index 000000000..64394d872 --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/HederaScheduleService.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.5.0 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../HederaResponseCodes.sol"; +import "./IHederaScheduleService.sol"; + +abstract contract HederaScheduleService { + address constant scheduleSystemContractAddress = address(0x16b); + + /// Authorizes the calling contract as a signer to the schedule transaction. + /// @param schedule the address of the schedule transaction. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function authorizeSchedule(address schedule) internal returns (int64 responseCode) { + (bool success, bytes memory result) = scheduleSystemContractAddress.call( + abi.encodeWithSelector(IHederaScheduleService.authorizeSchedule.selector, schedule)); + responseCode = success ? abi.decode(result, (int64)) : HederaResponseCodes.UNKNOWN; + } + + /// Allows for the signing of a schedule transaction given a protobuf encoded signature map + /// The message signed by the keys is defined to be the concatenation of the shard, realm, and schedule transaction ID. + /// @param schedule the address of the schedule transaction. + /// @param signatureMap the protobuf encoded signature map + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function signSchedule(address schedule, bytes memory signatureMap) internal returns (int64 responseCode) { + (bool success, bytes memory result) = scheduleSystemContractAddress.call( + abi.encodeWithSelector(IHederaScheduleService.signSchedule.selector, schedule, signatureMap)); + responseCode = success ? abi.decode(result, (int64)) : HederaResponseCodes.UNKNOWN; + } + + /// Allows for the creation of a schedule transaction for given a system contract address, abi encoded call data and payer address + /// Currently supports the Hedera Token Service System Contract (0x167) with encoded call data for + /// createFungibleToken, createNonFungibleToken, createFungibleTokenWithCustomFees, createNonFungibleTokenWithCustomFees + /// and updateToken functions + /// @param systemContractAddress the address of the system contract from which to create the schedule transaction + /// @param callData the abi encoded call data for the system contract function + /// @param payer the address of the account that will pay for the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return scheduleAddress The address of the newly created schedule transaction. + function scheduleNative(address systemContractAddress, bytes memory callData, address payer) internal returns (int64 responseCode, address scheduleAddress) { + (bool success, bytes memory result) = scheduleSystemContractAddress.call( + abi.encodeWithSelector(IHederaScheduleService.scheduleNative.selector, systemContractAddress, callData, payer)); + (responseCode, scheduleAddress) = success ? abi.decode(result, (int64, address)) : (int64(HederaResponseCodes.UNKNOWN), address(0)); + } + + /// Returns the token information for a scheduled fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return fungibleTokenInfo The token information for the scheduled fungible token create transaction + function getScheduledCreateFungibleTokenInfo(address scheduleAddress) internal returns (int64 responseCode, IHederaTokenService.FungibleTokenInfo memory fungibleTokenInfo) { + (bool success, bytes memory result) = scheduleSystemContractAddress.call( + abi.encodeWithSelector(IHederaScheduleService.getScheduledCreateFungibleTokenInfo.selector, scheduleAddress)); + IHederaTokenService.FungibleTokenInfo memory defaultTokenInfo; + (responseCode, fungibleTokenInfo) = success ? abi.decode(result, (int64, IHederaTokenService.FungibleTokenInfo)) : (int64(HederaResponseCodes.UNKNOWN), defaultTokenInfo); + } + + /// Returns the token information for a scheduled non fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return nonFungibleTokenInfo The token information for the scheduled non fungible token create transaction + function getScheduledCreateNonFungibleTokenInfo(address scheduleAddress) internal returns (int64 responseCode, IHederaTokenService.NonFungibleTokenInfo memory nonFungibleTokenInfo) { + (bool success, bytes memory result) = scheduleSystemContractAddress.call( + abi.encodeWithSelector(IHederaScheduleService.getScheduledCreateNonFungibleTokenInfo.selector, scheduleAddress)); + IHederaTokenService.NonFungibleTokenInfo memory defaultTokenInfo; + (responseCode, nonFungibleTokenInfo) = success ? abi.decode(result, (int64, IHederaTokenService.NonFungibleTokenInfo)) : (int64(HederaResponseCodes.UNKNOWN), defaultTokenInfo); + } +} diff --git a/contracts/system-contracts/hedera-schedule-service/IHRC755.sol b/contracts/system-contracts/hedera-schedule-service/IHRC755.sol new file mode 100644 index 000000000..0e28bed49 --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/IHRC755.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; +pragma experimental ABIEncoderV2; + +interface IHRC755 { + /// Authorizes the calling contract as a signer to the schedule transaction. + /// @param schedule the address of the schedule transaction. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function authorizeSchedule(address schedule) external returns (int64 responseCode); + + /// Allows for the signing of a schedule transaction given a protobuf encoded signature map + /// The message signed by the keys is defined to be the concatenation of the shard, realm, and schedule transaction ID. + /// @param schedule the address of the schedule transaction. + /// @param signatureMap the protobuf encoded signature map + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function signSchedule(address schedule, bytes memory signatureMap) external returns (int64 responseCode); +} diff --git a/contracts/system-contracts/hedera-schedule-service/IHRC755ScheduleFacade.sol b/contracts/system-contracts/hedera-schedule-service/IHRC755ScheduleFacade.sol new file mode 100644 index 000000000..d5e1cea00 --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/IHRC755ScheduleFacade.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; +pragma experimental ABIEncoderV2; + +interface IHRC755ScheduleFacade { + /// Signs the targeted schedule transaction with the key of the calling EOA. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function signSchedule() external returns (int64 responseCode); +} diff --git a/contracts/system-contracts/hedera-schedule-service/IHRC756.sol b/contracts/system-contracts/hedera-schedule-service/IHRC756.sol new file mode 100644 index 000000000..d66883cae --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/IHRC756.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../hedera-token-service/IHederaTokenService.sol"; + +interface IHRC756 { + /// Allows for the creation of a schedule transaction for given a system contract address, abi encoded call data and payer address + /// Currently supports the Hedera Token Service System Contract (0x167) with encoded call data for + /// createFungibleToken, createNonFungibleToken, createFungibleTokenWithCustomFees, createNonFungibleTokenWithCustomFees + /// and updateToken functions + /// @param systemContractAddress the address of the system contract from which to create the schedule transaction + /// @param callData the abi encoded call data for the system contract function + /// @param payer the address of the account that will pay for the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return scheduleAddress The address of the newly created schedule transaction. + function scheduleNative(address systemContractAddress, bytes memory callData, address payer) external returns (int64 responseCode, address scheduleAddress); + + /// Returns the token information for a scheduled fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return fungibleTokenInfo The token information for the scheduled fungible token create transaction + function getScheduledCreateFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.FungibleTokenInfo memory fungibleTokenInfo); + + /// Returns the token information for a scheduled non fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return nonFungibleTokenInfo The token information for the scheduled non fungible token create transaction + function getScheduledCreateNonFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.NonFungibleTokenInfo memory nonFungibleTokenInfo); +} diff --git a/contracts/system-contracts/hedera-schedule-service/IHederaScheduleService.sol b/contracts/system-contracts/hedera-schedule-service/IHederaScheduleService.sol new file mode 100644 index 000000000..a0b13e632 --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/IHederaScheduleService.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.4.9 <0.9.0; +pragma experimental ABIEncoderV2; + +import "../hedera-token-service/IHederaTokenService.sol"; +interface IHederaScheduleService { + + /// Authorizes the calling contract as a signer to the schedule transaction. + /// @param schedule the address of the schedule transaction. + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function authorizeSchedule(address schedule) external returns (int64 responseCode); + + /// Allows for the signing of a schedule transaction given a protobuf encoded signature map + /// The message signed by the keys is defined to be the concatenation of the shard, realm, and schedule transaction ID. + /// @param schedule the address of the schedule transaction. + /// @param signatureMap the protobuf encoded signature map + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + function signSchedule(address schedule, bytes memory signatureMap) external returns (int64 responseCode); + + /// Allows for the creation of a schedule transaction for a given system contract address, abi encoded call data and payer address + /// Currently supports the Hedera Token Service System Contract (0x167) with encoded call data for + /// createFungibleToken, createNonFungibleToken, createFungibleTokenWithCustomFees, createNonFungibleTokenWithCustomFees + /// and updateToken functions + /// @param systemContractAddress the address of the system contract from which to create the schedule transaction + /// @param callData the abi encoded call data for the system contract function + /// @param payer the address of the account that will pay for the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return scheduleAddress The address of the newly created schedule transaction. + function scheduleNative(address systemContractAddress, bytes memory callData, address payer) external returns (int64 responseCode, address scheduleAddress); + + /// Returns the token information for a scheduled fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return fungibleTokenInfo The token information for the scheduled fungible token create transaction + function getScheduledCreateFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.FungibleTokenInfo memory fungibleTokenInfo); + + /// Returns the token information for a scheduled non fungible token create transaction + /// @param scheduleAddress the address of the schedule transaction + /// @return responseCode The response code for the status of the request. SUCCESS is 22. + /// @return nonFungibleTokenInfo The token information for the scheduled non fungible token create transaction + function getScheduledCreateNonFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.NonFungibleTokenInfo memory nonFungibleTokenInfo); +} diff --git a/contracts/system-contracts/hedera-schedule-service/README.md b/contracts/system-contracts/hedera-schedule-service/README.md new file mode 100644 index 000000000..b289db723 --- /dev/null +++ b/contracts/system-contracts/hedera-schedule-service/README.md @@ -0,0 +1,21 @@ +## Hedera Schedule Service (HSS) System Contract Functions + +The Hedera Schedule Service (HSS) System Contract is accessible at address `0x16b` on the Hedera network. This contract interface introduces a new schedule transaction proxy contract to interact with other contracts for functionality such as creating and signing scheduled transactions. It also enables querying information about certain scheduled transactions. + +The table below outlines the available Hedera Schedule Service System Contract functions: + +| Function Name | Function Selector Hash | Consensus Node Release Version | HIP | Method Interface | +| ----------------- | ---------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------- | +| `authorizeSchedule` | `0xf0637961` | [0.57](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.57) | [HIP 755](https://hips.hedera.com/hip/hip-755) | `authorizeSchedule(address schedule) external returns (int64 responseCode)` | +| `signSchedule` | `0x358eeb03` | [0.59](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.59) | [HIP 755](https://hips.hedera.com/hip/hip-755) | `signSchedule(address schedule, bytes memory signatureMap) external returns (int64 responseCode` | +| `scheduleNative` | `0xca829811` | [0.59](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.59) | [HIP 756](https://hips.hedera.com/hip/hip-756) | `scheduleNative(address systemContractAddress, bytes memory callData, address payer) external returns (int64 responseCode, address scheduleAddress)` | +| `getScheduledCreateFungibleTokenInfo` | `0xda2d5f8f` | [0.59](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.59) | [HIP 756](https://hips.hedera.com/hip/hip-756) | `getScheduledCreateFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.FungibleTokenInfo memory fungibleTokenInfo)` | +| `getScheduledCreateNonFungibleTokenInfo` | `0xd68c902c` | [0.59](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.59) | [HIP 756](https://hips.hedera.com/hip/hip-756) | `getScheduledCreateNonFungibleTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.NonFungibleTokenInfo memory nonFungibleTokenInfo)` | + +The Hedera network also make facade contract calls available to EOAs for improved experience. +Facade function allow for EOAs to make calls without requiring a deployed contract +The table below outlines the available Hedera Schedule Service (HSS) System Contract facade functions: + +| Function Name | Function Selector Hash | Consensus Node Release Version | HIP | Method Interface | +| -------------------------------------- | ---------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `signSchedule` | `0x06d15889` | [0.57](https://docs.hedera.com/hedera/networks/release-notes/services#release-v0.57) | [HIP 755](https://hips.hedera.com/hip/hip-755) | `signSchedule() external returns (int64 responseCode)` \ No newline at end of file diff --git a/contracts/system-contracts/hedera-token-service/IHRC904.sol b/contracts/system-contracts/hedera-token-service/IHRC904.sol index ffd1fef94..dcd3ef366 100644 --- a/contracts/system-contracts/hedera-token-service/IHRC904.sol +++ b/contracts/system-contracts/hedera-token-service/IHRC904.sol @@ -12,16 +12,19 @@ interface IHRC904 is IHTSStructs { /// @notice - As a pending airdrop requiring claim if they have no available auto-association slots /// @notice Immediate airdrops are irreversible, pending airdrops can be canceled /// @notice All transfer fees and auto-renewal rent costs are charged to the transaction submitter + /// @notice The tokenTransfers array is limited to a maximum of 10 elements by default, managed by tokens.maxAllowedAirdropTransfersPerTx configuration /// @param tokenTransfers Array of token transfer lists containing token addresses and recipient details /// @return responseCode The response code for the status of the request. SUCCESS is 22. function airdropTokens(TokenTransferList[] memory tokenTransfers) external returns (int64 responseCode); /// @notice Cancels pending airdrops that have not yet been claimed + /// @notice The pendingAirdrops array is limited to a maximum of 10 elements by default, managed by tokens.maxAllowedPendingAirdropsToCancel configuration /// @param pendingAirdrops Array of pending airdrops to cancel /// @return responseCode The response code for the status of the request. SUCCESS is 22. function cancelAirdrops(PendingAirdrop[] memory pendingAirdrops) external returns (int64 responseCode); /// @notice Claims pending airdrops that were sent to the calling account + /// @notice The pendingAirdrops array is limited to a maximum of 10 elements by default, managed by tokens.maxAllowedPendingAirdropsToClaim configuration /// @param pendingAirdrops Array of pending airdrops to claim /// @return responseCode The response code for the status of the request. SUCCESS is 22. function claimAirdrops(PendingAirdrop[] memory pendingAirdrops) external returns (int64 responseCode); @@ -30,6 +33,7 @@ interface IHRC904 is IHTSStructs { /// @notice This transfer does not charge any custom fees or royalties defined for the tokens /// @notice For fungible tokens, the requesting account's balance will become 0 and the treasury balance will increase by that amount /// @notice For non-fungible tokens, the requesting account will no longer hold the rejected serial numbers and they will be transferred to the treasury + /// @notice The ftAddresses and nftIDs arrays are limited to a combined maximum of 10 elements by default, managed by ledger.tokenRejects.maxLen configuration /// @param rejectingAddress The address rejecting the tokens /// @param ftAddresses Array of fungible token addresses to reject /// @param nftIDs Array of NFT IDs to reject diff --git a/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol b/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol index 39a198f37..636be3e72 100644 --- a/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol +++ b/contracts/system-contracts/hedera-token-service/examples/hrc-904/Airdrop.sol @@ -168,17 +168,16 @@ contract Airdrop is HederaTokenService { // @param token The NFT token address // @param sender The address sending the NFTs // @param receivers Array of addresses to receive the NFTs + // @param serials Array of serial numbers to assign to each receiver // @return responseCode The response code from the airdrop operation (22 = success) - function nftAirdropDistribute(address token, address sender, address[] memory receivers) public payable returns (int64 responseCode) { + function nftAirdropDistribute(address token, address sender, address[] memory receivers, int64[] memory serials) public payable returns (int64 responseCode) { uint256 length = receivers.length; IHederaTokenService.TokenTransferList[] memory tokenTransfers = new IHederaTokenService.TokenTransferList[](1); IHederaTokenService.TokenTransferList memory airdrop; airdrop.token = token; IHederaTokenService.NftTransfer[] memory nftTransfers = new IHederaTokenService.NftTransfer[](length); - int64 serial = 1; for (uint i = 0; i < length; i++) { - nftTransfers[i] = prepareNftTransfer(sender, receivers[i], serial); - serial++; + nftTransfers[i] = prepareNftTransfer(sender, receivers[i], serials[i]); } airdrop.nftTransfers = nftTransfers; tokenTransfers[0] = airdrop; diff --git a/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol b/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol index 1d1155b56..2f0a37567 100644 --- a/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol +++ b/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateContract.sol @@ -15,6 +15,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { int64 maxSupply = 20000000000; int32 decimals = 0; bool freezeDefaultStatus = false; + bool finiteTotalSupplyType = true; event ResponseCode(int responseCode); event CreatedToken(address tokenAddress); @@ -37,12 +38,11 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = HederaTokenService.createFungibleToken(token, initialTotalSupply, decimals); - if (responseCode != HederaResponseCodes.SUCCESS) { revert (); } @@ -66,7 +66,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -102,7 +102,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -129,7 +129,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, false, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, false, keys, expiry ); IHederaTokenService.FixedFee[] memory fixedFees = new IHederaTokenService.FixedFee[](1); @@ -164,7 +164,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -193,7 +193,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -220,7 +220,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -249,7 +249,7 @@ contract TokenCreateContract is HederaTokenService, ExpiryHelper, KeyHelper { ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); IHederaTokenService.FixedFee[] memory fixedFees = new IHederaTokenService.FixedFee[](1); diff --git a/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol b/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol index 29f84a489..a430412e4 100644 --- a/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol +++ b/contracts/system-contracts/hedera-token-service/examples/token-create/TokenCreateCustom.sol @@ -8,6 +8,8 @@ import "../../KeyHelper.sol"; import "../../FeeHelper.sol"; contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelper, FeeHelper { + bool finiteTotalSupplyType = true; + event ResponseCode(int responseCode); event CreatedToken(address tokenAddress); event TransferToken(address tokenAddress, address receiver, int64 amount); @@ -29,7 +31,7 @@ contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelpe ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -64,7 +66,7 @@ contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelpe ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, freezeDefaultStatus, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, freezeDefaultStatus, keys, expiry ); (int responseCode, address tokenAddress) = @@ -93,7 +95,7 @@ contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelpe ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, false, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, false, keys, expiry ); (int responseCode, address tokenAddress) = @@ -120,7 +122,7 @@ contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelpe ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, false, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, false, keys, expiry ); (int responseCode, address tokenAddress) = @@ -148,7 +150,7 @@ contract TokenCreateCustomContract is HederaTokenService, ExpiryHelper, KeyHelpe ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - name, symbol, treasury, memo, true, maxSupply, false, keys, expiry + name, symbol, treasury, memo, finiteTotalSupplyType, maxSupply, false, keys, expiry ); (int responseCode, address tokenAddress) = diff --git a/contracts/system-contracts/hedera-token-service/safe-hts/SafeOperations.sol b/contracts/system-contracts/hedera-token-service/safe-hts/SafeOperations.sol index c41865c82..2044e5326 100644 --- a/contracts/system-contracts/hedera-token-service/safe-hts/SafeOperations.sol +++ b/contracts/system-contracts/hedera-token-service/safe-hts/SafeOperations.sol @@ -6,6 +6,8 @@ import "./SafeHTS.sol"; contract SafeOperations is SafeHTS { + bool finiteTotalSupplyType = true; + event TokenCreated(address); event MintedNft(int64[], int64); event BurnToken(int64); @@ -102,7 +104,7 @@ contract SafeOperations is SafeHTS { 0, msg.sender, 8000000 ); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - "tokenName", "tokenSymbol", msg.sender, "memo", true, 1000, false, getKeys(), expiry + "tokenName", "tokenSymbol", msg.sender, "memo", finiteTotalSupplyType, 1000, false, getKeys(), expiry ); (tokenAddress) = safeCreateNonFungibleToken(token); emit ResponseCode(HederaResponseCodes.SUCCESS); diff --git a/contracts/wrapped-tokens/README.md b/contracts/wrapped-tokens/README.md index 8c505f0da..a15602dbc 100644 --- a/contracts/wrapped-tokens/README.md +++ b/contracts/wrapped-tokens/README.md @@ -19,6 +19,10 @@ The WHBAR contract for Wrapped HBAR to help transactions that use native token p - Deposit - ``` event Deposit(address dst, uint256 wad)``` - Withdrawal - ``` event Withdrawal(address src, uint256 wad)``` +##### Errors: +- InsufficientFunds - ```error InsufficientFunds()``` +- InsufficientAllowance - ```error InsufficientAllowance()``` + ##### Methods: - receive - ```receive() external payable``` - fallback - ```fallback() external payable``` diff --git a/contracts/wrapped-tokens/WHBAR.sol b/contracts/wrapped-tokens/WHBAR.sol index c681852c5..6911a2296 100644 --- a/contracts/wrapped-tokens/WHBAR.sol +++ b/contracts/wrapped-tokens/WHBAR.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.22; +pragma solidity 0.8.24; contract WHBAR { string public name = "Wrapped HBAR"; @@ -11,8 +11,11 @@ contract WHBAR { event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; + error InsufficientFunds(); + error InsufficientAllowance(); + + mapping(address user => uint balance) public balanceOf; + mapping(address owner => mapping(address spender => uint amount)) public allowance; fallback() external payable { deposit(); @@ -29,10 +32,12 @@ contract WHBAR { } function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); + if (!(balanceOf[msg.sender] >= wad)) { + revert InsufficientFunds(); + } balanceOf[msg.sender] -= wad; - payable(msg.sender).transfer(wad); + payable(msg.sender).call{value: wad}(""); emit Withdrawal(msg.sender, wad); } @@ -54,12 +59,15 @@ contract WHBAR { } function transferFrom(address src, address dst, uint wad) public returns (bool) { - require(balanceOf[src] >= wad); + if (!(balanceOf[src] >= wad)) { + revert InsufficientFunds(); + } - if (src != msg.sender && allowance[src][msg.sender] != - type(uint256).max) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; + if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { + if (!(allowance[src][msg.sender] >= wad)) { + revert InsufficientAllowance(); + } + allowance[src][msg.sender] -= wad; } balanceOf[src] -= wad; @@ -67,6 +75,6 @@ contract WHBAR { emit Transfer(src, dst, wad); - return true; + return true; } } diff --git a/lib/layer-zero/HTSConnector.sol b/lib/layer-zero/HTSConnector.sol index da21587fb..5f0eabb17 100644 --- a/lib/layer-zero/HTSConnector.sol +++ b/lib/layer-zero/HTSConnector.sol @@ -9,10 +9,10 @@ import "./hts/KeyHelper.sol"; /** * @title HTS Connector * @dev HTS Connector is a HTS token that extends the functionality of the OFTCore contract. - */ + */ abstract contract HTSConnector is OFTCore, KeyHelper, HederaTokenService { address public htsTokenAddress; - + bool public finiteTotalSupplyType = true; event TokenCreated(address tokenAddress); /** @@ -37,7 +37,7 @@ abstract contract HTSConnector is OFTCore, KeyHelper, HederaTokenService { IHederaTokenService.Expiry memory expiry = IHederaTokenService.Expiry(0, address(this), 8000000); IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken( - _name, _symbol, address(this), "memo", true, 5000, false, keys, expiry + _name, _symbol, address(this), "memo", finiteTotalSupplyType, 5000, false, keys, expiry ); (int responseCode, address tokenAddress) = HederaTokenService.createFungibleToken( diff --git a/lib/layer-zero/README.md b/lib/layer-zero/README.md new file mode 100644 index 000000000..265e55a76 --- /dev/null +++ b/lib/layer-zero/README.md @@ -0,0 +1,146 @@ +:warning: :bangbang: All examples under this folder are exploration code and have NOT been audited. Use them at your own risk! :bangbang: :warning: + +--- + +# Layer Zero examples + +### OApp + +Message-passing interface to send and receive arbitrary pieces of data between contracts existing on different chains. + +##### Action steps: + +- Deploying the oapp contract on each network we're going to interact + +- In order to connect oapps together, we need to set the peer of the target oapp, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- Now, we're sending messages from one chain to another and vice versa + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking whether the messages are received on both chains + +### OFT + +Allows fungible tokens to be transferred across multiple chains. + +##### Action steps: + +- Deploying OFT tokens which under the hood are ERC20s and contain the messaging between chains functionality provided by LZ + +- In order to connect OFTs together, we need to set the peer of the target OFT, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- Now, we're sending tokens between chains. That means we're burning tokens on the source chain and minting new ones on the destination chain + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking whether the token balances are as expected on both the source and destination chains. + +### OFT Adapter + +If your token already exists on the chain you want to connect, you can deploy the OFT Adapter contract to act as an intermediary lockbox for the token. + +##### Action steps: + +- Deploying ERC20 tokens on each chain + +- Deploying an OFT Adapters which will be used as a lockbox of ERC20s deployed the step above, you can use an already existing HTS token as well + +- In order to connect OFT Adapters together, we need to set the peer of the target OFT Adapter, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- We're funding the Adapter on both chains with some liquidity and after that we're approving it to spend the signer's token + +- Now, we're sending already existing tokens that are used by OFT Adapter between different chains + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking the balances on each chain + +### ONFT + +Allows non-fungible tokens to be transferred across multiple chains. + +##### Action steps: + +- Deploying ONFT tokens which under the hood are ERC721s and contain the messaging between chains functionality provided by LZ + +- In order to connect ONFTs together, we need to set the peer of the target ONFT, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- Now, we're sending NFTs between chains. That means we're burning the NFT on the source chain and minting new one on the destination chain + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking whether the NFTs are transferred successfully + +### ONFT Adapter + +If your NFT contract already exists on the chain you want to connect, you can deploy the ONFT Adapter contract to act as an intermediary lockbox. + +##### Action steps: + +- Deploying ERC721s on each chain we want to connect + +- Deploying an ONFT Adapter which will be used as a lockbox of ERC721s deployed the step above + +- In order to connect ONFT Adapters together, we need to set the peer of the target ONFT Adapter, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- First, we have to mint some NFTs on each chain + +- Then, we have to approve the Adapter to be able to spend the NFT we want to send to another chain + +- Now, we're sending already existing NFTs between chains + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking whether the NFTs are transferred successfully + +### HTS Connector + +That's a variant of OFT but using an HTS token. Due to several incompatibilities between ERC20 and HTS tokens, we're not able to use them out of the box. All of them are described in the "HTS Adapter vs HTS Connector" section below. + +##### Action steps: + +- Deploying OFT on an EVM chain and HTS Connector on the Hedera chain. The HTS Connector extends OFTCore and creates HTS token within its constructor. Also, overrides OFTCore _debit and _credit with related HTS mint and burn precompile calls + +- In order to connect OFTs together, we need to set the peer of the target OFT, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- Approving HTS Connector to use some signer's tokens + +- Now, we're sending tokens from an EVM chain to Hedera and receiving HTS tokens and vice versa + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +Finally we're checking whether the balances are expected on both source and destination chains + +### HTS Connector for existing HTS token + +That's a variant of OFT but using an already existing HTS token. Keep in mind that "supply key" of the token must contains the HTS Connector contract's address. + +##### Action steps: + +- Create an HTS token + +- Deploying OFT on an EVM chain and HTS Connector on the Hedera chain. The HTS Connector for existing token extends OFTCore and receives the HTS tokens address as constructor parameter. Also, overrides OFTCore _debit and _credit with related HTS mint and burn precompile calls + +- In order to connect OFTs together, we need to set the peer of the target OFT, more info can be found here https://docs.layerzero.network/v2/developers/evm/getting-started#connecting-your-contracts + +- Adding the HTSConnectorExistingToken contract's address as a supply key of the existing HTS token + +- Funding the HTSConnectorExistingToken contract + +- Approving HTS Connector to use some signer's tokens + +- Now, we're sending tokens from an EVM chain to Hedera and receiving HTS tokens and vice versa + +- Wait a couple of minutes, the LZ progress can be tracked on https://testnet.layerzeroscan.com/tx/ + +- Finally we're checking whether the balances are expected on both source and destination chains + +### Useful information: +- The addresses of endpoints [here](https://github.com/hashgraph/hedera-json-rpc-relay/blob/1030-lz-setup/tools/layer-zero-example/hardhat.config.js#L60) are the official LZ endpoints. A entire list of LZ supported endpoints can be found on https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts. + +### HTS Adapter vs HTS Connector +- You could use a HTS Adapter when you already have an existing HTS token on the fly. +- You could use a HTS Connector when you want to create a new token. +- You could use a HTS Connector with the existing HTS token but you have to add the HTS Connector contract as the Supply Key of the HTS token in order to execute the needed burnToken/mintToken precompile calls. +- The main reason of using a HTS Connector instead of HTS Adapter is to avoid liquidity logic. diff --git a/test/constants.js b/test/constants.js index e189df8cc..52f0a9a2f 100644 --- a/test/constants.js +++ b/test/constants.js @@ -77,6 +77,7 @@ const Contract = { OZERC20Mock: 'OZERC20Mock', OZERC721Mock: 'OZERC721Mock', TokenCreateContract: 'TokenCreateContract', + TokenCreateOpcodeLogger: 'TokenCreateOpcodeLogger', DiamondCutFacet: 'DiamondCutFacet', Diamond: 'Diamond', DiamondInit: 'DiamondInit', @@ -205,12 +206,15 @@ const Contract = { KZGPointEvaluation: 'KZGPointEvaluation', StateRegistry: 'StateRegistry', Airdrop: 'Airdrop', + TokenReject: 'TokenReject', AliasAccountUtility: 'AliasAccountUtility', }; const CALL_EXCEPTION = 'CALL_EXCEPTION'; const CONTRACT_REVERT_EXECUTED_CODE = 3; const GAS_LIMIT_1_000_000 = { gasLimit: 1_000_000 }; +const GAS_LIMIT_2_000_000 = { gasLimit: 2_000_000 }; +const GAS_LIMIT_5_000_000 = { gasLimit: 5_000_000 }; const GAS_LIMIT_10_000_000 = { gasLimit: 10_000_000 }; const GAS_LIMIT_800000 = { gasLimit: 800000 }; const GAS_LIMIT_8000000 = { gasLimit: 8000000 }; @@ -235,6 +239,8 @@ module.exports = { CALL_EXCEPTION, CONTRACT_REVERT_EXECUTED_CODE, GAS_LIMIT_1_000_000, + GAS_LIMIT_2_000_000, + GAS_LIMIT_5_000_000, GAS_LIMIT_10_000_000, GAS_LIMIT_800000, GAS_LIMIT_8000000, @@ -252,4 +258,5 @@ module.exports = { GWEI, HTS_SYSTEM_CONTRACT_ADDRESS, HAS_SYSTEM_CONTRACT_ADDRESS, + ONE_HBAR, }; diff --git a/test/solidity/opcode-logger/OpcodeLogger.js b/test/solidity/opcode-logger/opcodeLogger.js similarity index 75% rename from test/solidity/opcode-logger/OpcodeLogger.js rename to test/solidity/opcode-logger/opcodeLogger.js index 4656b75b7..56f9070db 100644 --- a/test/solidity/opcode-logger/OpcodeLogger.js +++ b/test/solidity/opcode-logger/opcodeLogger.js @@ -1,8 +1,29 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2025 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. + * + */ + const Constants = require('../../constants'); -const {expect} = require('chai'); +const { expect, assert } = require('chai'); const hre = require('hardhat'); const fs = require('fs'); const {ethers} = hre; +const { hexToASCII } = require('../../utils') const BESU_RESULTS_JSON_PATH = __dirname + '/opcodeLoggerBesuResults.json'; const IS_BESU_NETWORK = hre.network.name === 'besu_local'; @@ -17,7 +38,7 @@ describe('@OpcodeLogger Test Suite', async function () { randomAddress = (ethers.Wallet.createRandom()).address; const factoryOpcodeLogger = await ethers.getContractFactory(Constants.Contract.OpcodeLogger); - opcodeLogger = await factoryOpcodeLogger.deploy(); + opcodeLogger = await factoryOpcodeLogger.deploy({gasLimit: 5_000_000}); await opcodeLogger.waitForDeployment(); }); @@ -599,12 +620,18 @@ describe('@OpcodeLogger Test Suite', async function () { } describe('nested calls', async function () { - let errorsExternal; + let errorsExternal, nestedContractCreateTx; before(async () => { const factoryErrorsExternal = await ethers.getContractFactory(Constants.Contract.ErrorsExternal); errorsExternal = await factoryErrorsExternal.deploy(); await errorsExternal.waitForDeployment(); + + const contractCreatorFactory = await ethers.getContractFactory(Constants.Contract.ContractCreator); + const contractCreator = await contractCreatorFactory.deploy(); + await contractCreator.waitForDeployment(); + const contractByteCode = (await hre.artifacts.readArtifact('Base')).bytecode; + nestedContractCreateTx = await contractCreator.createNewContract(contractByteCode); }); it('successful NESTED CALL to existing contract with disabledMemory, disabledStack, disabledStorage set to true', async function () { @@ -796,15 +823,69 @@ describe('@OpcodeLogger Test Suite', async function () { expect(sl.stack).to.equal(null); }); }); + + it('successful NESTED Create CALL Deploy a contract which successfully deploys another contract with disableMemory, DisableStack and disableStorage set to true', async function () { + const res = await executeDebugTraceTransaction(nestedContractCreateTx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: true + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('successful NESTED Create CALL Deploy a contract which successfully deploys another contract with disableMemory, DisableStack and disableStorage set to false', async function () { + const res = await executeDebugTraceTransaction(nestedContractCreateTx.hash, { + tracer: 'opcodeLogger', + disableStorage: false, + disableMemory: false, + disableStack: false + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.not.equal(null); + expect(sl.memory).to.not.equal(null); + expect(sl.stack).to.not.equal(null); + }); + }); }); describe('precompiles', async function () { let precompiles; + let tokenCreateContract; + let tokenCreateTx; + let tokenCreateContractAddress; + let tokenAddress; before(async () => { const factoryPrecompiles = await ethers.getContractFactory(Constants.Contract.Precompiles); precompiles = await factoryPrecompiles.deploy(); await precompiles.waitForDeployment(); + + const tokenCreateFactory = await ethers.getContractFactory(Constants.Contract.TokenCreateOpcodeLogger); + tokenCreateContract = await tokenCreateFactory.deploy(Constants.GAS_LIMIT_1_000_000); + await tokenCreateContract.waitForDeployment(); + tokenCreateTx = await tokenCreateContract.createFungibleTokenPublic( + await tokenCreateContract.getAddress(), + { + value: BigInt('10000000000000000000'), + gasLimit: 1_000_000, + } + ); + const tokenAddressReceipt = await tokenCreateTx.wait(); + tokenAddress = { tokenAddress } = tokenAddressReceipt.logs.filter( + (e) => e.fragment.name === Constants.Events.CreatedToken + )[0].args.tokenAddress; + tokenCreateContractAddress = await tokenCreateContract.getAddress(); }); it('successful ETH precompile call to 0x2 with disabledMemory, disabledStack, disabledStorage set to true', async function () { @@ -886,5 +967,237 @@ describe('@OpcodeLogger Test Suite', async function () { expect(sl.stack).to.not.equal(null); }); }); + + it('successful ETH precompile call to 0x2 with disabledStorage set to false, disabledMemory, disabledStack set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2); + await tx.wait(); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: false, + disableMemory: true, + disableStack: true + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.not.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('failing ETH precompile call to 0x2 with disabledStorage set to false, disabledMemory, disabledStack set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2, { gasLimit: 21_496 }); + await expect(tx.wait()).to.be.rejectedWith(Error); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: false, + disableMemory: true, + disableStack: true + }); + + expect(res.failed).to.be.true; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.not.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('successful ETH precompile call to 0x2 with disabledMemory set to false, disabledStorage, disabledStack set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2); + await tx.wait(); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: false, + disableStack: true + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.not.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('failing ETH precompile call to 0x2 with disabledMemory set to false, disabledStorage, disabledStack set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2, { gasLimit: 21_496 }); + await expect(tx.wait()).to.be.rejectedWith(Error); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: false, + disableStack: true + }); + + expect(res.failed).to.be.true; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.not.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('successful ETH precompile call to 0x2 with disabledStack set to false, disabledStorage, disabledMemory set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2); + await tx.wait(); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: false + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.not.equal(null); + }); + }); + + it('failing ETH precompile call to 0x2 with disabledStack set to false, disabledStorage, disabledMemory set to true', async function () { + const tx = await precompiles.modExp(5644, 3, 2, { gasLimit: 21_496 }); + await expect(tx.wait()).to.be.rejectedWith(Error); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: false + }); + + expect(res.failed).to.be.true; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.not.equal(null); + }); + }); + + it('successful tokenCreate call with disabledStorage, disabledMemory, disabledStack set to true', async function () { + const res = await executeDebugTraceTransaction(tokenCreateTx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: true + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.equal(null); + expect(sl.memory).to.equal(null); + expect(sl.stack).to.equal(null); + }); + }); + + it('successful tokenCreate call with disabledStorage, disabledMemory, disabledStack set to false', async function () { + const res = await executeDebugTraceTransaction(tokenCreateTx.hash, { + tracer: 'opcodeLogger', + disableStorage: false, + disableMemory: false, + disableStack: false + }); + + expect(res.failed).to.be.false; + expect(res.structLogs.length).to.be.greaterThan(0); + res.structLogs.map(function (sl) { + expect(sl.storage).to.not.equal(null); + expect(sl.memory).to.not.equal(null); + expect(sl.stack).to.not.equal(null); + }); + }); + + it('should not contain revert operation when GAS is depleted (insufficient)', async function () { + const tx = await tokenCreateContract.createNonFungibleTokenPublic( + tokenCreateContractAddress, + { gasLimit: 21432 } + ); + + const res = await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: true + }); + + const revertOperations = res.structLogs.filter(function (opLog) { + return opLog.op === "REVERT" + }); + expect(revertOperations.length).to.equal(0); + }); + }); + + describe('negative', async function () { + it('should fail to debug a transaction with invalid hash', async function () { + const res = await executeDebugTraceTransaction('0x0fdfb3da2d40cd9ac8776ca02c17cb4aae634d2726f5aad049ab4ce5056b1a5c', { + tracer: 'opcodeLogger', + disableStorage: true, + disableMemory: true, + disableStack: true + }); + + expect(res.failed).to.be.true; + expect(res.structLogs).to.be.empty; + }); + + it('should fail with invalid parameter value type for disableMemory, disableStack or disableStorage', async function () { + const tx = await opcodeLogger.call(opcodeLogger.target, '0xdbdf7fce'); // calling resetCounter() + await tx.wait(); + try { + await executeDebugTraceTransaction(tx.hash, { + tracer: 'opcodeLogger', + disableStorage: 'true', + disableMemory: 1, + disableStack: 0 + }); + + } catch (error) { + expect(error.name).to.equal('ProviderError'); + expect(error._isProviderError).to.be.true; + expect(error._stack).to.contain('Invalid parameter 2: Invalid tracerConfig'); + + return; + } + + assert.fail('Executing debug trace transaction with invalid parameter value types did not result in error') + }); + + it('should fail when executing debug trace transaction with incorrect tracer parameter', async function () { + const tx = await opcodeLogger.call(opcodeLogger.target, '0xdbdf7fce'); // calling resetCounter() + await tx.wait(); + const incorrectTracer = 'opcodeLogger1'; + + try { + await executeDebugTraceTransaction(tx.hash, { + tracer: incorrectTracer, + disableStorage: true, + disableMemory: true, + disableStack: true + }); + } catch (error) { + expect(error.name).to.equal('ProviderError'); + expect(error._isProviderError).to.be.true; + expect(error._stack).to.contain(`Invalid parameter 1: Invalid tracer type, value: ${incorrectTracer}`); + + return; + } + + assert.fail('Executing debug trace transaction with incorrect tracer parameter did not result in error') + }); }); }); diff --git a/test/system-contracts/hedera-token-service/hrc-904/AirdropContract.js b/test/system-contracts/hedera-token-service/hrc-904/AirdropContract.js new file mode 100644 index 000000000..d9e2bdf10 --- /dev/null +++ b/test/system-contracts/hedera-token-service/hrc-904/AirdropContract.js @@ -0,0 +1,484 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2025 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. + * + */ + +const { expect } = require('chai'); +const { ethers } = require('hardhat'); +const utils = require('../utils'); +const Constants = require('../../../constants'); + +describe('HIP904 AirdropContract Test Suite', function () { + let airdropContract; + let tokenCreateContract; + let erc20Contract; + let erc721Contract; + let tokenAddress; + let nftTokenAddress; + let signers; + let owner; + let accounts; + let contractAddresses; + + before(async function () { + signers = await ethers.getSigners(); + airdropContract = await utils.deployContract(Constants.Contract.Airdrop); + tokenCreateContract = await utils.deployContract( + Constants.Contract.TokenCreateContract + ); + erc20Contract = await utils.deployContract( + Constants.Contract.ERC20Contract + ); + erc721Contract = await utils.deployContract( + Constants.Contract.ERC721Contract + ); + owner = signers[0].address; + accounts = signers.slice(1, 3).map((s) => s.address); + + contractAddresses = [ + await airdropContract.getAddress(), + await tokenCreateContract.getAddress(), + ]; + await utils.updateAccountKeysViaHapi(contractAddresses); + + tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + nftTokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + }); + + it('should airdrop a fungible token (FT) to a single account', async function () { + const ftAmount = BigInt(1); + const receiver = signers[1].address; + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + + const initialBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver + ); + + const tx = await airdropContract.tokenAirdrop( + tokenAddress, + signers[0].address, + receiver, + ftAmount, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + + const updatedBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver + ); + expect(updatedBalance).to.equal(initialBalance + ftAmount); + }); + + it('should airdrop a non-fungible token (NFT) to a single account', async function () { + const receiver = signers[1].address; + + const serial = await utils.mintNFTToAddress( + tokenCreateContract, + nftTokenAddress + ); + + const txNFT = await airdropContract.nftAirdrop( + nftTokenAddress, + owner, + receiver, + serial, + Constants.GAS_LIMIT_5_000_000 + ); + await txNFT.wait(); + + const nftOwner = await erc721Contract.ownerOf(nftTokenAddress, serial); + expect(nftOwner).to.equal(receiver); + }); + + it('should airdrop fungible token (FT) to a single account using distribute', async function () { + const ftAmount = BigInt(1); + const receiver = signers[1].address; + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + + const initialBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver + ); + + const tx = await airdropContract.tokenAirdropDistribute( + tokenAddress, + owner, + [receiver], + ftAmount, + Constants.GAS_LIMIT_5_000_000 + ); + await tx.wait(); + + const updatedBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver + ); + expect(updatedBalance).to.equal(initialBalance + ftAmount); + }); + + it('should airdrop fungible tokens (FT) to multiple accounts', async function () { + const ftAmount = BigInt(1); + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + + const getBalances = async () => + Promise.all( + accounts.map((account) => + erc20Contract.balanceOf(tokenAddress, account) + ) + ); + + const initialBalances = await getBalances(); + + const tx = await airdropContract.tokenAirdropDistribute( + tokenAddress, + owner, + accounts, + ftAmount, + Constants.GAS_LIMIT_5_000_000 + ); + await tx.wait(); + + const updatedBalances = await getBalances(); + + updatedBalances.forEach((balance, index) => { + expect(balance).to.equal(initialBalances[index] + ftAmount); + }); + }); + + it('should airdrop non-fungible token (NFT) to a single account using distribute', async function () { + const receiver = signers[1].address; + const serial = await utils.mintNFTToAddress( + tokenCreateContract, + nftTokenAddress + ); + + const txNFT = await airdropContract.nftAirdropDistribute( + nftTokenAddress, + owner, + [receiver], + [serial], + Constants.GAS_LIMIT_5_000_000 + ); + await txNFT.wait(); + + const nftOwner = await erc721Contract.ownerOf(nftTokenAddress, serial); + expect(nftOwner).to.equal(receiver); + }); + + // TODO: Test skipped due to missing error code support in services implementation + // See: https://github.com/hashgraph/hedera-services/issues/17409 + it.skip('should airdrop non-fungible tokens (NFT) to multiple accounts', async function () { + const nftTokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + const serials = []; + serials.push( + await utils.mintNFTToAddress(tokenCreateContract, nftTokenAddress) + ); + serials.push( + await utils.mintNFTToAddress(tokenCreateContract, nftTokenAddress) + ); + + const txNFT = await airdropContract.nftAirdropDistribute( + nftTokenAddress, + owner, + accounts, + serials, + Constants.GAS_LIMIT_5_000_000 + ); + + await txNFT.wait(); + + const updatedNFTBalances = await Promise.all([ + erc721Contract.ownerOf(nftTokenAddress, serials[0]), + erc721Contract.ownerOf(nftTokenAddress, serials[1]), + ]); + + for (let i = 0; i < accounts.length; i++) { + expect(updatedNFTBalances[i]).to.equal(accounts[i]); + } + }); + + it('should airdrop 10 tokens to multiple accounts', async function () { + const ftAmount = BigInt(1); + const tokens = []; + // Every accountAmount counts as 1 transfer so 5x2=10 + for (let i = 0; i < 5; i++) { + tokens.push( + await utils.setupToken(tokenCreateContract, owner, contractAddresses) + ); + } + for (let i = 0; i < accounts.length; i++) { + const tx = await airdropContract.multipleFtAirdrop( + tokens, + owner, + accounts[i], + ftAmount, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + for (let j = 0; j < tokens.length; j++) { + const balance = await erc20Contract.balanceOf(tokens[j], accounts[i]); + expect(balance).to.equal(ftAmount); + } + } + }); + + it('should airdrop 10 NFTs to multiple accounts', async function () { + async function createNFTs(count) { + const tokens = []; + const serials = []; + for (let i = 0; i < count; i++) { + const tokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + const serial = await utils.mintNFTToAddress( + tokenCreateContract, + tokenAddress + ); + tokens.push(tokenAddress); + serials.push(serial); + } + return { tokens, serials }; + } + + async function performAirdropAndValidate(receiver, nftTokens, nftSerials) { + const tx = await airdropContract.multipleNftAirdrop( + nftTokens, + owner, + receiver, + nftSerials, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + + for (let i = 0; i < nftTokens.length; i++) { + const nftOwner = await erc721Contract.ownerOf( + nftTokens[i], + nftSerials[i] + ); + expect(nftOwner).to.equal(receiver); + } + } + + // Create and airdrop 10 NFTs to the first account + const { tokens: nftTokens1, serials: nftSerials1 } = await createNFTs(10); + await performAirdropAndValidate(accounts[0], nftTokens1, nftSerials1); + + // Create and airdrop 10 NFTs to the second account + const { tokens: nftTokens2, serials: nftSerials2 } = await createNFTs(10); + await performAirdropAndValidate(accounts[1], nftTokens2, nftSerials2); + }); + + it('should fail when the sender does not have enough balance', async function () { + const ftAmount = BigInt(100_000_000_000_000_000); + const receiver = signers[1].address; + + const tx = await airdropContract.tokenAirdrop( + tokenAddress, + signers[2].address, + receiver, + ftAmount, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('178'); // INSUFFICIENT_TOKEN_BALANCE code + }); + + it('should fail when the receiver does not have a valid account', async function () { + const invalidReceiver = '0x000000000000000000000000000000000000dead'; + const mintedTokenSerialNumber = await utils.mintNFTToAddress( + tokenCreateContract, + nftTokenAddress + ); + + const txNFT = await airdropContract.nftAirdrop( + nftTokenAddress, + owner, + invalidReceiver, + mintedTokenSerialNumber, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(txNFT.hash); + expect(responseCode).to.eq('15'); // INVALID_ACCOUNT_ID code + }); + + it('should fail when the token does not exist', async function () { + const receiver = signers[1].address; + const invalidToken = '0xdead00000000000000000000000000000000dead'; + const txNFT = await airdropContract.nftAirdrop( + invalidToken, + owner, + receiver, + 1, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(txNFT.hash); + expect(responseCode).to.eq('167'); // INVALID_TOKEN_ID code + }); + + it('should fail when the airdrop amounts are out of bounds', async function () { + const invalidAmount = BigInt(0); + const receiver = signers[1].address; + + const tx = await airdropContract.tokenAirdrop( + tokenAddress, + signers[0].address, + receiver, + invalidAmount, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('50'); // INVALID_TRANSACTION_BODY code + }); + + // TODO: The following 2 tests are skipped because they are not supported by the current implementation in services + // They do not return the correct error code and we can currently only check if they revert + // therefore they will be skipped until the implementation is updated + it.skip('should fail when 11 or more NFT airdrops are provided', async function () { + try { + const nftTokens = []; + const nftSerials = []; + for (let i = 0; i < 11; i++) { + const tokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + const serial = await utils.mintNFTToAddress( + tokenCreateContract, + tokenAddress + ); + nftTokens.push(tokenAddress); + nftSerials.push(serial); + } + + const tx = await airdropContract.multipleNftAirdrop( + nftTokens, + owner, + signers[1].address, + nftSerials, + { + gasLimit: 15_000_000, + } + ); + await tx.wait(); + expect.fail('Should revert'); + } catch (error) { + expect(error.shortMessage).to.eq('transaction execution reverted'); + } + }); + + it.skip('should fail when 11 or more token airdrops are provided', async function () { + try { + const ftAmount = BigInt(1); + const tokens = []; + for (let i = 0; i < 6; i++) { + tokens.push( + await utils.setupToken(tokenCreateContract, airdropContract, owner) + ); + } + const tx = await airdropContract.multipleFtAirdrop( + tokens, + owner, + signers[1].address, + ftAmount, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + expect.fail('Should revert'); + } catch (error) { + expect(error.shortMessage).to.eq('transaction execution reverted'); + } + }); + + it('should handle airdrop to account with no available association slots', async function () { + const ftAmount = BigInt(1); + const receiver = ethers.Wallet.createRandom().connect(ethers.provider); + await signers[0].sendTransaction({ + to: receiver.address, + value: ethers.parseEther('100'), + }); + const IHRC904AccountFacade = new ethers.Interface( + (await hre.artifacts.readArtifact('IHRC904AccountFacade')).abi + ); + + walletIHRC904AccountFacade = new ethers.Contract( + receiver.address, + IHRC904AccountFacade, + receiver + ); + + const disableAutoAssociations = + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations( + false, + { + gasLimit: 2_000_000, + } + ); + await disableAutoAssociations.wait(); + + const tx = await airdropContract.tokenAirdrop( + tokenAddress, + signers[0].address, + receiver.address, + ftAmount, + { + gasLimit: 2_000_000, + value: Constants.ONE_HBAR, + } + ); + await tx.wait(); + + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('22'); + + // The airdrop will be pending, so the balance should still be 0 + const balance = await erc20Contract.balanceOf( + tokenAddress, + receiver.address + ); + expect(balance).to.equal(0n); + }); +}); diff --git a/test/system-contracts/hedera-token-service/hrc-904/TokenRejectContract.js b/test/system-contracts/hedera-token-service/hrc-904/TokenRejectContract.js new file mode 100644 index 000000000..5ba26b2d9 --- /dev/null +++ b/test/system-contracts/hedera-token-service/hrc-904/TokenRejectContract.js @@ -0,0 +1,287 @@ +/*- + * + * Hedera Smart Contracts + * + * Copyright (C) 2025 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. + * + */ + +const { expect } = require('chai'); +const { ethers } = require('hardhat'); +const utils = require('../utils'); +const Constants = require('../../../constants'); + +describe('HIP904 TokenRejectContract Test Suite', function () { + let tokenRejectContract; + let tokenCreateContract; + let airdropContract; + let signers; + let owner; + let receiver; + let walletIHRC904AccountFacade; + let contractAddresses; + + before(async function () { + signers = await ethers.getSigners(); + tokenRejectContract = await utils.deployContract( + Constants.Contract.TokenReject + ); + tokenCreateContract = await utils.deployContract( + Constants.Contract.TokenCreateContract + ); + airdropContract = await utils.deployContract(Constants.Contract.Airdrop); + owner = signers[0].address; + + const randomWallet = ethers.Wallet.createRandom(); + const receiverPrivateKey = randomWallet.privateKey; + receiver = randomWallet.connect(ethers.provider); + + await signers[0].sendTransaction({ + to: receiver.address, + value: ethers.parseEther('100'), + }); + + contractAddresses = [ + await tokenRejectContract.getAddress(), + await tokenCreateContract.getAddress(), + await airdropContract.getAddress(), + ]; + await utils.updateAccountKeysViaHapi(contractAddresses); + + await utils.updateAccountKeysViaHapi(contractAddresses, [ + receiverPrivateKey, + ]); + + const IHRC904AccountFacade = new ethers.Interface( + (await hre.artifacts.readArtifact('IHRC904AccountFacade')).abi + ); + + walletIHRC904AccountFacade = new ethers.Contract( + receiver.address, + IHRC904AccountFacade, + receiver + ); + }); + + it('should reject tokens for a single account', async function () { + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + const receiver = signers[1]; + + const ftAmount = BigInt(1); + const airdropTx = await airdropContract.tokenAirdrop( + tokenAddress, + owner, + receiver.address, + ftAmount, + { + value: Constants.ONE_HBAR, + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations(true, { + gasLimit: 2_000_000, + }); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [tokenAddress], + [], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('22'); // SUCCESS code + }); + + it('should reject NFTs for a single account', async function () { + const nftTokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + const receiver = signers[1]; + + const serial = utils.mintNFTToAddress(tokenCreateContract, nftTokenAddress); + + const airdropTx = await airdropContract.nftAirdrop( + nftTokenAddress, + owner, + receiver.address, + serial, + { + value: Constants.ONE_HBAR, + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations(true, { + gasLimit: 2_000_000, + }); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [], + [nftTokenAddress], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('22'); // SUCCESS code + }); + + it('should reject tokens for multiple accounts', async function () { + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + const receivers = signers.slice(1, 3); + + for (const receiver of receivers) { + const airdropTx = await airdropContract.tokenAirdrop( + tokenAddress, + owner, + receiver.address, + BigInt(1), + { + value: Constants.ONE_HBAR, + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [tokenAddress], + [], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('22'); // SUCCESS code + } + }); + + it('should fail when sender does not have any associated tokens', async function () { + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations(false, { + gasLimit: 2_000_000, + }); + + const airdropTx = await airdropContract.tokenAirdrop( + tokenAddress, + owner, + receiver.address, + BigInt(1), + { + value: Constants.ONE_HBAR, + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [tokenAddress], + [], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('184'); // TOKEN_NOT_ASSOCIATED_TO_ACCOUNT code + }); + + it('should fail when sender does not have a pending airdrop', async function () { + const tokenAddress = await utils.setupToken( + tokenCreateContract, + owner, + contractAddresses + ); + const receiver = signers[1]; + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [tokenAddress], + [], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('178'); // INSUFFICIENT_TOKEN_BALANCE code + }); + + it('should fail when provided fungible token is invalid', async function () { + const invalidToken = ethers.Wallet.createRandom().address; + const nftTokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [invalidToken], + [nftTokenAddress], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('167'); // INVALID_TOKEN_ID code + }); + + it('should fail when provided NFT is invalid', async function () { + const invalidNft = ethers.Wallet.createRandom().address; + + const nftTokenAddress = await utils.setupNft( + tokenCreateContract, + owner, + contractAddresses + ); + const receiver = signers[1]; + + const serial = utils.mintNFTToAddress(tokenCreateContract, nftTokenAddress); + + const airdropTx = await airdropContract.nftAirdrop( + nftTokenAddress, + owner, + receiver.address, + serial, + { + value: Constants.ONE_HBAR, + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations(true, { + gasLimit: 2_000_000, + }); + + const tx = await tokenRejectContract.rejectTokens( + receiver.address, + [], + [invalidNft], + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('226'); // INVALID_NFT_ID code + }); +}); diff --git a/test/system-contracts/hedera-token-service/utils.js b/test/system-contracts/hedera-token-service/utils.js index 3f95f9490..ecff3fb4b 100644 --- a/test/system-contracts/hedera-token-service/utils.js +++ b/test/system-contracts/hedera-token-service/utils.js @@ -960,6 +960,16 @@ class Utils { } } + + /** + * This method fetches the transaction actions from the mirror node corresponding to the current network, + * filters the actions to find the one directed to the Hedera Token Service (HTS) system contract, + * and extracts the result data from the precompile action. The result data is converted from a BigInt + * to a string before being returned. + * + * @param {string} txHash - The transaction hash to query. + * @returns {string} - The response code as a string. + */ static async getHTSResponseCode(txHash) { const network = hre.network.name; const mirrorNodeUrl = getMirrorNodeUrl(network); @@ -968,10 +978,20 @@ class Utils { ); const precompileAction = res.data.actions.find( (x) => x.recipient === Constants.HTS_SYSTEM_CONTRACT_ADDRESS + ); return BigInt(precompileAction.result_data).toString(); } + /** + * This method fetches the transaction actions from the mirror node corresponding to the current network, + * filters the actions to find the one directed to the Hedera Account Service (HAS) system contract, + * and extracts the result data from the precompile action. The result data is converted from a BigInt + * to a string before being returned. + * + * @param {string} txHash - The transaction hash to query. + * @returns {string} - The response code as a string. + */ static async getHASResponseCode(txHash) { const network = hre.network.name; const mirrorNodeUrl = getMirrorNodeUrl(network); @@ -1030,8 +1050,7 @@ class Utils { true, true, true, - true, - true + false ); await this.associateToken( diff --git a/test/utils.js b/test/utils.js index ed639e36a..67a1d2cf4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -30,6 +30,15 @@ class Utils { static to32ByteString(str) { return str.toString(16).replace('0x', '').padStart(64, '0'); }; + + static hexToASCII(str) { + const hex = str.toString(); + let ascii = ''; + for (let n = 0; n < hex.length; n += 2) { + ascii += String.fromCharCode(parseInt(hex.substring(n, n + 2), 16)); + } + return ascii; + }; } module.exports = Utils; diff --git a/test/wrapped-tokens/WHBAR.js b/test/wrapped-tokens/WHBAR.js index ab10bbeb5..0f3fe1c52 100644 --- a/test/wrapped-tokens/WHBAR.js +++ b/test/wrapped-tokens/WHBAR.js @@ -117,6 +117,47 @@ describe('WHBAR', function() { expect(receiverBalanceAfter).to.equal(ONE_HBAR); }); + it('should be able to transferFrom', async function() { + const amount = 1; + + // create a random receiver + const receiverAddress = (ethers.Wallet.createRandom()).address; + + // create a new random signer + const newSigner = ethers.Wallet.createRandom().connect(signers[0].provider); + + // add some balance for gas covering + await (await signers[0].sendTransaction({ + to: newSigner.address, + value: ONE_HBAR_AS_WEIBAR + })).wait(); + + // deposit 1 hbar with signer[0] + await (await contract.deposit({ + value: ONE_HBAR_AS_WEIBAR + })).wait(); + + // approve the newSigner from signer[0] + await (await contract.approve(newSigner.address, amount)).wait(); + + // save the balances before + const allowanceBefore = await contract.allowance(signers[0].address, newSigner.address); + const receiverBalanceBefore = await contract.balanceOf(receiverAddress); + + // execute transferFrom with newSigner using signers[0] approval + const contractWithNewSigner = await contract.connect(newSigner); + await (await contractWithNewSigner.transferFrom(signers[0].address, receiverAddress, amount)).wait(); + + // save the balances after + const allowanceAfter = await contract.allowance(signers[0].address, newSigner.address); + const receiverBalanceAfter = await contract.balanceOf(receiverAddress); + + expect(allowanceBefore).to.equal(amount); + expect(allowanceAfter).to.equal(0); + expect(receiverBalanceBefore).to.equal(0); + expect(receiverBalanceAfter).to.equal(amount); + }); + it('should be able to approve', async function() { const receiverAddress = (ethers.Wallet.createRandom()).address; const amount = 5644; @@ -153,4 +194,30 @@ describe('WHBAR', function() { const whbarSigner0After = await contract.balanceOf(signers[0].address); expect(whbarSigner0After - whbarSigner0Before).to.equal(ONE_HBAR); }); + + it('should throw InsufficientFunds error on withdraw', async function() { + await expect(contract.withdraw(BigInt(100) * ONE_HBAR)) + .to.be.revertedWithCustomError(contract, `InsufficientFunds`); + }); + + it('should throw InsufficientAllowance error on withdraw', async function () { + const amount = 1; + const receiverAddress = (ethers.Wallet.createRandom()).address; + const newSigner = ethers.Wallet.createRandom().connect(signers[0].provider); + + // add some balance for gas covering + await (await signers[0].sendTransaction({ + to: newSigner.address, + value: ONE_HBAR_AS_WEIBAR + })).wait(); + + // deposit 1 hbar with signer[0] + await (await contract.deposit({ + value: ONE_HBAR_AS_WEIBAR + })).wait(); + + const contractWithNewSigner = await contract.connect(newSigner); + await expect(contractWithNewSigner.transferFrom(signers[0].address, receiverAddress, amount)) + .to.be.revertedWithCustomError(contractWithNewSigner, `InsufficientAllowance`); + }); });