From 3855f381198049b4d668a4118c4b6cd1137c5dd5 Mon Sep 17 00:00:00 2001 From: Maxence Raballand Date: Tue, 21 May 2024 16:49:29 +0200 Subject: [PATCH] feat: tests --- src/lib/kandel/distribution.test.ts | 0 src/lib/kandel/params.test.ts | 37 +++++++++++++++++++ src/lib/kandel/params.ts | 8 ++-- test/src/contracts/index.ts | 16 ++++++++ test/src/contracts/kandellib.bytecode.ts | 3 ++ .../contracts/smart-kandel-seeder.bytecode.ts | 3 ++ 6 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/lib/kandel/distribution.test.ts create mode 100644 src/lib/kandel/params.test.ts create mode 100644 test/src/contracts/kandellib.bytecode.ts create mode 100644 test/src/contracts/smart-kandel-seeder.bytecode.ts diff --git a/src/lib/kandel/distribution.test.ts b/src/lib/kandel/distribution.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/kandel/params.test.ts b/src/lib/kandel/params.test.ts new file mode 100644 index 0000000..737630d --- /dev/null +++ b/src/lib/kandel/params.test.ts @@ -0,0 +1,37 @@ +import { describe, it, inject, expect } from 'vitest' +import { getKandelPositionRawParams } from './params.js' +import { priceFromTick, tickFromPrice } from '../tick.js' +import { + humanPriceToRawPrice, + rawPriceToHumanPrice, +} from '../human-readable.js' + +const { wethUSDC } = inject('markets') + +describe('kandel params', () => { + it('kandel position raw params', () => { + const params = getKandelPositionRawParams({ + minPrice: 2500, + midPrice: 3000, + maxPrice: 3500, + pricePoints: 10n, + market: wethUSDC, + }) + + expect(params.pricePoints).toBe(10n) + expect(params.firstAskIndex).toBe(5n) + + const baseQuoteTickIndex0 = tickFromPrice( + humanPriceToRawPrice(2500, wethUSDC), + wethUSDC.tickSpacing, + ) + expect(params.baseQuoteTickIndex0).toBe(baseQuoteTickIndex0) + expect(params.baseQuoteTickOffset % wethUSDC.tickSpacing).toBe(0n) + + const endTick = + params.baseQuoteTickIndex0 + + params.baseQuoteTickOffset * (params.pricePoints - 1n) + const endPrice = rawPriceToHumanPrice(priceFromTick(endTick), wethUSDC) + expect(endPrice).toApproximateEqual(3500) + }) +}) diff --git a/src/lib/kandel/params.ts b/src/lib/kandel/params.ts index d15bec8..f2501d8 100644 --- a/src/lib/kandel/params.ts +++ b/src/lib/kandel/params.ts @@ -29,7 +29,7 @@ export type PositionKandelParams = { pricePoints: bigint } -function getKandelPositionRawParams( +export function getKandelPositionRawParams( params: RawKandelPositionParams, ): PositionKandelParams { const { market, pricePoints } = params @@ -90,10 +90,11 @@ export type ValidateParamsResult = { minBaseAmount: bigint minQuoteAmount: bigint minProvision: bigint + distribution: Distribution isValid: boolean } -function countBidsAndAsks(distribution: Distribution) { +export function countBidsAndAsks(distribution: Distribution) { let nBids = 0n let nAsks = 0n for (let i = 0; i < distribution.asks.length; i++) { @@ -106,7 +107,7 @@ function countBidsAndAsks(distribution: Distribution) { } } -function changeGives( +export function changeGives( distribution: Distribution, bidGives: bigint, askGives: bigint, @@ -204,5 +205,6 @@ export function validateKandelParams( minQuoteAmount, minProvision, isValid, + distribution, } } diff --git a/test/src/contracts/index.ts b/test/src/contracts/index.ts index 2b7541e..922bdcf 100644 --- a/test/src/contracts/index.ts +++ b/test/src/contracts/index.ts @@ -32,6 +32,22 @@ export async function deployERC20( }) } +export async function deploySmartKandel( + mgv: Address, + kandelGasreq: bigint, + routerProxyFactory: Address, + routerImplementation: Address, + kandelLibBytecode: Hex, + smartKandelSeederBytecode: Hex +): Promise<{kandelLib: Address, smartKandelSeeder: Address}> { + const libTx = await globalTestClient.deployContract({ + account: globalTestClient.account, + chain: globalTestClient.chain, + bytecode: kandelLibBytecode, + abi: parseAbi(["constructor()"]), + }) +} + export async function deployMangroveCore(bytecode: Hex): Promise
{ const gasprice = await globalTestClient.getGasPrice(); const res = await globalTestClient.deployContract({ diff --git a/test/src/contracts/kandellib.bytecode.ts b/test/src/contracts/kandellib.bytecode.ts new file mode 100644 index 0000000..42772fa --- /dev/null +++ b/test/src/contracts/kandellib.bytecode.ts @@ -0,0 +1,3 @@ +import { Hex } from "viem"; + +export const kandellibBytecode: Hex = "0x610ca061003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063fbbd4a651461003a575b600080fd5b61004d6100483660046109f1565b610063565b60405161005a9190610aa1565b60405180910390f35b60408051808201909152606080825260208201526000198514158061008a57506000198414155b6100d65760405162461bcd60e51b81526020600482015260186024820152774b616e64656c2f626f746847697665735661726961626c6560401b60448201526064015b60405180910390fd5b6000806100e4600285610af9565b6100ef600286610b23565b6100f99190610b37565b9050808811610109576000610113565b6101138189610b4a565b915060006101218587610b4a565b90508083111561012f578092505b5061013d9050600284610b23565b6101479088610b37565b965082871015610155578296505b808a10156101605750885b8a87101561016c578a96505b60008a881061017c576000610186565b610186888c610b4a565b828d1061019457600061019e565b61019e8d84610b4a565b6101a89190610b37565b9050806001600160401b038111156101c2576101c2610b5d565b6040519080825280602002602001820160405280156101fb57816020015b6101e86109d0565b8152602001906001900390816101e05790505b506020840152806001600160401b0381111561021957610219610b5d565b60405190808252806020026020018201604052801561025257816020015b61023f6109d0565b8152602001906001900390816102375790505b508352508a6000610263828b610b73565b61026d908c610ba3565b61027690610bcb565b905060005b838310156103625760405180606001604052808481526020018381526020016000198b146102a9578a6102b3565b6102b3848b61047c565b815250856020015182815181106102cc576102cc610be7565b602002602001018190525060006102e6600185898b6104ae565b90506040518060600160405280828152602001828e6103059190610b73565b8f6103109190610ba3565b81526000602090910152865180518490811061032e5761032e610be7565b60209081029190910101526103438c84610bfd565b925061034e82610c24565b9150508261035b90610c24565b925061027b565b89925061036f838c610b73565b610379908d610ba3565b91505b8c83101561046b5760405180606001604052808481526020018381526020016000198a146103aa57896103b4565b6103b4848c61047c565b905285518051839081106103ca576103ca610be7565b602002602001018190525060006103e4600085898b6104ae565b90506040518060600160405280828152602001828e6104039190610b73565b8f61040e9190610ba3565b61041790610bcb565b815260200160008152508660200151838151811061043757610437610be7565b602090810291909101015261044c8c84610ba3565b925061045782610c24565b9150508261046490610c24565b925061037c565b505050509998505050505050505050565b6000808061049161048c86610bcb565b61050b565b9092509050806104a18584610c3d565b901c925050505b92915050565b600060018560018111156104c4576104c4610c54565b036104ef576104d38385610b37565b90508181106104ea576104e7600183610b4a565b90505b610503565b828410610503576105008385610b4a565b90505b949350505050565b6000806105178361057d565b909250905060eb83901b60007ed89e8c075c4155dd3213326cbbcf86fd1f63f5c205dd2ad2cf44f9349b39e180830782139083050390607e1982850101908113156105655793841c9361056f565b8060000385901b94505b81607f039350505050915091565b600080600080841261058f5783610598565b61059884610bcb565b9050620d89e88111156105e75760405162461bcd60e51b81526020600482015260176024820152766d67762f6162735469636b2f6f75744f66426f756e647360481b60448201526064016100cd565b6000600182161561060a576ffff97272373d413259a46990580e21399350610612565b600160801b93505b600282161561063c576080610637856ffff2e50f5f656932ef12357cf3c7fdcb610c3d565b901c93505b6004821615610666576080610661856fffe5caca7e10e4e61c3624eaa0941ccf610c3d565b901c93505b600882161561069057608061068b856fffcb9843d60f6159c9db58835c926643610c3d565b901c93505b60108216156106ba5760806106b5856fff973b41fa98c081472e6896dfb254bf610c3d565b901c93505b60208216156106e45760806106df856fff2ea16466c96a3843ec78b326b52860610c3d565b901c93505b604082161561070e576080610709856ffe5dee046a99a2a811c461f1969c3052610c3d565b901c93505b6080821615610738576080610733856ffcbe86c7900a88aedcffc83b479aa3a3610c3d565b901c93505b61010082161561076357608061075e856ff987a7253ac413176f2b074cf7815e53610c3d565b901c93505b61020082161561078e576080610789856ff3392b0822b70005940c7a398e4b70f2610c3d565b901c93505b6104008216156107b95760806107b4856fe7159475a2c29b7443b29c7fa6e889d8610c3d565b901c93505b6108008216156107e45760806107df856fd097f3bdfd2022b8845ad8f792aa5825610c3d565b901c93505b61100082161561080f57608061080a856fa9f746462d870fdf8a65dc1f90e061e4610c3d565b901c93505b612000821615610847576080610835856fe1b0d342ada5437121767bec575e65ed610c3d565b901c9350610844600182610ba3565b90505b61400082161561087f57608061086d856fc6f84d7e5f423f66048c541550bf3e96610c3d565b901c935061087c600282610ba3565b90505b6180008216156108b75760806108a5856f9aa508b5b7a84e1c677de54f3e99bc8f610c3d565b901c93506108b4600482610ba3565b90505b620100008216156108f05760806108de856fbad5f1bdb70232cd33865244bdcc089c610c3d565b901c93506108ed600982610ba3565b90505b62020000821615610929576080610917856f885b9613d7e87aa498106fb7fa5edd37610c3d565b901c9350610926601282610ba3565b90505b62040000821615610962576080610950856f9142e0723efb884889d1f447715afacd610c3d565b901c935061095f602582610ba3565b90505b6208000082161561099b576080610989856fa4d9a773d61316918f140bd96e8e6814610c3d565b901c9350610998604b82610ba3565b90505b60008513156109bc576001848560000304019350806109b990610bcb565b90505b6109c7816080610ba3565b92505050915091565b60405180606001604052806000815260200160008152602001600081525090565b60008060008060008060008060006101208a8c031215610a1057600080fd5b505087359960208901359950604089013598606081013598506080810135975060a0810135965060c0810135955060e08101359450610100013592509050565b600081518084526020808501945080840160005b83811015610a965781518051885283810151848901526040908101519088015260609096019590820190600101610a64565b509495945050505050565b602081526000825160406020840152610abd6060840182610a50565b90506020840151601f19848303016040850152610ada8282610a50565b95945050505050565b634e487b7160e01b600052601260045260246000fd5b600082610b0857610b08610ae3565b500690565b634e487b7160e01b600052601160045260246000fd5b600082610b3257610b32610ae3565b500490565b808201808211156104a8576104a8610b0d565b818103818111156104a8576104a8610b0d565b634e487b7160e01b600052604160045260246000fd5b80820260008212600160ff1b84141615610b8f57610b8f610b0d565b81810583148215176104a8576104a8610b0d565b8082018281126000831280158216821582161715610bc357610bc3610b0d565b505092915050565b6000600160ff1b8201610be057610be0610b0d565b5060000390565b634e487b7160e01b600052603260045260246000fd5b8181036000831280158383131683831282161715610c1d57610c1d610b0d565b5092915050565b600060018201610c3657610c36610b0d565b5060010190565b80820281158282048414176104a8576104a8610b0d565b634e487b7160e01b600052602160045260246000fdfea264697066735822122075593e68f72d4bc201c22e348fa34c029c4bd0ff63fb069a0294e61aefc29e6a64736f6c63430008140033" diff --git a/test/src/contracts/smart-kandel-seeder.bytecode.ts b/test/src/contracts/smart-kandel-seeder.bytecode.ts new file mode 100644 index 0000000..5cdb3eb --- /dev/null +++ b/test/src/contracts/smart-kandel-seeder.bytecode.ts @@ -0,0 +1,3 @@ +import { Hex } from "viem"; + +export const smartKandelSeederBytecode: Hex = "0x61010060405234801561001157600080fd5b50604051615ec2380380615ec28339810160408190526100309161006a565b6001600160a01b0393841660805260a092909252821660c0521660e0526100bf565b6001600160a01b038116811461006757600080fd5b50565b6000806000806080858703121561008057600080fd5b845161008b81610052565b6020860151604087015191955093506100a381610052565b60608601519092506100b481610052565b939692955090935050565b60805160a05160c05160e051615daa61011860003960006103e201526000818160e601526103c1015260008181605d015261039f01526000818160980152818161010d015281816101a3015261037d0152615daa6000f3fe60806040523480156200001157600080fd5b5060043610620000525760003560e01c80633b49aadd146200005757806399fa5e2d1462000092578063e170fa6a14620000c9578063f5382f0314620000e0575b600080fd5b6200007f7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b620000ba7f000000000000000000000000000000000000000000000000000000000000000081565b604051620000899190620004b1565b620000ba620000da366004620004e2565b62000108565b620000ba7f000000000000000000000000000000000000000000000000000000000000000081565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635275b212856040518263ffffffff1660e01b8152600401620001599190620005ad565b6040805180830381865afa15801562000176573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019c9190620005c3565b91505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635275b212620001db8762000325565b6040518263ffffffff1660e01b8152600401620001f99190620005ad565b6040805180830381865afa15801562000216573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200023c9190620005c3565b9150506200024a826200036e565b80156200025d57506200025d816200036e565b620002ac5760405162461bcd60e51b815260206004820152601b60248201527a12d85b99195b14d95959195c8bda5b9858dd1a5d9953585c9ad95d602a1b604482015260640160405180910390fd5b620002b8858562000379565b604051633825b60160e11b81529093506001600160a01b0384169063704b6c0290620002e9903390600401620004b1565b600060405180830381600087803b1580156200030457600080fd5b505af115801562000319573d6000803e3d6000fd5b50505050505092915050565b6040805160608082018352600080835260208084018290529284015282519081018352838201516001600160a01b03908116825284511691810191909152918101519082015290565b600160ff1b16151590565b60007f0000000000000000000000000000000000000000000000000000000000000000837f0000000000000000000000000000000000000000000000000000000000000000337f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006040516200040f90620004a3565b6200042096959493929190620005e8565b604051809103906000f0801580156200043d573d6000803e3d6000fd5b509050620004566200044f8462000325565b6060902090565b60608420336001600160a01b03167f114118fd96b3092cade519057771b44dd0451af15ef6edce98175a10cbfe4da284604051620004959190620004b1565b60405180910390a492915050565b615740806200063583390190565b6001600160a01b0391909116815260200190565b80356001600160a01b0381168114620004dd57600080fd5b919050565b6000808284036080811215620004f757600080fd5b60608112156200050657600080fd5b50604051606081016001600160401b03811182821017156200053857634e487b7160e01b600052604160045260246000fd5b6040526200054684620004c5565b81526200055660208501620004c5565b6020820152604084810135908201529150606083013580151581146200057b57600080fd5b809150509250929050565b80516001600160a01b03908116835260208083015190911690830152604090810151910152565b60608101620005bd828462000586565b92915050565b60008060408385031215620005d757600080fd5b505080516020909101519092909150565b6001600160a01b0387811682526101008201906200060a602084018962000586565b86608084015280861660a084015280851660c084015280841660e08401525097965050505050505056fe6101806040523480156200001257600080fd5b506040516200574038038062005740833981016040819052620000359162000695565b60408051606081019182905263ce1821d760e01b9091526001600160a01b0384811660648301528281166084830152879187918190861663ce1821d760a48301602060405180830381865afa15801562000093573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b991906200077d565b6001600160a01b03168152602001866001600160a01b0316815260200160011515815250828282818382818181816000015133620000fd81620002b760201b60201c565b506001600160a01b0382166200015a5760405162461bcd60e51b815260206004820152601360248201527f4d67764f666665722f30784d616e67726f76650000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03918216608052811660a052602082015160009116156200018757816020015162000189565b305b604092830151151560e0526001600160a01b0390811660c05286518116610100526020870151166101205250840151610140525050606082207fa1824a64387381916c722ef6d39d525cb7c1dcbdfc58fc2dcd8cf57c061fc4e9915060405190815260200160405180910390a1505050505050506200020e846200037460201b60201c565b610100516200021d9062000481565b610120516200022c9062000481565b6001600160a01b0382811661016081905260405163ea2e085760e01b8152858316600482015291831660248301529063ea2e08579060440160408051808303816000875af115801562000283573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a99190620007b5565b50505050505050506200083e565b6001600160a01b0381166200030f5760405162461bcd60e51b815260206004820152601860248201527f416363657373436f6e74726f6c6c65642f307841646d696e0000000000000000604482015260640162000151565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a162000371816001600160e01b038216565b50565b6000546001600160a01b03163314620003d05760405162461bcd60e51b815260206004820152601860248201527f416363657373436f6e74726f6c6c65642f496e76616c69640000000000000000604482015260640162000151565b8062ffffff81168114620004275760405162461bcd60e51b815260206004820152601460248201527f4b616e64656c2f676173726571546f6f48696768000000000000000000000000604482015260640162000151565b6006805462ffffff60201b191664010000000062ffffff8416908102919091179091556040519081527fafef3ad374c0b972e3c793be825735801fa05cc4c67157d98d9a111b4027988d9060200160405180910390a15050565b6200048c8162000504565b60a0516001600160a01b0316156200037157620004b681620004ad62000569565b6000196200057a565b620003715760405162461bcd60e51b815260206004820152601d60248201527f4469726563742f526f7574657241637469766174696f6e4661696c6564000000604482015260640162000151565b6200051b816080516000196200057a60201b60201c565b620003715760405162461bcd60e51b815260206004820152601960248201527f4d67764f666665722f41637469766174696f6e4661696c656400000000000000604482015260640162000151565b60006200057560a05190565b905090565b60006200058984848462000591565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392839291881691620005f19190620007ef565b6000604051808303816000865af19150503d806000811462000630576040519150601f19603f3d011682016040523d82523d6000602084013e62000635565b606091505b5091509150818015620006635750805115806200066357508080602001905181019062000663919062000820565b9695505050505050565b6001600160a01b03811681146200037157600080fd5b805162000690816200066d565b919050565b600080600080600080868803610100811215620006b157600080fd5b8751620006be816200066d565b96506060601f1982011215620006d357600080fd5b50604051606081016001600160401b03811182821017156200070557634e487b7160e01b600052604160045260246000fd5b604052602088015162000718816200066d565b815260408801516200072a816200066d565b602082015260608801516040820152608088015190955093506200075160a0880162000683565b92506200076160c0880162000683565b91506200077160e0880162000683565b90509295509295509295565b6000602082840312156200079057600080fd5b81516200079d816200066d565b9392505050565b805180151581146200069057600080fd5b60008060408385031215620007c957600080fd5b8251620007d6816200066d565b9150620007e660208401620007a4565b90509250929050565b6000825160005b81811015620008125760208186018101518583015201620007f6565b506000920191825250919050565b6000602082840312156200083357600080fd5b6200079d82620007a4565b60805160a05160c05160e05161010051610120516101405161016051614d84620009bc60003960006107ed0152600081816103aa015281816125b5015261264701526000818161056a01528181610d2501528181610e89015281816112700152818161171001528181612024015281816123ca0152818161243a0152818161258601526125e90152600081816107b901528181610c9001528181610e02015281816111fe015281816116e50152818161204a0152818161230701528181612376015281816125570152818161261801526131700152600081816104710152818161225501526127b70152600081816107650152611fd10152600081816104d501528181610b3a0152611bde0152600081816105360152818161089d01528181610bc6015281816113a101528181611430015281816115c00152818161196501528181611a54015281816120f101528181612849015281816129c401528181612dfb0152818161327d0152818161337a015261376e0152614d846000f3fe6080604052600436106101e55760003560e01c8063100cd98d146101f15780631450acd21461020657806314ee02bd1461022657806318acf82f1461024f5780631c5a9d9c1461026f5780632380fafd1461028f57806326fab5e0146102af578063315dace3146102e457806334bd89311461030457806334be9cb6146103245780633fce15c91461036b57806346ca626b146103985780634f605c5b146103cc57806361638ed5146103df578063704b6c02146103ff5780637144df241461041f5780637692c3281461043f57806376a820e51461045f578063790532a1146104a35780637b0b5fca146104c357806398ed53401461050457806399fa5e2d146105245780639c579839146105585780639ee8a91c1461058c578063a224b5e9146105ac578063a24f2b2d146105cc578063a2e241af146105ec578063ace679021461060c578063b9c9cec21461062c578063bfc353f91461063f578063c7e1bb441461065f578063cff0ab961461067f578063d2e498fe146106f3578063e1f21c6714610713578063e4b643e314610733578063e910d67314610753578063ea0f394d14610787578063ec342ad0146107a7578063f5382f03146107db578063f851a4401461080f578063f887ea401461082d578063fcaa7e2e1461084257600080fd5b366101ec57005b600080fd5b6102046101ff3660046141a8565b610862565b005b34801561021257600080fd5b50610204610221366004614205565b61094a565b34801561023257600080fd5b5061023c60075481565b6040519081526020015b60405180910390f35b34801561025b57600080fd5b5061023c61026a366004614232565b610a78565b34801561027b57600080fd5b5061020461028a366004614262565b610b27565b34801561029b57600080fd5b5061023c6102aa366004614292565b610bc2565b3480156102bb57600080fd5b506102c4610c6d565b604080516001600160a01b03938416815292909116602083015201610246565b3480156102f057600080fd5b506102046102ff3660046142af565b610db8565b34801561031057600080fd5b5061020461031f366004614205565b610f1f565b34801561033057600080fd5b50610339610fe7565b6040805182516001600160a01b0390811682526020808501519091169082015291810151151590820152606001610246565b34801561037757600080fd5b5061038b6103863660046142f0565b61100a565b60405161024691906143a0565b3480156103a457600080fd5b5061023c7f000000000000000000000000000000000000000000000000000000000000000081565b6102046103da3660046143d9565b6110dc565b3480156103eb57600080fd5b506102046103fa36600461441c565b611197565b34801561040b57600080fd5b5061020461041a366004614262565b611324565b34801561042b57600080fd5b5061020461043a36600461443e565b611357565b34801561044b57600080fd5b5061023c61045a36600461446e565b61158c565b34801561046b57600080fd5b506104937f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610246565b3480156104af57600080fd5b506102046104be366004614498565b611641565b3480156104cf57600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b60405161024691906144ed565b34801561051057600080fd5b5061023c61051f366004614232565b611692565b34801561053057600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561056457600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561059857600080fd5b506102046105a7366004614501565b6116b6565b3480156105b857600080fd5b506102046105c7366004614205565b611736565b3480156105d857600080fd5b5061023c6105e736600461458c565b6117f4565b3480156105f857600080fd5b5061020461060736600461441c565b611800565b34801561061857600080fd5b506102046106273660046145c9565b611898565b61020461063a3660046145fd565b611933565b34801561064b57600080fd5b5061023c61065a36600461446e565b611a0e565b34801561066b57600080fd5b5061020461067a366004614679565b611a52565b34801561068b57600080fd5b506006546106be9063ffffffff8082169162ffffff600160201b82041691600160381b8204811691600160581b90041684565b6040805163ffffffff958616815262ffffff909416602085015291841691830191909152919091166060820152608001610246565b3480156106ff57600080fd5b5061023c61070e366004614232565b611b12565b34801561071f57600080fd5b5061049361072e3660046142af565b611b55565b34801561073f57600080fd5b506104f761074e366004614262565b611bdb565b34801561075f57600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561079357600080fd5b5061023c6107a236600461446e565b611c00565b3480156107b357600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b3480156107e757600080fd5b506104f77f000000000000000000000000000000000000000000000000000000000000000081565b34801561081b57600080fd5b506000546001600160a01b03166104f7565b34801561083957600080fd5b506104f7611c44565b34801561084e57600080fd5b5061020461085d366004614205565b611c55565b6000546001600160a01b031633146108955760405162461bcd60e51b815260040161088c906146b0565b60405180910390fd5b3415610910577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b60d4288346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108f657600080fd5b505af115801561090a573d6000803e3d6000fd5b50505050505b61091983611d10565b6109238282611197565b60065461094490859062ffffff600160201b8204169063ffffffff16611f21565b50505050565b6000546001600160a01b031633146109745760405162461bcd60e51b815260040161088c906146b0565b80806109ba5760405162461bcd60e51b81526020600482015260156024820152744b616e64656c2f7374657053697a65546f6f4c6f7760581b604482015260640161088c565b818163ffffffff161480156109dd5750600654600160581b900463ffffffff1682105b610a225760405162461bcd60e51b8152602060048201526016602482015275096c2dcc8cad85ee6e8cae0a6d2f4caa8dede90d2ced60531b604482015260640161088c565b6006805463ffffffff60381b1916600160381b63ffffffff8416021790556040518281527f0408193baae9f2730f7be76d9be93983ed2dd45af2305c085920b8f00c25bbcd906020015b60405180910390a15050565b600080610a83611fc7565b9050610a8e83612007565b6001600160a01b03168152610aa28361206f565b610aaa611c44565b6001600160a01b0316633247716a836040518263ffffffff1660e01b8152600401610ad59190614711565b602060405180830381865afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b16919061471f565b610b20919061474e565b9392505050565b610b30816120eb565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001615610bbf57610b7381610b6b611c44565b600019612160565b610bbf5760405162461bcd60e51b815260206004820152601d60248201527f4469726563742f526f7574657241637469766174696f6e4661696c6564000000604482015260640161088c565b50565b60007f0000000000000000000000000000000000000000000000000000000000000000336001600160a01b03821614610c0d5760405162461bcd60e51b815260040161088c906146b0565b60009150610c1f8360a0013584612175565b15610c675760405162461bcd60e51b81526020600482015260186024820152771b59dd93d999995c8bd8589bdc9d0bd9d95d11985a5b195960421b604482015260640161088c565b50919050565b6000806000610c7a611c44565b90506000610c86611fc7565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252604051637c86d5af60e11b815291925083169063f90dab5e90610cda908490600401614711565b602060405180830381865afa158015610cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1b9190614761565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168352604051637c86d5af60e11b815291955083169063f90dab5e90610d6f908490600401614711565b602060405180830381865afa158015610d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db09190614761565b925050509091565b6000546001600160a01b03163314610de25760405162461bcd60e51b815260040161088c906146b0565b6000610dec611c44565b90506000610df8611fc7565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682526040516303c71acd60e61b815291925083169063f1c6b34090610e4e908490899060040161477e565b600060405180830381600087803b158015610e6857600080fd5b505af1158015610e7c573d6000803e3d6000fd5b5050506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811683526040516303c71acd60e61b8152908416915063f1c6b34090610ed4908490889060040161477e565b600060405180830381600087803b158015610eee57600080fd5b505af1158015610f02573d6000803e3d6000fd5b505050506000831115610f1857610f1883610f1f565b5050505050565b6000546001600160a01b03163314610f495760405162461bcd60e51b815260040161088c906146b0565b8062ffffff81168114610f955760405162461bcd60e51b8152602060048201526014602482015273096c2dcc8cad85ecec2e6e4cae2a8dede90d2ced60631b604482015260640161088c565b6006805462ffffff60201b1916600160201b62ffffff8416908102919091179091556040519081527fafef3ad374c0b972e3c793be825735801fa05cc4c67157d98d9a111b4027988d90602001610a6c565b604080516060810182526000808252602082018190529181019190915290565b90565b60408051808201825260608082526020820152905163fbbd4a6560e01b8152600481018b9052602481018a905260448101899052606481018890526084810187905260a4810186905260c4810185905260e48101849052610104810183905273__$21700c02813271e276cd5b97a66397b810$__9063fbbd4a659061012401600060405180830381865af41580156110a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110ce9190810190614837565b9a9950505050505050505050565b6000546001600160a01b031633146111065760405162461bcd60e51b815260040161088c906146b0565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b82048116938301849052600160581b9091041660608201819052600754919260009261116d928b928b928b9290918b918b918b919061100a565b905061118d81836020015162ffffff16846000015163ffffffff16611f21565b5050505050505050565b6111a18282612302565b60408051600280825260608201909252600091816020015b6111c1613f6c565b8152602001906001900390816111b95790505090506111de611fc7565b816000815181106111f1576111f16148cb565b60200260200101819052507f000000000000000000000000000000000000000000000000000000000000000081600081518110611230576112306148cb565b60209081029190910101516001600160a01b039091169052611250611fc7565b81600181518110611263576112636148cb565b60200260200101819052507f0000000000000000000000000000000000000000000000000000000000000000816001815181106112a2576112a26148cb565b60209081029190910101516001600160a01b0390911690526112c2611c44565b6001600160a01b031663b8b5cc48826040518263ffffffff1660e01b81526004016112ed91906148e1565b600060405180830381600087803b15801561130757600080fd5b505af115801561131b573d6000803e3d6000fd5b50505050505050565b6000546001600160a01b0316331461134e5760405162461bcd60e51b815260040161088c906146b0565b610bbf8161248d565b6000546001600160a01b031633146113815760405162461bcd60e51b815260040161088c906146b0565b600019820361141a576040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a08231906113d69030906004016144ed565b602060405180830381865afa1580156113f3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611417919061471f565b91505b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024016020604051808303816000875af1158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a5919061492f565b6114e95760405162461bcd60e51b81526020600482015260156024820152741b59dd93d999995c8bddda5d1a191c985dd1985a5b605a1b604482015260640161088c565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114611536576040519150601f19603f3d011682016040523d82523d6000602084013e61153b565b606091505b50509050806115875760405162461bcd60e51b81526020600482015260186024820152771b59dd93d999995c8bddd95a551c985b9cd9995c91985a5b60421b604482015260640161088c565b505050565b6000806115998484611a0e565b905060006115a685612529565b604051630129e86d60e21b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906304a7a1b4906115f79084908690600401614978565b602060405180830381865afa158015611614573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611638919061471f565b95945050505050565b6000546001600160a01b0316331461166b5760405162461bcd60e51b815260040161088c906146b0565b6116758686611800565b6116808484836116b6565b61168a8282611357565b505050505050565b600061169d82611b12565b6116a683610a78565b6116b09190614993565b92915050565b6000546001600160a01b031633146116e05760405162461bcd60e51b815260040161088c906146b0565b61170b7f0000000000000000000000000000000000000000000000000000000000000000848361266f565b6115877f0000000000000000000000000000000000000000000000000000000000000000838361266f565b6000546001600160a01b031633146117605760405162461bcd60e51b815260040161088c906146b0565b808162ffffff16146117af5760405162461bcd60e51b8152602060048201526018602482015277096c2dcc8cad85ee8d2c6d69ecccce6cae8a8dede90d2ced60431b604482015260640161088c565b8060075414610bbf5760078190556040518181527f286da08673f0eb4b3843f2824fb8e3e412534a62f6094fdc8b4008cfeba4ba66906020015b60405180910390a150565b6000610b208383612844565b6000546001600160a01b0316331461182a5760405162461bcd60e51b815260040161088c906146b0565b6040517f97714c1c48a0b9a1a347710cb6a62f056f5a811d4006655e3b41959e1e72a40990600090a161185f82826001612905565b61186b82826000612905565b6040517fa9bc12cd7db30bdfe60fece3ec52cfa7c8d60e396e2ea5df439a7d458f05f9b690600090a15050565b6000546001600160a01b031633146118c25760405162461bcd60e51b815260040161088c906146b0565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b8204811693830193909352600160581b9004909116606082015261192f611915836149b3565b826020015162ffffff16836000015163ffffffff16611f21565b5050565b6000546001600160a01b0316331461195d5760405162461bcd60e51b815260040161088c906146b0565b34156119d8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b60d4288346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156119be57600080fd5b505af11580156119d2573d6000803e3d6000fd5b50505050505b6119e183611d10565b6119ea87611736565b6119f48282611197565b611a028a8a8a8989896110dc565b50505050505050505050565b60006001836001811115611a2457611a246149bf565b14611a3d57600082815260036020526040902054610b20565b50600090815260026020526040902054919050565b7f0000000000000000000000000000000000000000000000000000000000000000336001600160a01b03821614611a9b5760405162461bcd60e51b815260040161088c906146b0565b81602001356f6d67762f74726164655375636365737360801b03611ac45761094483833561294f565b6060830135611ae2611adb368690038601866149d5565b6060902090565b604080518535815260208087013590820152600080516020614d2f833981519152910160405180910390a3505050565b6000805b600154811015610c67576000611b2c848361158c565b9050611b3781612964565b611b41908461474e565b92505080611b4e906149f1565b9050611b16565b600080546001600160a01b03163314611b805760405162461bcd60e51b815260040161088c906146b0565b611b8b848484612160565b611bd15760405162461bcd60e51b81526020600482015260176024820152761b59dd93d999995c8bd85c1c1c9bdd994bd9985a5b1959604a1b604482015260640161088c565b5060019392505050565b507f000000000000000000000000000000000000000000000000000000000000000090565b60006001836001811115611c1657611c166149bf565b14611c2f57600082815260056020526040902054610b20565b50600090815260046020526040902054919050565b6000611c506000611bdb565b905090565b6000546001600160a01b03163314611c7f5760405162461bcd60e51b815260040161088c906146b0565b63040000008110611ccb5760405162461bcd60e51b8152602060048201526016602482015275096c2dcc8cad85ecec2e6e0e4d2c6caa8dede90d2ced60531b604482015260640161088c565b6006805463ffffffff191663ffffffff83161790556040518181527fdbebd814ae648f654dcc50c734aa76e55a32e96b7d85303a08e2ddf11874a0dd906020016117e9565b604080516080808201835260065463ffffffff808216845262ffffff600160201b8304166020850152600160381b8204811694840194909452600160581b90049092166060808301919091529091611d6d91908401908401614a0a565b63ffffffff16816060015163ffffffff1614611e1e576000611d956080840160608501614a0a565b905060028163ffffffff161015611dea5760405162461bcd60e51b81526020600482015260196024820152784b616e64656c2f696e76616c69645072696365506f696e747360381b604482015260640161088c565b611df98163ffffffff16612973565b6006805463ffffffff909216600160581b0263ffffffff60581b199092169190911790555b611e2e6060830160408401614a0a565b63ffffffff16816040015163ffffffff1614611e6257611e62611e576060840160408501614a0a565b63ffffffff1661094a565b611e6f6020830183614a0a565b63ffffffff1615801590611e9c5750805163ffffffff16611e936020840184614a0a565b63ffffffff1614155b15611ebc57611ebc611eb16020840184614a0a565b63ffffffff16611c55565b611ecc6040830160208401614a30565b62ffffff1615801590611eff5750806020015162ffffff16826020016020810190611ef79190614a30565b62ffffff1614155b1561192f5761192f611f176040840160208501614a30565b62ffffff16610f1f565b6040517faab0a16d4cef87072f3977d7f1c066be401e0e6486526674f5f6172d42703db190600090a1611f52613f93565b6060810183905260808101829052611f6a6000612529565b81526020840151611f7d906000836129a8565b8051611f8890612ad6565b81528351611f98906001836129a8565b6040517fac65490b93de6b3189ca1e1653852249eb8680e816c258cff6ccf73d8501d3d090600090a150505050565b611fcf613f6c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316606082015230602082015290565b6000600182600181111561201d5761201d6149bf565b14612048577f00000000000000000000000000000000000000000000000000000000000000006116b0565b7f000000000000000000000000000000000000000000000000000000000000000092915050565b60008061207b83612007565b6040516370a0823160e01b81529091506001600160a01b038216906370a08231906120aa9030906004016144ed565b602060405180830381865afa1580156120c7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b20919061471f565b612118817f0000000000000000000000000000000000000000000000000000000000000000600019612160565b610bbf5760405162461bcd60e51b81526020600482015260196024820152781359dd93d999995c8bd058dd1a5d985d1a5bdb91985a5b1959603a1b604482015260640161088c565b600061216d848484612b0e565b949350505050565b6000806121856020840184614262565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016121b091906144ed565b602060405180830381865afa1580156121cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f1919061471f565b90508381101561220a576122058185614a55565b61220d565b60005b915081156122fb57600061221f611fc7565b905061222e6020850185614262565b6001600160a01b031681526000612243611c44565b6001600160a01b031663504db8e683867f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b815260040161229293929190614a68565b6020604051808303816000875af11580156122b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d5919061471f565b9050838110156122ee576122e98185614a55565b6122f1565b60005b93505050506116b0565b5092915050565b61232e7f0000000000000000000000000000000000000000000000000000000000000000333085612bec565b6123745760405162461bcd60e51b815260206004820152601760248201527612d85b99195b0bd8985cd9551c985b9cd9995c91985a5b604a1b604482015260640161088c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600080516020614cef833981519152836040516123bd91815260200190565b60405180910390a26123f17f0000000000000000000000000000000000000000000000000000000000000000333084612bec565b6124385760405162461bcd60e51b815260206004820152601860248201527712d85b99195b0bdc5d5bdd19551c985b9cd9995c91985a5b60421b604482015260640161088c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600080516020614cef8339815191528260405161248191815260200190565b60405180910390a25050565b6001600160a01b0381166124de5760405162461bcd60e51b815260206004820152601860248201527720b1b1b2b9b9a1b7b73a3937b63632b217983c20b236b4b760411b604482015260640161088c565b600080546001600160a01b0319166001600160a01b0383161790556040517f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a1906117e99083906144ed565b612531610fe7565b6000826001811115612545576125456149bf565b146125dc5760405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000008152506116b0565b60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081525092915050565b6040516370a0823160e01b81526000906001600160a01b038516906370a082319061269e9030906004016144ed565b602060405180830381865afa1580156126bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126df919061471f565b905060006126eb611fc7565b6001600160a01b03861681529050600060001985146127215784831161271a576127158386614a55565b612795565b6000612795565b612729611c44565b6001600160a01b0316633247716a836040518263ffffffff1660e01b81526004016127549190614711565b602060405180830381865afa158015612771573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612795919061471f565b90508015612839576127a5611c44565b6001600160a01b031663504db8e683837f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b81526004016127f493929190614a68565b6020604051808303816000875af1158015612813573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612837919061471f565b505b61168a868686612cbd565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e982fb8d85856040518363ffffffff1660e01b8152600401612895929190614978565b602060405180830381865afa1580156128b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d6919061471f565b9050604881901c62ffffff166128eb82612dcb565b01602582901c6303ffffff1602620f424002949350505050565b600061291082612529565b9050835b83811015610f185760006129288483611a0e565b9050801561293e5761293c83826001612de1565b505b50612948816149f1565b9050612914565b600061295a83612e77565b610b208383612eba565b602c1c60016001607f1b031690565b60018190556040518181527f26003f10937c9ed98d59e0d595a28bc7d35537a044aeaad037fedaab24d17998906020016117e9565b8051604051631c04321560e01b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691631c043215916129f791600401614a8c565b602060405180830381865afa158015612a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a38919061471f565b90506000612a66612a4883612ecf565b8460600151612a57919061474e565b60ee84901c6101ff1690612edf565b905060005b855181101561168a576000868281518110612a8857612a886148cb565b60209081029190910181015180518183015192880192909252604080820151908801529150612ac387612abb8184611a0e565b838988612f17565b505080612acf906149f1565b9050612a6b565b612ade610fe7565b50604080516060810182526020808401516001600160a01b03908116835284511690820152918101519082015290565b6000806000856001600160a01b031663095ea7b360e01b8686604051602401612b38929190614a9a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612b769190614ad7565b6000604051808303816000865af19150503d8060008114612bb3576040519150601f19603f3d011682016040523d82523d6000602084013e612bb8565b606091505b5091509150818015612be2575080511580612be2575080806020019051810190612be2919061492f565b9695505050505050565b600081600003612bfe5750600161216d565b826001600160a01b0316846001600160a01b031603612c8f576040516370a0823160e01b815282906001600160a01b038716906370a0823190612c459088906004016144ed565b602060405180830381865afa158015612c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c86919061471f565b1015905061216d565b306001600160a01b03851603612cb157612caa858484612fc0565b905061216d565b61163885858585612fea565b6000198203612d36576040516370a0823160e01b81526001600160a01b038416906370a0823190612cf29030906004016144ed565b602060405180830381865afa158015612d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d33919061471f565b91505b612d418382846130c7565b612d835760405162461bcd60e51b815260206004820152601360248201527212d85b99195b0bdd1c985b9cd9995c91985a5b606a1b604482015260640161088c565b826001600160a01b03167f59c79d79be0fadf59fe689b6952b7ebe90201a3a1f00d4a31982377890bc604683604051612dbe91815260200190565b60405180910390a2505050565b6000603f82901c6101ff165b6103e80292915050565b604051630dcf4b9760e31b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e7a5cb890612e3490879087908790600401614af3565b6020604051808303816000875af1158015612e53573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216d919061471f565b6000612e8e612e896020840184614262565b61316c565b9050600080612e9d83856131b6565b915091506000612ead8284613376565b9050610f18838383613497565b6000612ec58361351c565b610b20838361367a565b6000602182901c6101ff16612dd7565b600080612eeb84613742565b83029050600160211b810615612f02576001612f05565b60005b60ff16602082901c0191505092915050565b83600003612f7c57604082015115612f4557612f3282613769565b509350612f4085848661388e565b610f18565b60408201819052612f5582613769565b506000604084018190528351919550612f7091908690612de1565b50612f4085848661388e565b8160400151600003612fb65760408201819052612f998285613376565b506000604083018190528251612fb0918690612de1565b50610f18565b61168a8285613376565b6000806000856001600160a01b031663a9059cbb60e01b8686604051602401612b38929190614a9a565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b179052915160009283928392918916916130509190614ad7565b6000604051808303816000865af19150503d806000811461308d576040519150601f19603f3d011682016040523d82523d6000602084013e613092565b606091505b50915091508180156130bc5750805115806130bc5750808060200190518101906130bc919061492f565b979650505050505050565b6000816000036130d957506001610b20565b306001600160a01b03841603613161576040516370a0823160e01b815282906001600160a01b038616906370a08231906131179087906004016144ed565b602060405180830381865afa158015613134573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613158919061471f565b10159050610b20565b61216d848484612fc0565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146131ae5760006116b0565b600192915050565b60006131c0613f93565b60006131d0858560600135611c00565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b8204811693830193909352600160581b90049091166060820152909150600061322587613937565b905060006132498285856040015163ffffffff16866060015163ffffffff16613973565b90506132558282611a0e565b955061326082612529565b808652604051630129e86d60e21b81526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916304a7a1b4916132b2918b90600401614978565b602060405180830381865afa1580156132cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132f3919061471f565b90506132fe81612964565b61330c9060c08a013561474e565b6040870181905260016001607f1b03101561332f5760016001607f1b0360408701525b61333c8160401b60eb1d90565b602080880191909152600160c0880152845163ffffffff166080880152939093015162ffffff166060860152509396929550919350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a84b08c88460a0015185600001518660200151876040015188606001518960800151896040518863ffffffff1660e01b81526004016133e796959493929190614b17565b6000604051808303818588803b15801561340057600080fd5b505af193505050508015613412575060015b61347f5761341e614b4e565b806308c379a0036134735750613432614b69565b8061343d5750613475565b8360c0015181906134615760405162461bcd60e51b815260040161088c9190614bf2565b5061346b81614c25565b9150506116b0565b505b3d6000803e3d6000fd5b506c1bd999995c8bdd5c19185d1959609a1b92915050565b6c1bd999995c8bdd5c19185d1959609a1b8114806134c2575080600080516020614d0f833981519152145b156134cc57505050565b8151606090208390604080517712d85b99195b0bdd5c19185d1953d999995c91985a5b195960421b815260208101859052600080516020614d2f83398151915291015b60405180910390a3505050565b60408051600280825260608201909252600091816020015b61353c613f6c565b815260200190600190039081613534579050509050613559611fc7565b8160008151811061356c5761356c6148cb565b60209081029190910181019190915261358790830183614262565b8160008151811061359a5761359a6148cb565b60209081029190910101516001600160a01b0390911690526135ba611fc7565b816001815181106135cd576135cd6148cb565b60200260200101819052508160000160200160208101906135ee9190614262565b81600181518110613601576136016148cb565b60209081029190910101516001600160a01b039091169052613621611c44565b6001600160a01b031663b8b5cc48826040518263ffffffff1660e01b815260040161364c91906148e1565b600060405180830381600087803b15801561366657600080fd5b505af115801561168a573d6000803e3d6000fd5b6000806000613688856139c2565b9150915081600014806136a257506136a081836139f5565b155b156136c0576b1bd999995c8bd99a5b1b195960a21b925050506116b0565b6040805160e0810190915261372d90806136df368990038901896149d5565b8152602081018490526040810185905260600160e088013560481c62ffffff16815260200160e088013560251c6303ffffff1681526000602082015260016040909101526060870135613376565b925061373a858585613a1e565b505092915050565b600060078211613753575060031690565b506004600382161760029190911c600119011b90565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f95902aa8460a00151856000015186602001518760400151886060015189608001516040518763ffffffff1660e01b81526004016137d9959493929190614c49565b60206040518083038185885af193505050508015613814575060408051601f3d908101601f191682019092526138119181019061471f565b60015b61387557613820614b4e565b806308c379a0036134735750613834614b69565b8061383f5750613475565b8360c0015181906138635760405162461bcd60e51b815260040161088c9190614bf2565b5061386d81614c25565b915050915091565b936c1bd999995c8bd8dc99585d1959609a1b9350915050565b60018360018111156138a2576138a26149bf565b036138cd576000818152600460209081526040808320859055848352600290915290208190556138ef565b6000818152600560209081526040808320859055848352600390915290208190555b826001811115613901576139016149bf565b60408051848152602081018490527f4414bf83296b9500de34e173e9e5b7ca010ff6de3f093002103e680a3a1051279101612dbe565b6000600282600181111561394d5761394d6149bf565b61395890600161474e565b6139629190614c79565b60018111156116b0576116b06149bf565b60006001856001811115613989576139896149bf565b036139b157613998838561474e565b90508181106139ac57612caa600183614a55565b61216d565b82841061216d576116388385614a55565b6000808260a001356139d78460800135612964565b6139e19190614a55565b9150608083013560401b60eb1d9050915091565b6000806000613a0385613aa7565b909250905080613a138584614c9b565b901c95945050505050565b6b1bd999995c8bd99a5b1b195960a21b811480613a4a57506c1bd999995c8bdd5c19185d1959609a1b81145b80613a62575080600080516020614d0f833981519152145b15613a6c57505050565b6060830135613a83611adb368690038601866149d5565b6040805185815260208101859052600080516020614d2f833981519152910161350f565b600080613ab383613b19565b909250905060eb83901b60007ed89e8c075c4155dd3213326cbbcf86fd1f63f5c205dd2ad2cf44f9349b39e180830782139083050390607e198285010190811315613b015793841c93613b0b565b8060000385901b94505b81607f039350505050915091565b6000806000808412613b2b5783613b34565b613b3484614cb2565b9050620d89e8811115613b835760405162461bcd60e51b81526020600482015260176024820152766d67762f6162735469636b2f6f75744f66426f756e647360481b604482015260640161088c565b60006001821615613ba6576ffff97272373d413259a46990580e21399350613bae565b600160801b93505b6002821615613bd8576080613bd3856ffff2e50f5f656932ef12357cf3c7fdcb614c9b565b901c93505b6004821615613c02576080613bfd856fffe5caca7e10e4e61c3624eaa0941ccf614c9b565b901c93505b6008821615613c2c576080613c27856fffcb9843d60f6159c9db58835c926643614c9b565b901c93505b6010821615613c56576080613c51856fff973b41fa98c081472e6896dfb254bf614c9b565b901c93505b6020821615613c80576080613c7b856fff2ea16466c96a3843ec78b326b52860614c9b565b901c93505b6040821615613caa576080613ca5856ffe5dee046a99a2a811c461f1969c3052614c9b565b901c93505b6080821615613cd4576080613ccf856ffcbe86c7900a88aedcffc83b479aa3a3614c9b565b901c93505b610100821615613cff576080613cfa856ff987a7253ac413176f2b074cf7815e53614c9b565b901c93505b610200821615613d2a576080613d25856ff3392b0822b70005940c7a398e4b70f2614c9b565b901c93505b610400821615613d55576080613d50856fe7159475a2c29b7443b29c7fa6e889d8614c9b565b901c93505b610800821615613d80576080613d7b856fd097f3bdfd2022b8845ad8f792aa5825614c9b565b901c93505b611000821615613dab576080613da6856fa9f746462d870fdf8a65dc1f90e061e4614c9b565b901c93505b612000821615613de3576080613dd1856fe1b0d342ada5437121767bec575e65ed614c9b565b901c9350613de0600182614cce565b90505b614000821615613e1b576080613e09856fc6f84d7e5f423f66048c541550bf3e96614c9b565b901c9350613e18600282614cce565b90505b618000821615613e53576080613e41856f9aa508b5b7a84e1c677de54f3e99bc8f614c9b565b901c9350613e50600482614cce565b90505b62010000821615613e8c576080613e7a856fbad5f1bdb70232cd33865244bdcc089c614c9b565b901c9350613e89600982614cce565b90505b62020000821615613ec5576080613eb3856f885b9613d7e87aa498106fb7fa5edd37614c9b565b901c9350613ec2601282614cce565b90505b62040000821615613efe576080613eec856f9142e0723efb884889d1f447715afacd614c9b565b901c9350613efb602582614cce565b90505b62080000821615613f37576080613f25856fa4d9a773d61316918f140bd96e8e6814614c9b565b901c9350613f34604b82614cce565b90505b6000851315613f5857600184856000030401935080613f5590614cb2565b90505b613f63816080614cce565b92505050915091565b60408051608081018252600080825260208201819052918101829052606081019190915290565b6040518060e00160405280613fa6610fe7565b815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b634e487b7160e01b600052604160045260246000fd5b606081016001600160401b038111828210171561400d5761400d613fd8565b60405250565b604081016001600160401b038111828210171561400d5761400d613fd8565b601f8201601f191681016001600160401b038111828210171561405757614057613fd8565b6040525050565b60006001600160401b0382111561407757614077613fd8565b5060051b60200190565b600082601f83011261409257600080fd5b8135602061409f8261405e565b604080516140ad8382614032565b848152606094850287018401948482019350888611156140cc57600080fd5b8488015b868110156141145781818b0312156140e85760008081fd5b83516140f381613fee565b813581528682013587820152848201358582015285529385019381016140d0565b509098975050505050505050565b60006040828403121561413457600080fd5b60405161414081614013565b90508082356001600160401b038082111561415a57600080fd5b61416686838701614081565b8352602085013591508082111561417c57600080fd5b5061418985828601614081565b6020830152505092915050565b600060808284031215610c6757600080fd5b60008060008060e085870312156141be57600080fd5b84356001600160401b038111156141d457600080fd5b6141e087828801614122565b9450506141f08660208701614196565b939693955050505060a08201359160c0013590565b60006020828403121561421757600080fd5b5035919050565b80356002811061422d57600080fd5b919050565b60006020828403121561424457600080fd5b610b208261421e565b6001600160a01b0381168114610bbf57600080fd5b60006020828403121561427457600080fd5b8135610b208161424d565b60006101408284031215610c6757600080fd5b600061014082840312156142a557600080fd5b610b20838361427f565b6000806000606084860312156142c457600080fd5b83356142cf8161424d565b925060208401356142df8161424d565b929592945050506040919091013590565b60008060008060008060008060006101208a8c03121561430f57600080fd5b505087359960208901359950604089013598606081013598506080810135975060a0810135965060c0810135955060e08101359450610100013592509050565b600081518084526020808501945080840160005b838110156143955781518051885283810151848901526040908101519088015260609096019590820190600101614363565b509495945050505050565b6020815260008251604060208401526143bc606084018261434f565b90506020840151601f19848303016040850152611638828261434f565b60008060008060008060c087890312156143f257600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b6000806040838503121561442f57600080fd5b50508035926020909101359150565b6000806040838503121561445157600080fd5b8235915060208301356144638161424d565b809150509250929050565b6000806040838503121561448157600080fd5b61448a8361421e565b946020939093013593505050565b60008060008060008060c087890312156144b157600080fd5b863595506020870135945060408701359350606087013592506080870135915060a08701356144df8161424d565b809150509295509295509295565b6001600160a01b0391909116815260200190565b60008060006060848603121561451657600080fd5b8335925060208401359150604084013561452f8161424d565b809150509250925092565b60006060828403121561454c57600080fd5b60405161455881613fee565b80915082356145668161424d565b815260208301356145768161424d565b6020820152604092830135920191909152919050565b6000806080838503121561459f57600080fd5b6145a9848461453a565b946060939093013593505050565b600060408284031215610c6757600080fd5b6000602082840312156145db57600080fd5b81356001600160401b038111156145f157600080fd5b61216d848285016145b7565b6000806000806000806000806000806101a08b8d03121561461d57600080fd5b8a35995060208b0135985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b013593506146588c60e08d01614196565b92506101608b013591506101808b013590509295989b9194979a5092959850565b600080610180838503121561468d57600080fd5b614697848461427f565b91506146a78461014085016145b7565b90509250929050565b6020808252601890820152771058d8d95cdcd0dbdb9d1c9bdb1b19590bd25b9d985b1a5960421b604082015260600190565b80516001600160a01b039081168352602080830151908401526040808301519084015260609182015116910152565b608081016116b082846146e2565b60006020828403121561473157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156116b0576116b0614738565b60006020828403121561477357600080fd5b8151610b208161424d565b60a0810161478c82856146e2565b6001600160a01b039290921660809190910152919050565b600082601f8301126147b557600080fd5b815160206147c28261405e565b604080516147d08382614032565b848152606094850287018401948482019350888611156147ef57600080fd5b8488015b868110156141145781818b03121561480b5760008081fd5b835161481681613fee565b815181528682015187820152848201518582015285529385019381016147f3565b60006020828403121561484957600080fd5b81516001600160401b038082111561486057600080fd5b908301906040828603121561487457600080fd5b60405161488081614013565b82518281111561488f57600080fd5b61489b878286016147a4565b8252506020830151828111156148b057600080fd5b6148bc878286016147a4565b60208301525095945050505050565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015614923576149108385516146e2565b92840192608092909201916001016148fd565b50909695505050505050565b60006020828403121561494157600080fd5b81518015158114610b2057600080fd5b80516001600160a01b03908116835260208083015190911690830152604090810151910152565b608081016149868285614951565b8260608301529392505050565b81810360008312801583831316838312821617156122fb576122fb614738565b60006116b03683614122565b634e487b7160e01b600052602160045260246000fd5b6000606082840312156149e757600080fd5b610b20838361453a565b600060018201614a0357614a03614738565b5060010190565b600060208284031215614a1c57600080fd5b813563ffffffff81168114610b2057600080fd5b600060208284031215614a4257600080fd5b813562ffffff81168114610b2057600080fd5b818103818111156116b0576116b0614738565b60c08101614a7682866146e2565b83608083015282151560a0830152949350505050565b606081016116b08284614951565b6001600160a01b03929092168252602082015260400190565b60005b83811015614ace578181015183820152602001614ab6565b50506000910152565b60008251614ae9818460208701614ab3565b9190910192915050565b60a08101614b018286614951565b8360608301528215156080830152949350505050565b6101008101614b268289614951565b6060820196909652608081019490945260a084019290925260c083015260e090910152919050565b600060033d11156110075760046000803e5060005160e01c90565b600060443d1015614b775790565b6040516003193d81016004833e81513d6001600160401b038083116024840183101715614ba657505050505090565b8285019150815181811115614bbe5750505050505090565b843d8701016020828501011115614bd85750505050505090565b614be760208286010187614032565b509095945050505050565b6020815260008251806020840152614c11816040850160208701614ab3565b601f01601f19169190910160400192915050565b80516020808301519190811015610c675760001960209190910360031b1b16919050565b60e08101614c578288614951565b8560608301528460808301528360a08301528260c08301529695505050505050565b600082614c9657634e487b7160e01b600052601260045260246000fd5b500690565b80820281158282048414176116b0576116b0614738565b6000600160ff1b8201614cc757614cc7614738565b5060000390565b808201828112600083128015821682158216171561373a5761373a61473856fe1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa0946d67762f77726974654f666665722f64656e736974792f746f6f4c6f7700000045b7a2e43f35c7d127ad18416b3d34235d187b2060d4050bb82bb11de272a7c3a26469706673582212202ba6a906ba1e6a91ebaf4459683056bb5dd0f54193c13b9b6bd741087965ab3c64736f6c63430008140033a264697066735822122004d9238b62ad7bdf4f311b2daac0784abe71d007430d432dbb099e66892d2d2364736f6c63430008140033"