From f1a3844f181b1f367ffb548d3d1d65fe2fb6503b Mon Sep 17 00:00:00 2001 From: Maxence Raballand Date: Wed, 26 Jun 2024 15:09:13 +0200 Subject: [PATCH] feat: Add classic kandelSeeder to tests. (#104) * feat: Add classic kandelSeeder to tests. * chore: format --------- Co-authored-by: maxencerb --- src/actions/kandel/populate.test.ts | 67 +++++++++++++++++++- src/actions/kandel/sow.test.ts | 19 +++++- src/lib/kandel/params.ts | 6 ++ src/lib/ol-key.test.ts | 59 ++++++++++++++++- test/globalSetup.ts | 12 +++- test/src/contracts/index.ts | 52 ++++++++++++++- test/src/contracts/kandel-seeder.bytecode.ts | 3 + 7 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 test/src/contracts/kandel-seeder.bytecode.ts diff --git a/src/actions/kandel/populate.test.ts b/src/actions/kandel/populate.test.ts index c0a792f..daef246 100644 --- a/src/actions/kandel/populate.test.ts +++ b/src/actions/kandel/populate.test.ts @@ -2,17 +2,18 @@ import { parseEther, parseUnits } from 'viem' import { describe, expect, inject, it } from 'vitest' import { validateKandelParams } from '~mgv/index.js' import { getClient } from '~test/src/client.js' +import { mintAndApprove } from '~test/src/contracts/index.js' import { getBook } from '../book.js' import { simulateBind, simulateDeployRouter } from '../smart-router.js' import { simulatePopulate } from './populate.js' import { simulateSow } from './sow.js' -const { smartKandelSeeder } = inject('kandel') +const { smartKandelSeeder, kandelSeeder } = inject('kandel') const { wethUSDC } = inject('markets') const actionParams = inject('mangrove') const client = getClient() -describe('populate', () => { +describe('populate smart kandel', () => { it('populates', async () => { const { request: sowReq, result: kandel } = await simulateSow( client, @@ -34,7 +35,7 @@ describe('populate', () => { pricePoints: 5n, market: wethUSDC, baseAmount: parseEther('1'), - quoteAmount: parseUnits('3000', 18), + quoteAmount: parseUnits('3000', 6), stepSize: 1n, gasreq: 350_000n, factor: 3, @@ -70,3 +71,63 @@ describe('populate', () => { await client.waitForTransactionReceipt({ hash: hash2 }) }) }) + +describe('populate kandel', () => { + it('populates', async () => { + const { request: sowReq, result: kandel } = await simulateSow( + client, + wethUSDC, + kandelSeeder, + { + account: client.account.address, + }, + ) + const hash = await client.writeContract(sowReq) + await client.waitForTransactionReceipt({ hash }) + + const book = await getBook(client, actionParams, wethUSDC) + + const { params, isValid, minProvision } = validateKandelParams({ + minPrice: 2990, + midPrice: 3000, + maxPrice: 3010, + pricePoints: 5n, + market: wethUSDC, + baseAmount: parseEther('10'), + quoteAmount: parseUnits('30000', 6), + stepSize: 1n, + gasreq: 350_000n, + factor: 3, + asksLocalConfig: book.asksConfig, + bidsLocalConfig: book.bidsConfig, + marketConfig: book.marketConfig, + deposit: true, + }) + + expect(isValid).toBe(true) + + // mint tokens and give approval to kandel + await mintAndApprove( + client, + wethUSDC.base.address, + client.account.address, + params.baseAmount || 0n, + kandel, + ) + await mintAndApprove( + client, + wethUSDC.quote.address, + client.account.address, + params.quoteAmount || 0n, + kandel, + ) + + const { request } = await simulatePopulate(client, kandel, { + ...params, + account: client.account.address, + value: minProvision, + }) + const hash2 = await client.writeContract(request) + await client.waitForTransactionReceipt({ hash: hash2 }) + }) +}) diff --git a/src/actions/kandel/sow.test.ts b/src/actions/kandel/sow.test.ts index 01e368c..0cff982 100644 --- a/src/actions/kandel/sow.test.ts +++ b/src/actions/kandel/sow.test.ts @@ -3,11 +3,11 @@ import { describe, expect, inject, it } from 'vitest' import { getClient } from '~test/src/client.js' import { simulateSow } from './sow.js' -const { smartKandelSeeder } = inject('kandel') +const { smartKandelSeeder, kandelSeeder } = inject('kandel') const { wethUSDC } = inject('markets') const client = getClient() -describe('sow', () => { +describe('sow Smart Kandel', () => { it('sows', async () => { const { request, result } = await simulateSow( client, @@ -21,3 +21,18 @@ describe('sow', () => { expect(receipt.status).toBe('success') }) }) + +describe('Sow Kandel', () => { + it('sows', async () => { + const { request, result } = await simulateSow( + client, + wethUSDC, + kandelSeeder, + {}, + ) + expect(isAddress(result)).toBe(true) + const tx = await client.writeContract(request) + const receipt = await client.waitForTransactionReceipt({ hash: tx }) + expect(receipt.status).toBe('success') + }) +}) diff --git a/src/lib/kandel/params.ts b/src/lib/kandel/params.ts index a853e15..b4269ef 100644 --- a/src/lib/kandel/params.ts +++ b/src/lib/kandel/params.ts @@ -77,6 +77,7 @@ export type RawKandelParams = RawKandelPositionParams & { asksLocalConfig: LocalConfig bidsLocalConfig: LocalConfig marketConfig: GlobalConfig + deposit?: boolean | undefined } export type KandelParams = PositionKandelParams & { @@ -84,6 +85,8 @@ export type KandelParams = PositionKandelParams & { askGives: bigint bidGives: bigint gasreq: bigint + baseAmount?: bigint | undefined + quoteAmount?: bigint | undefined } export type ValidateParamsResult = { @@ -140,6 +143,7 @@ export function validateKandelParams( asksLocalConfig, bidsLocalConfig, marketConfig, + deposit = false, } = params let distribution = createGeometricDistribution({ @@ -202,6 +206,8 @@ export function validateKandelParams( bidGives, gasreq, pricePoints, + baseAmount: deposit ? baseAmount : undefined, + quoteAmount: deposit ? quoteAmount : undefined, }, rawParams: { ...params, diff --git a/src/lib/ol-key.test.ts b/src/lib/ol-key.test.ts index ec76dad..e3f6ce0 100644 --- a/src/lib/ol-key.test.ts +++ b/src/lib/ol-key.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' import type { OLKey } from '../types/lib.js' -import { flip } from './ol-key.js' +import { flip, hash } from './ol-key.js' describe('flip', () => { it('flips the OLKey', () => { @@ -16,4 +16,61 @@ describe('flip', () => { tickSpacing: 100n, }) }) + + it('hashes the olKey', () => { + const markets = [ + { + id: '0x456cb2ca75d08a5c881c4b083a6dd4a469f35d14bd7f2279e8ea8141378ad840', + outbound_tkn: '0x999f220296b5843b2909cc5f8b4204aaca5341d8', + inbound_tkn: '0x4300000000000000000000000000000000000004', + tickSpacing: 1n, + }, + { + id: '0x8c421ef7d31aa292802bc4360219b78a45e38a40cc76d04f3f0a9fbc914cbd79', + outbound_tkn: '0x4300000000000000000000000000000000000003', + inbound_tkn: '0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34', + tickSpacing: 1n, + }, + { + id: '0x9478fa0733344acd896e7f5ffa9ee03ccab653020a2898458323ddd6b53593df', + outbound_tkn: '0x4300000000000000000000000000000000000003', + inbound_tkn: '0x4300000000000000000000000000000000000004', + tickSpacing: 1n, + }, + { + id: '0x9646f837c173ebace85f4331500010baada3c402b39fe0b42cb6a981ae4c86d0', + outbound_tkn: '0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34', + inbound_tkn: '0x4300000000000000000000000000000000000003', + tickSpacing: 1n, + }, + { + id: '0x970524a7911bd72feac6c2e9065d469de667eeb53c26dd876351b6c9eaea9a30', + outbound_tkn: '0x9a50953716ba58e3d6719ea5c437452ac578705f', + inbound_tkn: '0x4300000000000000000000000000000000000004', + tickSpacing: 1n, + }, + { + id: '0xa0d8dad9aa31ad878a583f223811d7a37f06a6f2eefaf72f6b60ef43419f9cdd', + outbound_tkn: '0x4300000000000000000000000000000000000004', + inbound_tkn: '0x4300000000000000000000000000000000000003', + tickSpacing: 1n, + }, + { + id: '0xa1dbe0263a07f9407dbe0f2b0ccfae710ce701cca7bfba9fe42227998e859403', + outbound_tkn: '0x4300000000000000000000000000000000000004', + inbound_tkn: '0x9a50953716ba58e3d6719ea5c437452ac578705f', + tickSpacing: 1n, + }, + { + id: '0xdff65bb4101d518f43ad16acfea56d37bce9a65b8ecc0de94a3e238f68a3516d', + outbound_tkn: '0x4300000000000000000000000000000000000004', + inbound_tkn: '0x999f220296b5843b2909cc5f8b4204aaca5341d8', + tickSpacing: 1n, + }, + ] as const + + for (const market of markets) { + expect(hash(market)).toEqual(market.id) + } + }) }) diff --git a/test/globalSetup.ts b/test/globalSetup.ts index 03ea3a7..363465b 100644 --- a/test/globalSetup.ts +++ b/test/globalSetup.ts @@ -7,6 +7,7 @@ import { globalTestClient } from '~test/src/client.js' import { accounts } from './src/constants.js' import { deployERC20, + deployKandelSeeder, deployMangroveCore, deployMangroveOrder, deployMangroveReader, @@ -15,6 +16,7 @@ import { openMarket, setMulticall, } from './src/contracts/index.js' +import { kandelSeederBytecode } from './src/contracts/kandel-seeder.bytecode.js' import { kandellibBytecode } from './src/contracts/kandellib.bytecode.js' import { getMangroveBytecodes } from './src/contracts/mangrove.js' import { smartKandelSeederBytecode } from './src/contracts/smart-kandel-seeder.bytecode.js' @@ -79,6 +81,13 @@ export default async function ({ provide }: GlobalSetupContext) { smartKandelSeederBytecode, ) + const kandelSeeder = await deployKandelSeeder( + mangrove, + 128_000n, + kandelLib, + kandelSeederBytecode, + ) + provide('tokens', { WETH, USDC, DAI }) provide('mangrove', { mgv: mangrove, @@ -89,7 +98,7 @@ export default async function ({ provide }: GlobalSetupContext) { multicall, tickSpacing: 60n, }) - provide('kandel', { kandelLib, smartKandelSeeder }) + provide('kandel', { kandelLib, kandelSeeder, smartKandelSeeder }) // open markets @@ -163,6 +172,7 @@ declare module 'vitest' { } kandel: { kandelLib: Address + kandelSeeder: Address smartKandelSeeder: Address } } diff --git a/test/src/contracts/index.ts b/test/src/contracts/index.ts index df7f67e..6764e4a 100644 --- a/test/src/contracts/index.ts +++ b/test/src/contracts/index.ts @@ -1,7 +1,7 @@ import { globalTestClient } from "../client.js"; import { accounts } from "../constants.js"; import { Address, Client, Hex, parseAbi } from "viem"; -import { writeContract } from "viem/actions"; +import { writeContract, waitForTransactionReceipt } from "viem/actions"; import { ERC20_ABI, ERC20_BYTECODE } from "./erc20.js"; import type { OLKey } from "~mgv/types/lib.js"; import { flip } from "~mgv/lib/ol-key.js"; @@ -32,6 +32,28 @@ export async function deployERC20( }) } +export async function deployKandelSeeder( + mgv: Address, + kandelGasreq: bigint, + kandelLib: Address, + kandelSeederBytecode: Hex +): Promise
{ + const seederTx = await globalTestClient.deployContract({ + account: globalTestClient.account, + chain: globalTestClient.chain, + bytecode: kandelSeederBytecode.replace(/__\$[a-fA-F0-9]{34}\$__/g, kandelLib.slice(2)), + abi: parseAbi([ + "constructor(address mgv, uint gasreq)", + ]), + args: [mgv, kandelGasreq], + } as any); + const seederReceipt = await globalTestClient.waitForTransactionReceipt({ + hash: seederTx, + }); + const seederAddress = seederReceipt.contractAddress; + return seederAddress; +} + export async function deploySmartKandel( mgv: Address, kandelGasreq: bigint, @@ -219,4 +241,32 @@ export async function mint( functionName: "mint", args: [to, amount], } as any); + await waitForTransactionReceipt(client, { hash: res }); +} + +export async function approve( + client: Client, + token: Address, + owner: Address, + spender: Address, + amount: bigint +) { + const res = await writeContract(client, { + address: token, + abi: ERC20_ABI, + functionName: "approve", + args: [spender, amount], + } as any); + await waitForTransactionReceipt(client, { hash: res }); +} + +export async function mintAndApprove( + client: Client, + token: Address, + to: Address, + amount: bigint, + spender: Address +) { + await mint(client, token, to, amount) + await approve(client, token, to, spender, amount) } diff --git a/test/src/contracts/kandel-seeder.bytecode.ts b/test/src/contracts/kandel-seeder.bytecode.ts new file mode 100644 index 0000000..c6d20fd --- /dev/null +++ b/test/src/contracts/kandel-seeder.bytecode.ts @@ -0,0 +1,3 @@ +import { Hex } from "viem"; + +export const kandelSeederBytecode: Hex = '0x60c060405234801561001057600080fd5b506040516156f83803806156f883398101604081905261002f91610045565b6001600160a01b0390911660805260a05261007f565b6000806040838503121561005857600080fd5b82516001600160a01b038116811461006f57600080fd5b6020939093015192949293505050565b60805160a05161563a6100be6000396000818160510152610392015260008181608c015281816101140152818161018a0152610370015261563a6000f3fe60806040523480156200001157600080fd5b5060043610620000465760003560e01c80633b49aadd146200004b57806399fa5e2d1462000086578063e170fa6a14620000c7575b600080fd5b620000737f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b620000ae7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016200007d565b620000ae620000d836600462000476565b6040805163293ad90960e11b815283516001600160a01b03908116600483015260208501518116602483015291840151604482015260009182917f000000000000000000000000000000000000000000000000000000000000000090911690635275b212906064016040805180830381865afa1580156200015d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018391906200051b565b91505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635275b212620001c28762000323565b604080516001600160e01b031960e085901b16815282516001600160a01b039081166004830152602084015116602482015291015160448201526064016040805180830381865afa1580156200021c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200024291906200051b565b915050600160ff1b821615158015620002605750600160ff1b811615155b620002b15760405162461bcd60e51b815260206004820152601b60248201527f4b616e64656c5365656465722f696e6163746976654d61726b65740000000000604482015260640160405180910390fd5b620002bd85856200036c565b604051633825b60160e11b81523360048201529093506001600160a01b0384169063704b6c0290602401600060405180830381600087803b1580156200030257600080fd5b505af115801562000317573d6000803e3d6000fd5b50505050505092915050565b6040805160608082018352600080835260208084018290529284015282519081018352838201516001600160a01b03908116825284511691810191909152918101519082015290565b60007f0000000000000000000000000000000000000000000000000000000000000000837f0000000000000000000000000000000000000000000000000000000000000000604051620003bf906200044b565b620003cd9392919062000540565b604051809103906000f080158015620003ea573d6000803e3d6000fd5b50905062000403620003fc8462000323565b6060902090565b606084206040516001600160a01b038416815233907f0a1a61147c22f919c9109e36ac0663eda48f5ad4ad1b3203059bfd6970d3d8bd9060200160405180910390a492915050565b615076806200058f83390190565b80356001600160a01b03811681146200047157600080fd5b919050565b60008082840360808112156200048b57600080fd5b60608112156200049a57600080fd5b506040516060810181811067ffffffffffffffff82111715620004cd57634e487b7160e01b600052604160045260246000fd5b604052620004db8462000459565b8152620004eb6020850162000459565b6020820152604084810135908201529150606083013580151581146200051057600080fd5b809150509250929050565b600080604083850312156200052f57600080fd5b505080516020909101519092909150565b6001600160a01b038416815260a0810162000580602083018580516001600160a01b03908116835260208083015190911690830152604090810151910152565b82608083015294935050505056fe6101606040523480156200001257600080fd5b50604051620050763803806200507683398101604081905262000035916200057f565b82826200005b604080516060810182526000808252602082018190529181019190915290565b8282828183828181818160000151336200007b81620001b360201b60201c565b506001600160a01b038216620000d85760405162461bcd60e51b815260206004820152601360248201527f4d67764f666665722f30784d616e67726f76650000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03918216608052811660a052602082015160009116156200010557816020015162000107565b305b604092830151151560e0526001600160a01b0390811660c05286518116610100526020870151166101205250840151610140525050606082207fa1824a64387381916c722ef6d39d525cb7c1dcbdfc58fc2dcd8cf57c061fc4e9915060405190815260200160405180910390a1505050505050506200018c816200027060201b60201c565b610100516200019b906200037d565b61012051620001aa906200037d565b5050506200068c565b6001600160a01b0381166200020b5760405162461bcd60e51b815260206004820152601860248201527f416363657373436f6e74726f6c6c65642f307841646d696e00000000000000006044820152606401620000cf565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a16200026d816001600160e01b038216565b50565b6000546001600160a01b03163314620002cc5760405162461bcd60e51b815260206004820152601860248201527f416363657373436f6e74726f6c6c65642f496e76616c696400000000000000006044820152606401620000cf565b8062ffffff81168114620003235760405162461bcd60e51b815260206004820152601460248201527f4b616e64656c2f676173726571546f6f486967680000000000000000000000006044820152606401620000cf565b6006805462ffffff60201b191664010000000062ffffff8416908102919091179091556040519081527fafef3ad374c0b972e3c793be825735801fa05cc4c67157d98d9a111b4027988d9060200160405180910390a15050565b620003888162000400565b60a0516001600160a01b0316156200026d57620003b281620003a962000465565b60001962000476565b6200026d5760405162461bcd60e51b815260206004820152601d60248201527f4469726563742f526f7574657241637469766174696f6e4661696c65640000006044820152606401620000cf565b62000417816080516000196200047660201b60201c565b6200026d5760405162461bcd60e51b815260206004820152601960248201527f4d67764f666665722f41637469766174696f6e4661696c6564000000000000006044820152606401620000cf565b60006200047160a05190565b905090565b6000620004858484846200048d565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392839291881691620004ed919062000630565b6000604051808303816000865af19150503d80600081146200052c576040519150601f19603f3d011682016040523d82523d6000602084013e62000531565b606091505b50915091508180156200055f5750805115806200055f5750808060200190518101906200055f919062000661565b9695505050505050565b6001600160a01b03811681146200026d57600080fd5b600080600083850360a08112156200059657600080fd5b8451620005a38162000569565b93506060601f1982011215620005b857600080fd5b50604051606081016001600160401b0381118282101715620005ea57634e487b7160e01b600052604160045260246000fd5b6040526020850151620005fd8162000569565b815260408501516200060f8162000569565b60208201526060850151604082015260809094015192959394509192915050565b6000825160005b8181101562000653576020818601810151858301520162000637565b506000920191825250919050565b6000602082840312156200067457600080fd5b815180151581146200068557600080fd5b9392505050565b60805160a05160c05160e05161010051610120516101405161487e620007f8600039600081816103ad0152818161227c015261230e01526000818161057801528181610f8d015281816110020152818161145301528181611d530152818161224d01526122b00152600081816107e701528181610eb201528181610f270152818161142801528181611d790152818161221e015281816122df0152612b5f0152600081816104740152611fb601526000818161079301528181611f8801528181612ff101526130e20152600081816104d80152818161075f0152818161083601528181610b2e01528181611e1901528181611f220152613185015260008181610544015281816108b501528181610ba8015281816110e20152818161116e01528181611303015281816116ad0152818161179c01528181611da401528181612444015281816125b70152818161299501528181612c6c01528181612d6d01526132f2015261487e6000f3fe6080604052600436106102345760003560e01c806399fa5e2d1161012e578063cff0ab96116100ab578063ea0f394d1161006f578063ea0f394d146107b5578063ec342ad0146107d5578063f851a44014610809578063f887ea4014610827578063fcaa7e2e1461085a57600080fd5b8063cff0ab961461068d578063d2e498fe14610701578063e1f21c6714610721578063e4b643e314610741578063e910d6731461078157600080fd5b8063a2e241af116100f2578063a2e241af146105fa578063ace679021461061a578063b9c9cec21461063a578063bfc353f91461064d578063c7e1bb441461066d57600080fd5b806399fa5e2d146105325780639c579839146105665780639ee8a91c1461059a578063a224b5e9146105ba578063a24f2b2d146105da57600080fd5b806346ca626b116101bc5780637692c328116101805780637692c3281461044257806376a820e514610462578063790532a1146104a65780637b0b5fca146104c657806398ed53401461051257600080fd5b806346ca626b1461039b5780634f605c5b146103cf57806361638ed5146103e2578063704b6c02146104025780637144df241461042257600080fd5b80631c5a9d9c116102035780631c5a9d9c146102be5780632380fafd146102de57806334bd8931146102fe57806334be9cb61461031e5780633fce15c91461036e57600080fd5b8063100cd98d146102405780631450acd21461025557806314ee02bd1461027557806318acf82f1461029e57600080fd5b3661023b57005b600080fd5b61025361024e366004613d4b565b61087a565b005b34801561026157600080fd5b50610253610270366004613da9565b610962565b34801561028157600080fd5b5061028b60075481565b6040519081526020015b60405180910390f35b3480156102aa57600080fd5b5061028b6102b9366004613dd6565b610a94565b3480156102ca57600080fd5b506102536102d9366004613e06565b610b12565b3480156102ea57600080fd5b5061028b6102f9366004613e36565b610ba4565b34801561030a57600080fd5b50610253610319366004613da9565b610c54565b34801561032a57600080fd5b50604080516060808201835260008083526020808401828152938501828152855192835293516001600160a01b031690820152915115159282019290925201610295565b34801561037a57600080fd5b5061038e610389366004613e53565b610d20565b6040516102959190613f03565b3480156103a757600080fd5b5061028b7f000000000000000000000000000000000000000000000000000000000000000081565b6102536103dd366004613f3c565b610df2565b3480156103ee57600080fd5b506102536103fd366004613f7f565b610ead565b34801561040e57600080fd5b5061025361041d366004613e06565b611067565b34801561042e57600080fd5b5061025361043d366004613fa1565b61109a565b34801561044e57600080fd5b5061028b61045d366004613fd1565b6112cf565b34801561046e57600080fd5b506104967f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610295565b3480156104b257600080fd5b506102536104c1366004613ffb565b611384565b3480156104d257600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610295565b34801561051e57600080fd5b5061028b61052d366004613dd6565b6113d5565b34801561053e57600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561057257600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105a657600080fd5b506102536105b5366004614050565b6113f9565b3480156105c657600080fd5b506102536105d5366004613da9565b611479565b3480156105e657600080fd5b5061028b6105f53660046140db565b61153c565b34801561060657600080fd5b50610253610615366004613f7f565b611548565b34801561062657600080fd5b50610253610635366004614118565b6115e0565b61025361064836600461414d565b61167b565b34801561065957600080fd5b5061028b610668366004613fd1565b611756565b34801561067957600080fd5b506102536106883660046141c9565b61179a565b34801561069957600080fd5b506006546106cc9063ffffffff8082169162ffffff600160201b82041691600160381b8204811691600160581b90041684565b6040805163ffffffff958616815262ffffff909416602085015291841691830191909152919091166060820152608001610295565b34801561070d57600080fd5b5061028b61071c366004613dd6565b61186c565b34801561072d57600080fd5b5061049661073c366004614200565b6118b3565b34801561074d57600080fd5b506104fa61075c366004613e06565b507f000000000000000000000000000000000000000000000000000000000000000090565b34801561078d57600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107c157600080fd5b5061028b6107d0366004613fd1565b61193f565b3480156107e157600080fd5b506104fa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561081557600080fd5b506000546001600160a01b03166104fa565b34801561083357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006104fa565b34801561086657600080fd5b50610253610875366004613da9565b611983565b6000546001600160a01b031633146108ad5760405162461bcd60e51b81526004016108a490614241565b60405180910390fd5b3415610928577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b60d4288346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561090e57600080fd5b505af1158015610922573d6000803e3d6000fd5b50505050505b61093183611a3e565b61093b8282610ead565b60065461095c90859062ffffff600160201b8204169063ffffffff16611c53565b50505050565b6000546001600160a01b0316331461098c5760405162461bcd60e51b81526004016108a490614241565b80806109d25760405162461bcd60e51b81526020600482015260156024820152744b616e64656c2f7374657053697a65546f6f4c6f7760581b60448201526064016108a4565b818163ffffffff161480156109f55750600654600160581b900463ffffffff1682105b610a3a5760405162461bcd60e51b8152602060048201526016602482015275096c2dcc8cad85ee6e8cae0a6d2f4caa8dede90d2ced60531b60448201526064016108a4565b600680546affffffff000000000000001916600160381b63ffffffff8416021790556040518281527f0408193baae9f2730f7be76d9be93983ed2dd45af2305c085920b8f00c25bbcd906020015b60405180910390a15050565b600080610aa083611d36565b6040516370a0823160e01b81523060048201529091506001600160a01b038216906370a0823190602401602060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0b9190614278565b9392505050565b610b1b81611d9e565b610b23611e17565b15610ba157610b55817f0000000000000000000000000000000000000000000000000000000000000000600019611e46565b610ba15760405162461bcd60e51b815260206004820152601d60248201527f4469726563742f526f7574657241637469766174696f6e4661696c656400000060448201526064016108a4565b50565b60007f0000000000000000000000000000000000000000000000000000000000000000336001600160a01b03821614610bef5760405162461bcd60e51b81526004016108a490614241565b60009150610c018360a0013584611e5b565b15610c4e5760405162461bcd60e51b815260206004820152601860248201527f6d67764f666665722f61626f72742f6765744661696c6564000000000000000060448201526064016108a4565b50919050565b6000546001600160a01b03163314610c7e5760405162461bcd60e51b81526004016108a490614241565b8062ffffff81168114610cca5760405162461bcd60e51b8152602060048201526014602482015273096c2dcc8cad85ecec2e6e4cae2a8dede90d2ced60631b60448201526064016108a4565b6006805466ffffff000000001916600160201b62ffffff8416908102919091179091556040519081527fafef3ad374c0b972e3c793be825735801fa05cc4c67157d98d9a111b4027988d90602001610a88565b90565b60408051808201825260608082526020820152905163fbbd4a6560e01b8152600481018b9052602481018a905260448101899052606481018890526084810187905260a4810186905260c4810185905260e48101849052610104810183905273__$21700c02813271e276cd5b97a66397b810$__9063fbbd4a659061012401600060405180830381865af4158015610dbc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610de49190810190614324565b9a9950505050505050505050565b6000546001600160a01b03163314610e1c5760405162461bcd60e51b81526004016108a490614241565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b82048116938301849052600160581b90910416606082018190526007549192600092610e83928b928b928b9290918b918b918b9190610d20565b9050610ea381836020015162ffffff16846000015163ffffffff16611c53565b5050505050505050565b610ed97f0000000000000000000000000000000000000000000000000000000000000000333085612064565b610f255760405162461bcd60e51b815260206004820152601760248201527f4b616e64656c2f626173655472616e736665724661696c00000000000000000060448201526064016108a4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa09483604051610f8091815260200190565b60405180910390a2610fb47f0000000000000000000000000000000000000000000000000000000000000000333084612064565b6110005760405162461bcd60e51b815260206004820152601860248201527f4b616e64656c2f71756f74655472616e736665724661696c000000000000000060448201526064016108a4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa0948260405161105b91815260200190565b60405180910390a25050565b6000546001600160a01b031633146110915760405162461bcd60e51b81526004016108a490614241565b610ba181612133565b6000546001600160a01b031633146110c45760405162461bcd60e51b81526004016108a490614241565b6000198203611158576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611131573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111559190614278565b91505b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024016020604051808303816000875af11580156111bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e391906143b9565b6112275760405162461bcd60e51b81526020600482015260156024820152741b59dd93d999995c8bddda5d1a191c985dd1985a5b605a1b60448201526064016108a4565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114611274576040519150601f19603f3d011682016040523d82523d6000602084013e611279565b606091505b50509050806112ca5760405162461bcd60e51b815260206004820152601860248201527f6d67764f666665722f7765695472616e736665724661696c000000000000000060448201526064016108a4565b505050565b6000806112dc8484611756565b905060006112e9856121dd565b604051630129e86d60e21b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906304a7a1b49061133a9084908690600401614402565b602060405180830381865afa158015611357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137b9190614278565b95945050505050565b6000546001600160a01b031633146113ae5760405162461bcd60e51b81526004016108a490614241565b6113b88686611548565b6113c38484836113f9565b6113cd828261109a565b505050505050565b60006113e08261186c565b6113e983610a94565b6113f39190614433565b92915050565b6000546001600160a01b031633146114235760405162461bcd60e51b81526004016108a490614241565b61144e7f00000000000000000000000000000000000000000000000000000000000000008483612336565b6112ca7f00000000000000000000000000000000000000000000000000000000000000008383612336565b6000546001600160a01b031633146114a35760405162461bcd60e51b81526004016108a490614241565b808162ffffff16146114f75760405162461bcd60e51b815260206004820152601860248201527f4b616e64656c2f7469636b4f6666736574546f6f48696768000000000000000060448201526064016108a4565b8060075414610ba15760078190556040518181527f286da08673f0eb4b3843f2824fb8e3e412534a62f6094fdc8b4008cfeba4ba66906020015b60405180910390a150565b6000610b0b838361243f565b6000546001600160a01b031633146115725760405162461bcd60e51b81526004016108a490614241565b6040517f97714c1c48a0b9a1a347710cb6a62f056f5a811d4006655e3b41959e1e72a40990600090a16115a782826001612500565b6115b382826000612500565b6040517fa9bc12cd7db30bdfe60fece3ec52cfa7c8d60e396e2ea5df439a7d458f05f9b690600090a15050565b6000546001600160a01b0316331461160a5760405162461bcd60e51b81526004016108a490614241565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b8204811693830193909352600160581b9004909116606082015261167761165d8361445a565b826020015162ffffff16836000015163ffffffff16611c53565b5050565b6000546001600160a01b031633146116a55760405162461bcd60e51b81526004016108a490614241565b3415611720577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b60d4288346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561170657600080fd5b505af115801561171a573d6000803e3d6000fd5b50505050505b61172983611a3e565b61173287611479565b61173c8282610ead565b61174a8a8a8a898989610df2565b50505050505050505050565b6000600183600181111561176c5761176c614466565b1461178557600082815260036020526040902054610b0b565b50600090815260026020526040902054919050565b7f0000000000000000000000000000000000000000000000000000000000000000336001600160a01b038216146117e35760405162461bcd60e51b81526004016108a490614241565b81602001356f6d67762f74726164655375636365737360801b0361180c5761095c838335612551565b606083013561182a6118233686900386018661447c565b6060902090565b6040805185358152602080870135908201527f45b7a2e43f35c7d127ad18416b3d34235d187b2060d4050bb82bb11de272a7c3910160405180910390a3505050565b6000805b600154811015610c4e57600061188684836112cf565b905061189f60016001607f1b03602c83901c1684614498565b925050806118ac906144ab565b9050611870565b600080546001600160a01b031633146118de5760405162461bcd60e51b81526004016108a490614241565b6118e9848484611e46565b6119355760405162461bcd60e51b815260206004820152601760248201527f6d67764f666665722f617070726f76652f6661696c656400000000000000000060448201526064016108a4565b5060019392505050565b6000600183600181111561195557611955614466565b1461196e57600082815260056020526040902054610b0b565b50600090815260046020526040902054919050565b6000546001600160a01b031633146119ad5760405162461bcd60e51b81526004016108a490614241565b630400000081106119f95760405162461bcd60e51b8152602060048201526016602482015275096c2dcc8cad85ecec2e6e0e4d2c6caa8dede90d2ced60531b60448201526064016108a4565b6006805463ffffffff191663ffffffff83161790556040518181527fdbebd814ae648f654dcc50c734aa76e55a32e96b7d85303a08e2ddf11874a0dd90602001611531565b604080516080808201835260065463ffffffff808216845262ffffff600160201b8304166020850152600160381b8204811694840194909452600160581b90049092166060808301919091529091611a9b919084019084016144c4565b63ffffffff16816060015163ffffffff1614611b50576000611ac360808401606085016144c4565b905060028163ffffffff161015611b1c5760405162461bcd60e51b815260206004820152601960248201527f4b616e64656c2f696e76616c69645072696365506f696e74730000000000000060448201526064016108a4565b611b2b8163ffffffff16612566565b6006805463ffffffff909216600160581b0263ffffffff60581b199092169190911790555b611b6060608301604084016144c4565b63ffffffff16816040015163ffffffff1614611b9457611b94611b8960608401604085016144c4565b63ffffffff16610962565b611ba160208301836144c4565b63ffffffff1615801590611bce5750805163ffffffff16611bc560208401846144c4565b63ffffffff1614155b15611bee57611bee611be360208401846144c4565b63ffffffff16611983565b611bfe60408301602084016144ea565b62ffffff1615801590611c315750806020015162ffffff16826020016020810190611c2991906144ea565b62ffffff1614155b1561167757611677611c4960408401602085016144ea565b62ffffff16610c54565b6040517faab0a16d4cef87072f3977d7f1c066be401e0e6486526674f5f6172d42703db190600090a1611c84613b1c565b6060810183905260808101829052611c9c60006121dd565b81526020840151611caf9060008361259b565b80516040805160608082018352600080835260208084018290529284015282519081018352818401516001600160a01b03908116825284511691810191909152918101519082015281528351611d079060018361259b565b6040517fac65490b93de6b3189ca1e1653852249eb8680e816c258cff6ccf73d8501d3d090600090a150505050565b60006001826001811115611d4c57611d4c614466565b14611d77577f00000000000000000000000000000000000000000000000000000000000000006113f3565b7f000000000000000000000000000000000000000000000000000000000000000092915050565b611dcb817f0000000000000000000000000000000000000000000000000000000000000000600019611e46565b610ba15760405162461bcd60e51b815260206004820152601960248201527f4d67764f666665722f41637469766174696f6e4661696c65640000000000000060448201526064016108a4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316151590565b6000611e538484846126c9565b949350505050565b600080611e6b6020840184613e06565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015611eb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed59190614278565b9050600084821015611ef057611eeb828661450f565b611ef3565b60005b9050611efd611e17565b611f0a5791506113f39050565b60408051608081019091526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063504db8e69080611f5760208a018a613e06565b6001600160a01b03168152602001611f77611823368b90038b018b61447c565b8152602001886060013581526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250847f00000000000000000000000000000000000000000000000000000000000000006040518463ffffffff1660e01b8152600401611ff393929190614522565b6020604051808303816000875af1158015612012573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120369190614278565b90508181101561204f5761204a818361450f565b612052565b60005b93505050506113f3565b505092915050565b60008160000361207657506001611e53565b826001600160a01b0316846001600160a01b031603612105576040516370a0823160e01b81526001600160a01b0385811660048301528391908716906370a0823190602401602060405180830381865afa1580156120d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120fc9190614278565b10159050611e53565b306001600160a01b03851603612127576121208584846127af565b9050611e53565b61137b858585856127e5565b6001600160a01b0381166121895760405162461bcd60e51b815260206004820152601860248201527f416363657373436f6e74726f6c6c65642f307841646d696e000000000000000060448201526064016108a4565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a150565b604080516060810182526000808252602082018190529181018290529082600181111561220c5761220c614466565b146122a35760405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000008152506113f3565b60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000081525092915050565b60001982036123aa576040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015612383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a79190614278565b91505b6123b58382846128c2565b6123f75760405162461bcd60e51b815260206004820152601360248201527212d85b99195b0bdd1c985b9cd9995c91985a5b606a1b60448201526064016108a4565b826001600160a01b03167f59c79d79be0fadf59fe689b6952b7ebe90201a3a1f00d4a31982377890bc60468360405161243291815260200190565b60405180910390a2505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e982fb8d85856040518363ffffffff1660e01b8152600401612490929190614402565b602060405180830381865afa1580156124ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d19190614278565b9050604881901c62ffffff166124e682612965565b01602582901c6303ffffff1602620f424002949350505050565b600061250b826121dd565b9050835b8381101561254a5760006125238483611756565b90508015612539576125378382600161297b565b505b50612543816144ab565b905061250f565b5050505050565b600061255c83612a11565b610b0b8383612a54565b60018190556040518181527f26003f10937c9ed98d59e0d595a28bc7d35537a044aeaad037fedaab24d1799890602001611531565b8051604051631c04321560e01b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691631c043215916125ea91600401614570565b602060405180830381865afa158015612607573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262b9190614278565b9050600061265961263b83612a69565b846060015161264a9190614498565b60ee84901c6101ff1690612a79565b905060005b85518110156113cd57600086828151811061267b5761267b61457e565b602090810291909101810151805181830151928801929092526040808201519088015291506126b6876126ae8184611756565b838988612ab2565b5050806126c2906144ab565b905061265e565b6040516001600160a01b03838116602483015260448201839052600091829182919087169063095ea7b360e01b906064015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161273991906145b8565b6000604051808303816000865af19150503d8060008114612776576040519150601f19603f3d011682016040523d82523d6000602084013e61277b565b606091505b50915091508180156127a55750805115806127a55750808060200190518101906127a591906143b9565b9695505050505050565b6040516001600160a01b03838116602483015260448201839052600091829182919087169063a9059cbb60e01b906064016126fb565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839283929189169161284b91906145b8565b6000604051808303816000865af19150503d8060008114612888576040519150601f19603f3d011682016040523d82523d6000602084013e61288d565b606091505b50915091508180156128b75750805115806128b75750808060200190518101906128b791906143b9565b979650505050505050565b6000816000036128d457506001610b0b565b306001600160a01b0384160361295a576040516370a0823160e01b81526001600160a01b0384811660048301528391908616906370a0823190602401602060405180830381865afa15801561292d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129519190614278565b10159050610b0b565b611e538484846127af565b6000603f82901c6101ff165b6103e80292915050565b604051630dcf4b9760e31b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e7a5cb8906129ce908790879087906004016145d4565b6020604051808303816000875af11580156129ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e539190614278565b6000612a28612a236020840184613e06565b612b5b565b9050600080612a378385612ba5565b915091506000612a478284612d69565b905061254a838383612e8a565b6000612a5f83612f38565b610b0b8383613206565b6000602182901c6101ff16612971565b600080612a85846132c6565b83029050640200000000810615612a9d576001612aa0565b60005b60ff16602082901c0191505092915050565b83600003612b1757604082015115612ae057612acd826132ed565b509350612adb858486613412565b61254a565b60408201819052612af0826132ed565b506000604084018190528351919550612b0b9190869061297b565b50612adb858486613412565b8160400151600003612b515760408201819052612b348285612d69565b506000604083018190528251612b4b91869061297b565b5061254a565b6113cd8285612d69565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614612b9d5760006113f3565b600192915050565b6000612baf613b1c565b6000612bbf85856060013561193f565b6040805160808101825260065463ffffffff808216835262ffffff600160201b8304166020840152600160381b8204811693830193909352600160581b900490911660608201529091506000612c14876134bb565b90506000612c388285856040015163ffffffff16866060015163ffffffff166134f7565b9050612c448282611756565b9550612c4f826121dd565b808652604051630129e86d60e21b81526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916304a7a1b491612ca1918b90600401614402565b602060405180830381865afa158015612cbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce29190614278565b9050612cff60016001607f1b03602c83901c1660c08a0135614498565b6040870181905260016001607f1b031015612d225760016001607f1b0360408701525b612d2f8160401b60eb1d90565b602080880191909152600160c0880152845163ffffffff166080880152939093015162ffffff166060860152509396929550919350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a84b08c88460a0015185600001518660200151876040015188606001518960800151896040518863ffffffff1660e01b8152600401612dda969594939291906145f8565b6000604051808303818588803b158015612df357600080fd5b505af193505050508015612e05575060015b612e7257612e1161462f565b806308c379a003612e665750612e2561464a565b80612e305750612e68565b8360c001518190612e545760405162461bcd60e51b81526004016108a491906146d4565b50612e5e81614707565b9150506113f3565b505b3d6000803e3d6000fd5b506c1bd999995c8bdd5c19185d1959609a1b92915050565b6c1bd999995c8bdd5c19185d1959609a1b811480612ec75750807f6d67762f77726974654f666665722f64656e736974792f746f6f4c6f77000000145b15612ed157505050565b8151606090208390604080517f4b616e64656c2f7570646174654f666665724661696c656400000000000000008152602081018590527f45b7a2e43f35c7d127ad18416b3d34235d187b2060d4050bb82bb11de272a7c391015b60405180910390a3505050565b612f40611e17565b15610ba1576000612f596118233684900384018461447c565b6040805160028082526060820190925291925060009190816020015b604080516080810182526000808252602080830182905292820181905260608201528252600019909201910181612f75579050509050612fb86020840184613e06565b81600081518110612fcb57612fcb61457e565b6020026020010151600001906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816000815181106130235761302361457e565b6020026020010151606001906001600160a01b031690816001600160a01b031681525050818160008151811061305b5761305b61457e565b602002602001015160200181815250508260600135816000815181106130835761308361457e565b602002602001015160400181815250508260000160200160208101906130a99190613e06565b816001815181106130bc576130bc61457e565b6020026020010151600001906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816001815181106131145761311461457e565b6020026020010151606001906001600160a01b031690816001600160a01b031681525050818160018151811061314c5761314c61457e565b602002602001015160200181815250508260600135816001815181106131745761317461457e565b6020908102919091010151604001527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b8b5cc48826040518263ffffffff1660e01b81526004016131cf919061472b565b600060405180830381600087803b1580156131e957600080fd5b505af11580156131fd573d6000803e3d6000fd5b50505050505050565b600080600061321485613546565b91509150816000148061322e575061322c818361357b565b155b1561324c576b1bd999995c8bd99a5b1b195960a21b925050506113f3565b6040805160e081019091526132b9908061326b3689900389018961447c565b8152602081018490526040810185905260600160e088013560481c62ffffff16815260200160e088013560251c6303ffffff1681526000602082015260016040909101526060870135612d69565b925061205c8585856135a4565b6000600782116132d7575060031690565b506004600382161760029190911c600119011b90565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f95902aa8460a00151856000015186602001518760400151886060015189608001516040518763ffffffff1660e01b815260040161335d9594939291906147a3565b60206040518083038185885af193505050508015613398575060408051601f3d908101601f1916820190925261339591810190614278565b60015b6133f9576133a461462f565b806308c379a003612e6657506133b861464a565b806133c35750612e68565b8360c0015181906133e75760405162461bcd60e51b81526004016108a491906146d4565b506133f181614707565b915050915091565b936c1bd999995c8bd8dc99585d1959609a1b9350915050565b600183600181111561342657613426614466565b0361345157600081815260046020908152604080832085905584835260029091529020819055613473565b6000818152600560209081526040808320859055848352600390915290208190555b82600181111561348557613485614466565b60408051848152602081018490527f4414bf83296b9500de34e173e9e5b7ca010ff6de3f093002103e680a3a1051279101612432565b600060028260018111156134d1576134d1614466565b6134dc906001614498565b6134e691906147d3565b60018111156113f3576113f3614466565b6000600185600181111561350d5761350d614466565b036135355761351c8385614498565b90508181106135305761212060018361450f565b611e53565b828410611e535761137b838561450f565b60008061356760a084013560016001607f1b036080860135602c1c1661450f565b9150608083013560401b60eb1d9050915091565b600080600061358985613651565b90925090508061359985846147f5565b901c95945050505050565b6b1bd999995c8bd99a5b1b195960a21b8114806135d057506c1bd999995c8bdd5c19185d1959609a1b81145b806135fa5750807f6d67762f77726974654f666665722f64656e736974792f746f6f4c6f77000000145b1561360457505050565b606083013561361b6118233686900386018661447c565b60408051858152602081018590527f45b7a2e43f35c7d127ad18416b3d34235d187b2060d4050bb82bb11de272a7c39101612f2b565b60008061365d836136c3565b909250905060eb83901b60007ed89e8c075c4155dd3213326cbbcf86fd1f63f5c205dd2ad2cf44f9349b39e180830782139083050390607e1982850101908113156136ab5793841c936136b5565b8060000385901b94505b81607f039350505050915091565b60008060008084126136d557836136de565b6136de8461480c565b9050620d89e88111156137335760405162461bcd60e51b815260206004820152601760248201527f6d67762f6162735469636b2f6f75744f66426f756e647300000000000000000060448201526064016108a4565b60006001821615613756576ffff97272373d413259a46990580e2139935061375e565b600160801b93505b6002821615613788576080613783856ffff2e50f5f656932ef12357cf3c7fdcb6147f5565b901c93505b60048216156137b25760806137ad856fffe5caca7e10e4e61c3624eaa0941ccf6147f5565b901c93505b60088216156137dc5760806137d7856fffcb9843d60f6159c9db58835c9266436147f5565b901c93505b6010821615613806576080613801856fff973b41fa98c081472e6896dfb254bf6147f5565b901c93505b602082161561383057608061382b856fff2ea16466c96a3843ec78b326b528606147f5565b901c93505b604082161561385a576080613855856ffe5dee046a99a2a811c461f1969c30526147f5565b901c93505b608082161561388457608061387f856ffcbe86c7900a88aedcffc83b479aa3a36147f5565b901c93505b6101008216156138af5760806138aa856ff987a7253ac413176f2b074cf7815e536147f5565b901c93505b6102008216156138da5760806138d5856ff3392b0822b70005940c7a398e4b70f26147f5565b901c93505b610400821615613905576080613900856fe7159475a2c29b7443b29c7fa6e889d86147f5565b901c93505b61080082161561393057608061392b856fd097f3bdfd2022b8845ad8f792aa58256147f5565b901c93505b61100082161561395b576080613956856fa9f746462d870fdf8a65dc1f90e061e46147f5565b901c93505b612000821615613993576080613981856fe1b0d342ada5437121767bec575e65ed6147f5565b901c9350613990600182614828565b90505b6140008216156139cb5760806139b9856fc6f84d7e5f423f66048c541550bf3e966147f5565b901c93506139c8600282614828565b90505b618000821615613a035760806139f1856f9aa508b5b7a84e1c677de54f3e99bc8f6147f5565b901c9350613a00600482614828565b90505b62010000821615613a3c576080613a2a856fbad5f1bdb70232cd33865244bdcc089c6147f5565b901c9350613a39600982614828565b90505b62020000821615613a75576080613a63856f885b9613d7e87aa498106fb7fa5edd376147f5565b901c9350613a72601282614828565b90505b62040000821615613aae576080613a9c856f9142e0723efb884889d1f447715afacd6147f5565b901c9350613aab602582614828565b90505b62080000821615613ae7576080613ad5856fa4d9a773d61316918f140bd96e8e68146147f5565b901c9350613ae4604b82614828565b90505b6000851315613b0857600184856000030401935080613b059061480c565b90505b613b13816080614828565b92505050915091565b604080516101408101909152600060e0820181815261010083018290526101208301919091528190815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b634e487b7160e01b600052604160045260246000fd5b6060810181811067ffffffffffffffff82111715613bac57613bac613b76565b60405250565b6040810181811067ffffffffffffffff82111715613bac57613bac613b76565b601f8201601f1916810167ffffffffffffffff81118282101715613bf857613bf8613b76565b6040525050565b600067ffffffffffffffff821115613c1957613c19613b76565b5060051b60200190565b600082601f830112613c3457600080fd5b81356020613c4182613bff565b60408051613c4f8382613bd2565b84815260609485028701840194848201935088861115613c6e57600080fd5b8488015b86811015613cb65781818b031215613c8a5760008081fd5b8351613c9581613b8c565b81358152868201358782015284820135858201528552938501938101613c72565b509098975050505050505050565b600060408284031215613cd657600080fd5b604051613ce281613bb2565b809150823567ffffffffffffffff80821115613cfd57600080fd5b613d0986838701613c23565b83526020850135915080821115613d1f57600080fd5b50613d2c85828601613c23565b6020830152505092915050565b600060808284031215610c4e57600080fd5b60008060008060e08587031215613d6157600080fd5b843567ffffffffffffffff811115613d7857600080fd5b613d8487828801613cc4565b945050613d948660208701613d39565b939693955050505060a08201359160c0013590565b600060208284031215613dbb57600080fd5b5035919050565b803560028110613dd157600080fd5b919050565b600060208284031215613de857600080fd5b610b0b82613dc2565b6001600160a01b0381168114610ba157600080fd5b600060208284031215613e1857600080fd5b8135610b0b81613df1565b60006101408284031215610c4e57600080fd5b60006101408284031215613e4957600080fd5b610b0b8383613e23565b60008060008060008060008060006101208a8c031215613e7257600080fd5b505087359960208901359950604089013598606081013598506080810135975060a0810135965060c0810135955060e08101359450610100013592509050565b600081518084526020808501945080840160005b83811015613ef85781518051885283810151848901526040908101519088015260609096019590820190600101613ec6565b509495945050505050565b602081526000825160406020840152613f1f6060840182613eb2565b90506020840151601f1984830301604085015261137b8282613eb2565b60008060008060008060c08789031215613f5557600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b60008060408385031215613f9257600080fd5b50508035926020909101359150565b60008060408385031215613fb457600080fd5b823591506020830135613fc681613df1565b809150509250929050565b60008060408385031215613fe457600080fd5b613fed83613dc2565b946020939093013593505050565b60008060008060008060c0878903121561401457600080fd5b863595506020870135945060408701359350606087013592506080870135915060a087013561404281613df1565b809150509295509295509295565b60008060006060848603121561406557600080fd5b8335925060208401359150604084013561407e81613df1565b809150509250925092565b60006060828403121561409b57600080fd5b6040516140a781613b8c565b80915082356140b581613df1565b815260208301356140c581613df1565b6020820152604092830135920191909152919050565b600080608083850312156140ee57600080fd5b6140f88484614089565b946060939093013593505050565b600060408284031215610c4e57600080fd5b60006020828403121561412a57600080fd5b813567ffffffffffffffff81111561414157600080fd5b611e5384828501614106565b6000806000806000806000806000806101a08b8d03121561416d57600080fd5b8a35995060208b0135985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b013593506141a88c60e08d01613d39565b92506101608b013591506101808b013590509295989b9194979a5092959850565b60008061018083850312156141dd57600080fd5b6141e78484613e23565b91506141f7846101408501614106565b90509250929050565b60008060006060848603121561421557600080fd5b833561422081613df1565b9250602084013561423081613df1565b929592945050506040919091013590565b60208082526018908201527f416363657373436f6e74726f6c6c65642f496e76616c69640000000000000000604082015260600190565b60006020828403121561428a57600080fd5b5051919050565b600082601f8301126142a257600080fd5b815160206142af82613bff565b604080516142bd8382613bd2565b848152606094850287018401948482019350888611156142dc57600080fd5b8488015b86811015613cb65781818b0312156142f85760008081fd5b835161430381613b8c565b815181528682015187820152848201518582015285529385019381016142e0565b60006020828403121561433657600080fd5b815167ffffffffffffffff8082111561434e57600080fd5b908301906040828603121561436257600080fd5b60405161436e81613bb2565b82518281111561437d57600080fd5b61438987828601614291565b82525060208301518281111561439e57600080fd5b6143aa87828601614291565b60208301525095945050505050565b6000602082840312156143cb57600080fd5b81518015158114610b0b57600080fd5b80516001600160a01b03908116835260208083015190911690830152604090810151910152565b6080810161441082856143db565b8260608301529392505050565b634e487b7160e01b600052601160045260246000fd5b81810360008312801583831316838312821617156144535761445361441d565b5092915050565b60006113f33683613cc4565b634e487b7160e01b600052602160045260246000fd5b60006060828403121561448e57600080fd5b610b0b8383614089565b808201808211156113f3576113f361441d565b6000600182016144bd576144bd61441d565b5060010190565b6000602082840312156144d657600080fd5b813563ffffffff81168114610b0b57600080fd5b6000602082840312156144fc57600080fd5b813562ffffff81168114610b0b57600080fd5b818103818111156113f3576113f361441d565b60c0810161455a828680516001600160a01b039081168352602080830151908401526040808301519084015260609182015116910152565b83608083015282151560a0830152949350505050565b606081016113f382846143db565b634e487b7160e01b600052603260045260246000fd5b60005b838110156145af578181015183820152602001614597565b50506000910152565b600082516145ca818460208701614594565b9190910192915050565b60a081016145e282866143db565b8360608301528215156080830152949350505050565b610100810161460782896143db565b6060820196909652608081019490945260a084019290925260c083015260e090910152919050565b600060033d1115610d1d5760046000803e5060005160e01c90565b600060443d10156146585790565b6040516003193d81016004833e81513d67ffffffffffffffff816024840111818411171561468857505050505090565b82850191508151818111156146a05750505050505090565b843d87010160208285010111156146ba5750505050505090565b6146c960208286010187613bd2565b509095945050505050565b60208152600082518060208401526146f3816040850160208701614594565b601f01601f19169190910160400192915050565b80516020808301519190811015610c4e5760001960209190910360031b1b16919050565b6020808252825182820181905260009190848201906040850190845b818110156147975761478483855180516001600160a01b039081168352602080830151908401526040808301519084015260609182015116910152565b9284019260809290920191600101614747565b50909695505050505050565b60e081016147b182886143db565b8560608301528460808301528360a08301528260c08301529695505050505050565b6000826147f057634e487b7160e01b600052601260045260246000fd5b500690565b80820281158282048414176113f3576113f361441d565b6000600160ff1b82016148215761482161441d565b5060000390565b808201828112600083128015821682158216171561205c5761205c61441d56fea264697066735822122085f069852f4bc2c2c2da37c2900a1ab7b2b2dd8d9c8fe2a6bef6bd08547a094364736f6c63430008140033a264697066735822122088ae4f95b00050eb750c0f6123c02ad785a6813bb622272ffae7b00a0b01813c64736f6c63430008140033'