{"matchId":"47533026","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-09-08T16:11:26Z","creationBytecode":{"onchainBytecode":"0x60e0346100c157601f614e1938819003918201601f19168301916001600160401b038311848410176100c5578084926060946040528339810103126100c1578051906001600160a01b03821682036100c1576020810151906001600160a01b03821682036100c15760400151916001600160a01b03831683036100c15760805260a05260c052604051614d3f90816100da823960805181818160e90152610182015260a05181818160a5015261028d015260c051818181605d01526102b50152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660808301527f0000000000000000000000000000000000000000000000000000000000000000811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0000000000000000000000000899ecd0bb962d674da4f4b1916200b70a7d37d1c00000000000000000000000081ffb09b8abb42d0f6dc78a186ddf5e37b68e39b","recompiledBytecode":"0x60e0346100c157601f614e1938819003918201601f19168301916001600160401b038311848410176100c5578084926060946040528339810103126100c1578051906001600160a01b03821682036100c1576020810151906001600160a01b03821682036100c15760400151916001600160a01b03831683036100c15760805260a05260c052604051614d3f90816100da823960805181818160e90152610182015260a05181818160a5015261028d015260c051818181605d01526102b50152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660808301527f0000000000000000000000000000000000000000000000000000000000000000811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","sourceMap":"710:1647:22:-:0;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;1038:18;;1058:19;;1079:21;;710:1647;;;;;;;;1038:18;710:1647;;;;;;;;;;1058:19;710:1647;;;;;;;;;;1079:21;710:1647;;;;;;;;;;;;-1:-1:-1;710:1647:22;;;;;;-1:-1:-1;710:1647:22;;;;;-1:-1:-1;710:1647:22","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","offset":19940},"2":{"value":"0xa2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c63430008230033","offset":12430},"3":{"value":"0xa26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033","offset":19887}},"transformations":[{"type":"insert","offset":19993,"reason":"constructorArguments"}],"transformationValues":{"constructorArguments":"0x000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0000000000000000000000000899ecd0bb962d674da4f4b1916200b70a7d37d1c00000000000000000000000081ffb09b8abb42d0f6dc78a186ddf5e37b68e39b"}},"runtimeBytecode":{"onchainBytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000081ffb09b8abb42d0f6dc78a186ddf5e37b68e39b6001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f000000000000000000000000899ecd0bb962d674da4f4b1916200b70a7d37d1c6001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b06001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b06001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f000000000000000000000000899ecd0bb962d674da4f4b1916200b70a7d37d1c811660808301527f00000000000000000000000081ffb09b8abb42d0f6dc78a186ddf5e37b68e39b811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","recompiledBytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660808301527f0000000000000000000000000000000000000000000000000000000000000000811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","sourceMap":"710:1647:22:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;888:49;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;838:44;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;800:32;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;-1:-1:-1;;710:1647:22;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;1376:7;-1:-1:-1;;;;;710:1647:22;;1362:10;:21;;;1358:46;;1900:6;;;;:::i;:::-;1894:25;;;:54;;;;710:1647;1894:85;;;;710:1647;1894:116;;;;710:1647;1894:146;;;;710:1647;1894:184;;;;710:1647;1890:214;;2124:9;;;;2152:3;2124:17;:9;;;;:::i;:::-;:17;;:::i;:::-;2118:37;;;:79;;;;710:1647;2118:120;;;;710:1647;2118:161;;;;710:1647;2118:204;;;;710:1647;2114:234;;710:1647;1471:32;;710:1647;;;;1491:11;;;710:1647;;;;;;1471:32;;;710:1647;;;;;;;;;;;;;;;;;1461:43;;1530:84;;;;;;1471:32;1530:84;;;;;710:1647;1530:84;;;;;;;;;;710:1647;-1:-1:-1;;;;;1575:9:22;710:1647;;2124:9;710:1647;;;1586:12;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1491:11;710:1647;;;;;;;;;2152:3;710:1647;;;;;;;;;;;;;1491:11;710:1647;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;;;2124:9;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;1530:84;;;;;710:1647;1530:84;;;;;-1:-1:-1;;;;;710:1647:22;;1678:11;;;;:::i;:::-;1691:13;;710:1647;1691:13;710:1647;1691:13;;;;:::i;:::-;1706:11;;;1739:14;1719:18;1706:11;710:1647;1706:11;;;;:::i;:::-;1719:18;;;;;;:::i;:::-;1739:14;;;;:::i;:::-;710:1647;;;1641:165;;;;;;;;;;710:1647;1641:165;;;;;;;710:1647;1641:165;710:1647;1641:165;;710:1647;1641:165;;710:1647;1641:165;710:1647;1641:165;710:1647;1641:165;;;;710:1647;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;1471:32;710:1647;;;;:::i;:::-;;;;2124:9;710:1647;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;1471:32;710:1647;;;;:::i;:::-;;;;;1471:32;710:1647;;;;:::i;:::-;;2124:9;710:1647;;;;:::i;:::-;;2124:9;710:1647;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2152:3;710:1647;;;1491:11;710:1647;;;;;1641:165;;710:1647;1641:165;;;;;710:1647;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;1641:165;710:1647;;;;;;;;;1641:165;710:1647;;;;;;;;;;;2114:234;2087:17;;;710:1647;2331:17;710:1647;;2331:17;2118:204;2289:9;2152:3;2289:19;:9;;;;:::i;:::-;2124;2289:19;;;;:::i;:::-;2283:39;;;2118:204;;:161;2248:9;2152:3;2248:17;:9;;;;:::i;:::-;:17;;;;;:::i;:::-;2242:37;;;2118:161;;:120;2207:9;2152:3;2207:17;:9;;;;:::i;:::-;710:1647;2207:17;;;;:::i;:::-;2201:37;;;2118:120;;:79;2165:9;2152:3;2165:18;:9;;;;:::i;:::-;710:1647;2165:18;;;;:::i;:::-;2159:38;;;2118:79;;1894:184;2050:13;2074:4;2050:13;;;;;;:::i;:::-;2044:34;;;1894:184;;:146;2020:6;2037:3;2020:6;;;;;;:::i;:::-;2014:26;;;1894:146;;:116;1989:8;2008:2;1989:8;710:1647;1989:8;;;;:::i;:::-;1983:27;;;1894:116;;:85;1958:8;;710:1647;1958:8;;;;:::i;:::-;1952:27;;;1894:85;;:54;1929:6;710:1647;1929:6;;;;:::i;:::-;1923:25;;;1894:54;;1358:46;1392:12;;;710:1647;1392:12;710:1647;;1392:12;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;710:1647:22;;;;;;;;-1:-1:-1;;710:1647:22;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","offset":19722},"2":{"value":"0xa2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c63430008230033","offset":12212},"3":{"value":"0xa26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033","offset":19669}},"immutableReferences":{"8651":[{"start":233,"length":32},{"start":386,"length":32}],"8654":[{"start":165,"length":32},{"start":653,"length":32}],"8657":[{"start":93,"length":32},{"start":693,"length":32}]},"transformations":[{"id":"8657","type":"replace","offset":93,"reason":"immutable"},{"id":"8654","type":"replace","offset":165,"reason":"immutable"},{"id":"8651","type":"replace","offset":233,"reason":"immutable"},{"id":"8651","type":"replace","offset":386,"reason":"immutable"},{"id":"8654","type":"replace","offset":653,"reason":"immutable"},{"id":"8657","type":"replace","offset":693,"reason":"immutable"}],"transformationValues":{"immutables":{"8651":"0x000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0","8654":"0x000000000000000000000000899ecd0bb962d674da4f4b1916200b70a7d37d1c","8657":"0x00000000000000000000000081ffb09b8abb42d0f6dc78a186ddf5e37b68e39b"}}},"deployment":{"transactionHash":"0xad71e345cc366ea1bbea7106710ca19d22a909f3fe8918a2e3e056f43bf13ad5","blockNumber":"57816681","transactionIndex":"9","deployer":"0x42939046CeE36C4cADaA4fa8be999C2d5037FE4D"},"sources":{"src/BrishopBondingCurve.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from PONS v2's verified curve; see ../NOTICE.md and upstream provenance.\npragma solidity ^0.8.26;\n\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {BrishopBondingCurveMath} from \"./libraries/BrishopBondingCurveMath.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {FeePolicySnapshot, IBrishopFeeEscrow, IBrishopFeePolicy, IBrishopSnipeTax} from \"./interfaces/IBrishop.sol\";\n\n/// @notice Permanent constant-product market. Phantom quote sets pricing; only\n/// actual quote reserves, excluding earned fees, can fund a sell.\ncontract BrishopBondingCurve is ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    uint256 private constant BPS = 10_000;\n    uint256 public constant MAX_RESERVE = type(uint128).max;\n\n    struct BuyQuote { uint256 tokensOut; uint256 fee; uint256 tax; uint256 snipeTax; }\n    struct SellQuote { uint256 quoteOut; uint256 grossQuoteOut; uint256 fee; uint256 tax; bool reserveSufficient; }\n    struct Terms {\n        address pairToken;\n        address creator;\n        uint256 phantomQuote;\n        uint256 feeBps;\n        uint256 creatorTaxBps;\n        bool buybackEnabled;\n    }\n    error ZeroAddress();\n    error ZeroAmount();\n    error NotFactory();\n    error AlreadyInitialized();\n    error NotInitialized();\n    error InvalidLaunchEconomics();\n    error InvalidFeePolicy();\n    error ReserveLimit();\n    error DeadlineExpired();\n    error SlippageExceeded(uint256 actual, uint256 minimum);\n    error InsufficientRealReserve(uint256 required, uint256 available);\n    error NativeValueMismatch(uint256 supplied, uint256 expected);\n    error UnexpectedNativeValue();\n    error TransferFailed();\n    error NotFeeSweepOperator();\n    error InternalSwapRequiresOperator();\n    error MinimumOutputRequired();\n\n    event Initialized(address token);\n    event CurveBuy(address indexed buyer, address indexed recipient, uint256 quoteIn, uint256 tokensOut, uint256 fee, uint256 tax);\n    event CurveSell(address indexed seller, address indexed recipient, uint256 tokensIn, uint256 quoteOut, uint256 fee, uint256 tax);\n    event ReservesUpdated(uint256 realQuote, uint256 tokens);\n    event SnipeTaxExempted(address indexed account);\n    event SnipeTaxCharged(address indexed recipient, uint256 amount);\n    event CreatorFeeRecipientUpdated(address indexed previousRecipient, address indexed newRecipient);\n    event BuybackEnabledUpdated(bool enabled);\n    event FeesSwept(uint256 protocolAmount, uint256 buybackAmount, uint256 creatorAmount);\n    event BuybackLocked(uint256 quoteSpent, uint256 tokensLocked);\n\n    address public token;\n    address public immutable pairToken;\n    address public deployer;\n    address public immutable factory;\n    IBrishopFeePolicy public immutable feePolicy;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    address public immutable protocolFeeRecipient;\n    address public immutable buybackCreatorRecipient;\n    uint16 public immutable protocolFeeShareBps;\n    uint16 public immutable buybackBurnBps;\n    uint16 public immutable maxInternalPriceImpactBps;\n    uint256 public immutable phantomQuote;\n    uint256 public immutable feeBps;\n    uint256 public immutable creatorTaxBps;\n    bool public buybackEnabled;\n    uint256 public quoteFeeBalance;\n    uint256 public buybackQuoteBalance;\n    uint256 public creatorTaxBalance;\n    uint256 public trackedQuote;\n    uint256 public trackedTokens;\n    uint256 public launchSupply;\n    uint256 public launchedAt;\n    uint256 public snipeTaxStartBps;\n    uint256 public snipeTaxSeconds;\n    mapping(address => bool) public snipeTaxExempt;\n\n    modifier onlyFactory() { if (msg.sender != factory) revert NotFactory(); _; }\n    modifier onlyInitialized() { if (token == address(0)) revert NotInitialized(); _; }\n\n    constructor(address factory_, IBrishopFeeEscrow escrow_, BrishopBuybackVault vault_, FeePolicySnapshot memory policy, Terms memory terms) {\n        if (factory_ == address(0) || address(escrow_) == address(0) || address(vault_) == address(0) || terms.creator == address(0)) revert ZeroAddress();\n        if (policy.protocolFeeRecipient == address(0) || policy.protocolFeeShareBps > BPS || policy.buybackBurnBps > BPS || policy.maxInternalPriceImpactBps == 0 || policy.maxInternalPriceImpactBps >= BPS || terms.feeBps + terms.creatorTaxBps > 2_000) revert InvalidFeePolicy();\n        if (terms.phantomQuote == 0 || terms.phantomQuote > MAX_RESERVE) revert InvalidLaunchEconomics();\n        factory = factory_;\n        feePolicy = IBrishopFeePolicy(factory_);\n        feeEscrow = escrow_;\n        buybackVault = vault_;\n        pairToken = terms.pairToken;\n        deployer = terms.creator;\n        protocolFeeRecipient = policy.protocolFeeRecipient;\n        buybackCreatorRecipient = terms.creator;\n        protocolFeeShareBps = policy.protocolFeeShareBps;\n        buybackBurnBps = policy.buybackBurnBps;\n        maxInternalPriceImpactBps = policy.maxInternalPriceImpactBps;\n        phantomQuote = terms.phantomQuote;\n        feeBps = terms.feeBps;\n        creatorTaxBps = terms.creatorTaxBps;\n        buybackEnabled = terms.buybackEnabled;\n    }\n\n    /// @dev The caller supplies the complete immutable exemption list atomically\n    /// at initialization. There is no way to add exemptions to a live pool.\n    function initialize(address token_, address[] calldata exemptions) external onlyFactory {\n        if (token != address(0)) revert AlreadyInitialized();\n        if (token_ == address(0) || token_ == pairToken) revert ZeroAddress();\n        uint256 received = IERC20(token_).balanceOf(address(this));\n        uint256 supply = IERC20(token_).totalSupply();\n        if (received == 0 || received > supply || supply > MAX_RESERVE || exemptions.length > 34) revert InvalidLaunchEconomics();\n        token = token_;\n        launchSupply = supply;\n        trackedTokens = received;\n        launchedAt = block.timestamp;\n        snipeTaxStartBps = IBrishopSnipeTax(factory).snipeTaxStartBps();\n        snipeTaxSeconds = IBrishopSnipeTax(factory).snipeTaxSeconds();\n        if (snipeTaxStartBps > 9_900 || snipeTaxSeconds == 0 || snipeTaxSeconds > 1 days) revert InvalidFeePolicy();\n        for (uint256 i; i < exemptions.length; ++i) {\n            if (exemptions[i] == address(0)) revert ZeroAddress();\n            snipeTaxExempt[exemptions[i]] = true;\n            emit SnipeTaxExempted(exemptions[i]);\n        }\n        emit Initialized(token_);\n        emit ReservesUpdated(0, received);\n    }\n\n    function isNativeQuote() public view returns (bool) { return pairToken == address(0); }\n    function realQuoteReserve() public view returns (uint256) { return trackedQuote - quoteFeeBalance - creatorTaxBalance; }\n    function getReserves() public view returns (uint256 quote, uint256 tokens) { return (phantomQuote + realQuoteReserve(), trackedTokens); }\n    function quoteReserve() external view returns (uint256) { return phantomQuote + realQuoteReserve(); }\n    function tokenReserve() external view returns (uint256) { return trackedTokens; }\n\n    /// @notice PONS's verified fourteen-halving decay; the live three-second\n    /// default produces 9900, 618, 19, 0 bps before the combined-fee cap.\n    function currentSnipeTaxBps(address recipient) public view returns (uint256) {\n        if (snipeTaxExempt[recipient] || snipeTaxStartBps == 0) return 0;\n        uint256 elapsed = block.timestamp - launchedAt;\n        if (elapsed >= snipeTaxSeconds) return 0;\n        return snipeTaxStartBps >> ((elapsed * 14) / snipeTaxSeconds);\n    }\n\n    function quoteBuy(uint256 quoteIn, address recipient) public view onlyInitialized returns (BuyQuote memory q) {\n        if (recipient == address(0)) revert ZeroAddress();\n        if (quoteIn == 0) revert ZeroAmount();\n        if (quoteIn > MAX_RESERVE - phantomQuote - trackedQuote) revert ReserveLimit();\n        uint256 snipeBps = currentSnipeTaxBps(recipient);\n        uint256 maxSnipe = BPS - feeBps - creatorTaxBps - 100;\n        if (snipeBps > maxSnipe) snipeBps = maxSnipe;\n        q.fee = Math.mulDiv(quoteIn, feeBps, BPS);\n        q.tax = Math.mulDiv(quoteIn, creatorTaxBps, BPS);\n        q.snipeTax = Math.mulDiv(quoteIn, snipeBps, BPS);\n        (uint256 quote, uint256 tokens) = getReserves();\n        q.tokensOut = BrishopBondingCurveMath.getAmountOut(quoteIn - q.fee - q.tax - q.snipeTax, quote, tokens, 0);\n    }\n\n    function quoteSell(uint256 tokensIn) public view onlyInitialized returns (SellQuote memory q) {\n        if (tokensIn == 0) revert ZeroAmount();\n        if (tokensIn > MAX_RESERVE - trackedTokens) revert ReserveLimit();\n        (uint256 quote, uint256 tokens) = getReserves();\n        q.grossQuoteOut = BrishopBondingCurveMath.getAmountOut(tokensIn, tokens, quote, 0);\n        q.fee = Math.mulDiv(q.grossQuoteOut, feeBps, BPS);\n        q.tax = Math.mulDiv(q.grossQuoteOut, creatorTaxBps, BPS);\n        q.quoteOut = q.grossQuoteOut - q.fee - q.tax;\n        q.reserveSufficient = q.grossQuoteOut <= realQuoteReserve();\n    }\n\n    function buy(uint256 quoteIn, uint256 minTokensOut, address recipient, uint256 deadline) external payable nonReentrant onlyInitialized returns (uint256 tokensOut) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        uint256 received = _receiveQuote(quoteIn);\n        BuyQuote memory q = quoteBuy(received, recipient);\n        tokensOut = q.tokensOut;\n        if (tokensOut < minTokensOut) revert SlippageExceeded(tokensOut, minTokensOut);\n        _accrueFees(q.fee + q.snipeTax, q.tax);\n        trackedQuote += received;\n        trackedTokens -= tokensOut;\n        IERC20(token).safeTransfer(recipient, tokensOut);\n        if (q.snipeTax != 0) emit SnipeTaxCharged(recipient, q.snipeTax);\n        emit CurveBuy(msg.sender, recipient, received, tokensOut, q.fee + q.snipeTax, q.tax);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n\n    function sell(uint256 tokensIn, uint256 minQuoteOut, address recipient, uint256 deadline) external nonReentrant onlyInitialized returns (uint256 quoteOut) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        if (recipient == address(0)) revert ZeroAddress();\n        SellQuote memory q = quoteSell(tokensIn);\n        if (!q.reserveSufficient) revert InsufficientRealReserve(q.grossQuoteOut, realQuoteReserve());\n        quoteOut = q.quoteOut;\n        if (quoteOut < minQuoteOut) revert SlippageExceeded(quoteOut, minQuoteOut);\n        IERC20(token).safeTransferFrom(msg.sender, address(this), tokensIn);\n        _accrueFees(q.fee, q.tax);\n        trackedQuote -= quoteOut;\n        trackedTokens += tokensIn;\n        _sendQuote(recipient, quoteOut);\n        emit CurveSell(msg.sender, recipient, tokensIn, quoteOut, q.fee, q.tax);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n\n    function setCreatorFeeRecipient(address recipient) external onlyFactory {\n        if (recipient == address(0)) revert ZeroAddress();\n        emit CreatorFeeRecipientUpdated(deployer, recipient);\n        deployer = recipient;\n    }\n    function setBuybackEnabled(bool enabled) external onlyFactory { buybackEnabled = enabled; emit BuybackEnabledUpdated(enabled); }\n\n    function _receiveQuote(uint256 amount) private returns (uint256) {\n        if (isNativeQuote()) {\n            if (msg.value != amount) revert NativeValueMismatch(msg.value, amount);\n            return amount;\n        }\n        if (msg.value != 0) revert UnexpectedNativeValue();\n        uint256 beforeBalance = IERC20(pairToken).balanceOf(address(this));\n        IERC20(pairToken).safeTransferFrom(msg.sender, address(this), amount);\n        return IERC20(pairToken).balanceOf(address(this)) - beforeBalance;\n    }\n    function _sendQuote(address recipient, uint256 amount) private {\n        if (isNativeQuote()) {\n            (bool sent,) = payable(recipient).call{value: amount}(\"\");\n            if (!sent) revert TransferFailed();\n        } else IERC20(pairToken).safeTransfer(recipient, amount);\n    }\n    function _creditQuote(address recipient, uint256 amount) private {\n        if (isNativeQuote()) feeEscrow.credit{value: amount}(recipient);\n        else {\n            IERC20(pairToken).forceApprove(address(feeEscrow), amount);\n            feeEscrow.creditToken(recipient, pairToken, amount);\n        }\n    }\n    function _accrueFees(uint256 fee, uint256 tax) private {\n        quoteFeeBalance += fee;\n        creatorTaxBalance += tax;\n        if (buybackEnabled && fee != 0) {\n            uint256 creatorSlice = fee - Math.mulDiv(fee, protocolFeeShareBps, BPS);\n            buybackQuoteBalance += Math.mulDiv(creatorSlice, buybackBurnBps, BPS);\n        }\n    }\n\n    /// @notice PONS fee sweep and five-year buyback behavior, with its former\n    /// graduation inventory limit removed. Minimum output bounds buyback swaps.\n    function sweepFees(uint256 minBuybackTokensOut) external nonReentrant onlyInitialized {\n        bool operator = msg.sender == feePolicy.feeSweepOperator();\n        if (!operator && msg.sender != deployer) revert NotFeeSweepOperator();\n        if (!operator && buybackQuoteBalance != 0) revert InternalSwapRequiresOperator();\n        uint256 pending = quoteFeeBalance;\n        uint256 tax = creatorTaxBalance;\n        if (pending == 0 && tax == 0) return;\n        uint256 protocolAmount = Math.mulDiv(pending, protocolFeeShareBps, BPS);\n        uint256 creatorBucket = pending - protocolAmount;\n        uint256 buybackAmount = Math.min(buybackQuoteBalance, creatorBucket);\n        uint256 creatorAmount = creatorBucket - buybackAmount + tax;\n        uint256 tokensLocked;\n        if (buybackAmount != 0) {\n            if (minBuybackTokensOut == 0) revert MinimumOutputRequired();\n            (uint256 quote, uint256 tokens) = getReserves();\n            uint256 movementBps = Math.mulDiv(buybackAmount, BPS, quote + buybackAmount);\n            if (movementBps <= maxInternalPriceImpactBps) tokensLocked = BrishopBondingCurveMath.quoteAmountOut(buybackAmount, quote, tokens, 0);\n            if (tokensLocked == 0) { creatorAmount += buybackAmount; buybackAmount = 0; }\n            else if (tokensLocked < minBuybackTokensOut) revert SlippageExceeded(tokensLocked, minBuybackTokensOut);\n        }\n        quoteFeeBalance = 0;\n        creatorTaxBalance = 0;\n        buybackQuoteBalance = 0;\n        trackedQuote -= protocolAmount + creatorAmount;\n        if (tokensLocked != 0) {\n            trackedTokens -= tokensLocked;\n            IERC20(token).forceApprove(address(buybackVault), tokensLocked);\n            buybackVault.lock(token, tokensLocked, buybackCreatorRecipient, protocolFeeRecipient, protocolFeeShareBps);\n            emit BuybackLocked(buybackAmount, tokensLocked);\n        }\n        if (protocolAmount != 0) _creditQuote(protocolFeeRecipient, protocolAmount);\n        if (creatorAmount != 0) _creditQuote(deployer, creatorAmount);\n        emit FeesSwept(protocolAmount, buybackAmount, creatorAmount);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n}\n"},"src/BrishopBuybackVault.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IBrishopFeeEscrow, IBrishopFeePolicy, IBrishopLaunchFactory} from \"./interfaces/IBrishop.sol\";\n\n/**\n * @title BrishopBuybackVault\n * @notice Holds every launch's bought-back memecoin supply and releases it\n * linearly over five years instead of burning it immediately, splitting\n * every release between the creator and the protocol on the launch's\n * recorded fee shares. One shared deployment serves every launch, the same\n * \"single deployment for every token\" pattern BrishopFeeEscrow already uses.\n *\n * Note that the split applies to the release, not to the funding. The\n * permanent curve carves the buyback slice out of the creator's share of\n * the fees alone, so the creator funds the entire lock and then receives\n * only their fee share of it back. Enabling a buyback therefore moves value\n * from the creator to the protocol relative to taking the fees directly,\n * by an amount that grows with `buybackBurnBps`.\n *\n * Deposits use a weighted-average vesting clock instead of per-deposit\n * tranches: a launch's fee sweep can add to its lock on every single sweep,\n * and tracking an unbounded array of tranches would make `release()`'s gas\n * cost grow forever. Instead, each new deposit shifts the launch's single\n * `vestingStart` forward by an amount proportional to the deposit's share\n * of the new total, so a large existing lock is barely disturbed by a small\n * top-up, and a small existing lock is pulled close to the new deposit's own\n * clock. `vestedAmount` at any time reflects a fair, size-weighted blend\n * across every deposit made so far.\n */\ncontract BrishopBuybackVault is Ownable2Step, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n\n    struct LaunchVest {\n        uint256 totalLocked;\n        uint256 totalReleased;\n        uint256 vestingStart;\n        uint256 vestedUnreleased;\n        uint256 unvestedAmount;\n        uint256 lastUpdate;\n        uint256 vestingEnd;\n        address creatorRecipient;\n        address protocolRecipient;\n        uint16 protocolFeeShareBps;\n    }\n\n    uint256 private constant BASIS_POINTS = 10_000;\n    uint256 public constant VESTING_DURATION = 5 * 365 days;\n\n    error ZeroAddress();\n    error AlreadyInitialized();\n    error NotFactory();\n    error NotAuthorizedLocker();\n    error NotVestBeneficiary();\n    error InvalidVestingTerms();\n    error VestingTermsMismatch();\n    error OwnershipCannotBeRenounced();\n\n    event FactorySet(address factory);\n    event Locked(address indexed token, address indexed depositor, uint256 amount, uint256 newVestingStart);\n    event VestingTermsSnapshotted(\n        address indexed token,\n        address indexed creatorRecipient,\n        address indexed protocolRecipient,\n        uint256 protocolFeeShareBps\n    );\n    event Released(address indexed token, uint256 creatorAmount, uint256 protocolAmount);\n    event CreatorRecipientUpdated(\n        address indexed token, address indexed previousRecipient, address indexed newRecipient\n    );\n\n    IBrishopFeePolicy public immutable feePolicy;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    address public factory;\n\n    mapping(address token => LaunchVest) private _vaults;\n\n    /**\n     * @param initialOwner Administrative owner; only used to wire the factory once.\n     * @param feePolicy_ Shared Brishop protocol/creator fee policy.\n     * @param feeEscrow_ Shared claimable balance ledger releases are paid through.\n     */\n    constructor(address initialOwner, IBrishopFeePolicy feePolicy_, IBrishopFeeEscrow feeEscrow_) Ownable(initialOwner) {\n        if (address(feePolicy_) == address(0) || address(feeEscrow_) == address(0)) revert ZeroAddress();\n        feePolicy = feePolicy_;\n        feeEscrow = feeEscrow_;\n    }\n\n    /**\n     * @notice One-time wiring of the v2 factory, set after both are\n     * deployed, used to authorize each launch's bonding curve as a locker.\n     */\n    function setFactory(address factory_) external onlyOwner {\n        if (factory != address(0)) revert AlreadyInitialized();\n        if (factory_ == address(0)) revert ZeroAddress();\n        factory = factory_;\n        emit FactorySet(factory_);\n    }\n\n    /**\n     * @notice Permanently disabled. Ownership here exists only to perform the\n     * one-time factory wiring, and renouncing before that wiring would strand\n     * every future buyback lock.\n     */\n    function renounceOwnership() public pure override {\n        revert OwnershipCannotBeRenounced();\n    }\n\n    /**\n     * @notice Locks `amount` of `token` into its five-year vest, preserving\n     * the supplied beneficiaries and split for the active vesting epoch.\n     * Restricted to this token's registered Brishop curve, looked up live\n     * from the factory.\n     */\n    function lock(\n        address token,\n        uint256 amount,\n        address creatorRecipient,\n        address protocolRecipient,\n        uint16 protocolFeeShareBps\n    ) external nonReentrant {\n        if (token == address(0)) revert ZeroAddress();\n        if (factory == address(0)) revert NotFactory();\n        if (!_isAuthorizedLocker(token, msg.sender)) revert NotAuthorizedLocker();\n        if (amount == 0) return;\n        if (creatorRecipient == address(0) || protocolRecipient == address(0) || protocolFeeShareBps > BASIS_POINTS) {\n            revert InvalidVestingTerms();\n        }\n\n        // Schedule against what arrived, not what was asked for. Recording a\n        // nominal amount the vault never received would make the final\n        // release of the epoch revert on its own balance, stranding the tail\n        // of the vest. Every other ERC-20 boundary in the protocol measures\n        // this delta; this one is no different for being fed by our own\n        // launcher token today.\n        uint256 balanceBefore = IERC20(token).balanceOf(address(this));\n        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n        amount = IERC20(token).balanceOf(address(this)) - balanceBefore;\n        if (amount == 0) return;\n\n        LaunchVest storage v = _vaults[token];\n        uint256 nowTs = block.timestamp;\n        _checkpoint(v, nowTs);\n        _setOrValidateVestingTerms(v, token, creatorRecipient, protocolRecipient, protocolFeeShareBps);\n\n        uint256 existingUnvested = v.unvestedAmount;\n        uint256 combinedAmount = existingUnvested + amount;\n        uint256 remainingDuration = existingUnvested == 0 ? 0 : v.vestingEnd - nowTs;\n        uint256 combinedDuration = (existingUnvested * remainingDuration + amount * VESTING_DURATION) / combinedAmount;\n\n        v.unvestedAmount = combinedAmount;\n        v.lastUpdate = nowTs;\n        v.vestingEnd = nowTs + combinedDuration;\n        v.vestingStart = nowTs - (VESTING_DURATION - combinedDuration);\n        v.totalLocked += amount;\n\n        emit Locked(token, msg.sender, amount, v.vestingStart);\n    }\n\n    /**\n     * @notice Releases every currently vested, not-yet-released token for\n     * `token`, using the beneficiaries and split frozen for its active\n     * vesting epoch.\n     * @dev Restricted to the two parties a release pays. Letting anyone\n     * choose when value leaves the vest is harmful in two ways. A caller can\n     * time a release inside the protocol owner's creator-recipient recovery\n     * window, flushing vested tokens to the very address the recovery exists\n     * to abandon. A caller can also advance the checkpoint every second, so\n     * each step rounds its newly vested amount down to zero and the vest\n     * stalls without ever paying out.\n     */\n    function release(address token) external nonReentrant returns (uint256 released) {\n        if (factory == address(0)) revert NotFactory();\n\n        LaunchVest storage v = _vaults[token];\n        if (msg.sender != v.creatorRecipient && msg.sender != v.protocolRecipient) revert NotVestBeneficiary();\n\n        _checkpoint(v, block.timestamp);\n        released = v.vestedUnreleased;\n        if (released == 0) return 0;\n        v.vestedUnreleased = 0;\n        v.totalReleased += released;\n\n        uint256 protocolAmount = (released * v.protocolFeeShareBps) / BASIS_POINTS;\n        uint256 creatorAmount = released - protocolAmount;\n\n        IERC20(token).forceApprove(address(feeEscrow), released);\n        if (protocolAmount != 0) feeEscrow.creditToken(v.protocolRecipient, token, protocolAmount);\n        if (creatorAmount != 0) feeEscrow.creditToken(v.creatorRecipient, token, creatorAmount);\n\n        emit Released(token, creatorAmount, protocolAmount);\n    }\n\n    /**\n     * @notice Redirects a launch's buyback vest to a new creator recipient.\n     * Restricted to the factory, which forwards both self-service creator\n     * transfers and protocol-owner recovery overrides here, so vested\n     * buyback tokens track the same recipient as immediate creator fees\n     * rather than remaining stranded on the launch-time address. Vested but\n     * not-yet-released tokens follow the new recipient too, matching the\n     * intent of wallet recovery. Only the protocol split terms stay bound to\n     * the launch snapshot; the creator identity is managed here instead.\n     */\n    function updateCreatorRecipient(address token, address newRecipient) external {\n        if (msg.sender != factory) revert NotFactory();\n        if (token == address(0) || newRecipient == address(0)) revert ZeroAddress();\n\n        LaunchVest storage v = _vaults[token];\n        address previousRecipient = v.creatorRecipient;\n        if (previousRecipient == newRecipient) return;\n        v.creatorRecipient = newRecipient;\n        emit CreatorRecipientUpdated(token, previousRecipient, newRecipient);\n    }\n\n    /**\n     * @notice Total amount of `token` ever locked into this vault.\n     */\n    function totalLocked(address token) external view returns (uint256) {\n        return _vaults[token].totalLocked;\n    }\n\n    /**\n     * @notice Total amount of `token` already released from this vault.\n     */\n    function totalReleased(address token) external view returns (uint256) {\n        return _vaults[token].totalReleased;\n    }\n\n    /**\n     * @notice The launch's current weighted-average vesting start time.\n     * @dev Reporting only. Vesting is accounted from `vestedUnreleased`,\n     * `unvestedAmount`, `lastUpdate` and `vestingEnd`, which are settled on\n     * every lock and release. Interpolating this value against\n     * `VESTING_DURATION` will not reproduce `vestedAmount`, because already\n     * vested tokens are banked at each deposit rather than recomputed from\n     * the shifted clock. Read `vestedAmount` for the authoritative figure.\n     */\n    function vestingStart(address token) external view returns (uint256) {\n        return _vaults[token].vestingStart;\n    }\n\n    /**\n     * @notice Amount of `token` vested so far, released or not.\n     */\n    function vestedAmount(address token) external view returns (uint256) {\n        return _vestedAmount(_vaults[token]);\n    }\n\n    /**\n     * @notice Amount of `token` currently releasable: vested but not yet released.\n     */\n    function releasable(address token) external view returns (uint256) {\n        LaunchVest storage v = _vaults[token];\n        return v.vestedUnreleased + _previewNewlyVested(v, block.timestamp);\n    }\n\n    /**\n     * @notice Returns the immutable terms for the token's active vesting epoch.\n     */\n    function vestingTerms(address token)\n        external\n        view\n        returns (address creatorRecipient, address protocolRecipient, uint16 protocolFeeShareBps)\n    {\n        LaunchVest storage v = _vaults[token];\n        return (v.creatorRecipient, v.protocolRecipient, v.protocolFeeShareBps);\n    }\n\n    /**\n     * @dev Linear vest over VESTING_DURATION from the launch's current\n     * weighted-average start time, capped at the total ever locked.\n     */\n    function _vestedAmount(LaunchVest storage v) private view returns (uint256) {\n        return v.totalReleased + v.vestedUnreleased + _previewNewlyVested(v, block.timestamp);\n    }\n\n    /**\n     * @dev Crystallizes the linear portion vested since the previous state\n     * update while preserving the existing schedule's maturity.\n     */\n    function _checkpoint(LaunchVest storage v, uint256 nowTs) private {\n        uint256 newlyVested = _previewNewlyVested(v, nowTs);\n        if (newlyVested != 0) {\n            v.unvestedAmount -= newlyVested;\n            v.vestedUnreleased += newlyVested;\n        }\n        v.lastUpdate = nowTs;\n    }\n\n    /**\n     * @dev Previews how much of the active schedule vested since lastUpdate.\n     */\n    function _previewNewlyVested(LaunchVest storage v, uint256 nowTs) private view returns (uint256) {\n        if (v.unvestedAmount == 0 || nowTs <= v.lastUpdate) return 0;\n        if (nowTs >= v.vestingEnd) return v.unvestedAmount;\n\n        uint256 remainingDuration = v.vestingEnd - v.lastUpdate;\n        uint256 elapsed = nowTs - v.lastUpdate;\n        return (v.unvestedAmount * elapsed) / remainingDuration;\n    }\n\n    /**\n     * @dev A new epoch begins only after every token in the prior epoch has\n     * been released. This keeps every active weighted-average vest bound to\n     * one immutable set of beneficiaries without unbounded tranche storage.\n     */\n    function _setOrValidateVestingTerms(\n        LaunchVest storage v,\n        address token,\n        address creatorRecipient,\n        address protocolRecipient,\n        uint16 protocolFeeShareBps\n    ) private {\n        bool newEpoch = v.unvestedAmount == 0 && v.vestedUnreleased == 0;\n        if (newEpoch) {\n            // Seed the buyback beneficiary only when it has never been set.\n            // Once the factory has redirected the vest through\n            // updateCreatorRecipient (a creator transfer or a protocol\n            // recovery override), a later lock must not silently reset it\n            // back to the launch-time recipient, even across a fresh epoch.\n            if (v.creatorRecipient == address(0)) {\n                v.creatorRecipient = creatorRecipient;\n            }\n            v.protocolRecipient = protocolRecipient;\n            v.protocolFeeShareBps = protocolFeeShareBps;\n            emit VestingTermsSnapshotted(token, v.creatorRecipient, protocolRecipient, protocolFeeShareBps);\n            return;\n        }\n\n        // The creator recipient is deliberately excluded from this check: it\n        // is managed independently through updateCreatorRecipient, so recovery\n        // can move the vest without ever bricking a subsequent lock on a terms\n        // mismatch. The protocol split terms remain immutable per launch.\n        if (v.protocolRecipient != protocolRecipient || v.protocolFeeShareBps != protocolFeeShareBps) {\n            revert VestingTermsMismatch();\n        }\n    }\n\n    /**\n     * @dev Only the token's own registered curve may lock its buybacks.\n     * No per-launch administrator action or shared external hook is needed.\n     */\n    function _isAuthorizedLocker(address token, address caller) private view returns (bool) {\n        if (factory == address(0)) return false;\n        return caller == IBrishopLaunchFactory(factory).getLaunchedToken(token).curve;\n    }\n}\n"},"src/BrishopLaunchDeployer.sol":{"content":"// SPDX-License-Identifier: MIT\n// Deployment/metadata pattern derived from PONS v2; see ../NOTICE.md.\npragma solidity ^0.8.26;\nimport {BrishopLauncherToken} from \"./BrishopLauncherToken.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {FeePolicySnapshot, IBrishopFeeEscrow} from \"./interfaces/IBrishop.sol\";\n\nstruct TokenParams {\n    string name;\n    string symbol;\n    string logo;\n    string description;\n    BrishopLauncherToken.Socials socials;\n    address creatorFeeRecipient;\n    uint16 creatorTaxBps;\n    bool buybackEnabled;\n    bytes32 expectedEconomics;\n    bytes32 salt;\n    address[] snipeTaxExemptions;\n}\n\ncontract BrishopLaunchDeployer {\n    error NotFactory();\n    error InvalidMetadata();\n    address public immutable factory;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    constructor(address factory_, IBrishopFeeEscrow escrow_, BrishopBuybackVault vault_) {\n        factory = factory_; feeEscrow = escrow_; buybackVault = vault_;\n    }\n    function deployLaunch(TokenParams calldata params, BrishopBondingCurve.Terms calldata terms, FeePolicySnapshot calldata policy, address creator, uint256 supply, uint256 creatorAllocation) external returns (address token, address curve) {\n        if (msg.sender != factory) revert NotFactory();\n        _checkMetadata(params);\n        bytes32 salt = keccak256(abi.encode(creator, params.salt));\n        curve = address(new BrishopBondingCurve{salt: salt}(factory, feeEscrow, buybackVault, policy, terms));\n        token = address(new BrishopLauncherToken{salt: salt}(params.name, params.symbol, params.logo, params.description, params.socials, creator, curve, factory, supply, creatorAllocation));\n    }\n    function _checkMetadata(TokenParams calldata p) private pure {\n        if (bytes(p.name).length == 0 || bytes(p.name).length > 64 || bytes(p.symbol).length == 0 || bytes(p.symbol).length > 16 || bytes(p.logo).length > 512 || bytes(p.description).length > 2048) revert InvalidMetadata();\n        if (bytes(p.socials.twitter).length > 256 || bytes(p.socials.telegram).length > 256 || bytes(p.socials.discord).length > 256 || bytes(p.socials.website).length > 256 || bytes(p.socials.farcaster).length > 256) revert InvalidMetadata();\n    }\n}\n"},"src/BrishopLauncherToken.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\n/**\n * @title BrishopLauncherToken\n * @notice Fixed-supply ERC-20 deployed by BrishopLaunchFactory for a v2 launch.\n * Community supply mints to the curve. An administrator personality launch\n * assigns 25% to its creator and 75% to the curve. Purchases are limited by\n * curve pricing and inventory. `deployer` is carried here\n * as immutable reference data for off-chain attribution only, and confers no\n * privileges over the token.\n * `ERC20Burnable` lets any holder voluntarily burn their own balance; the\n * protocol's buyback mechanism does not use it, bought-back tokens are\n * locked into `BrishopBuybackVault` for a five-year vest instead of being\n * burned.\n */\ncontract BrishopLauncherToken is ERC20, ERC20Burnable {\n    struct Socials {\n        string twitter;\n        string telegram;\n        string discord;\n        string website;\n        string farcaster;\n    }\n\n    error ZeroAddress();\n    error InvalidAllocation();\n\n    address public immutable deployer;\n    address public immutable launchFactory;\n    address public immutable curve;\n    uint256 public immutable initialSupply;\n    uint256 public immutable initialCreatorAllocation;\n\n    string public logo;\n    string public description;\n\n    Socials private _socials;\n\n    /**\n     * @notice Mints the fixed initial supply between the curve and creator allocation.\n     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        string memory logo_,\n        string memory description_,\n        Socials memory socials_,\n        address deployer_,\n        address curve_,\n        address launchFactory_,\n        uint256 supply_,\n        uint256 creatorAllocation_\n    ) ERC20(name_, symbol_) {\n        if (deployer_ == address(0) || curve_ == address(0) || launchFactory_ == address(0)) {\n            revert ZeroAddress();\n        }\n\n        deployer = deployer_;\n        // Passed explicitly rather than read from msg.sender: BrishopLaunchFactory\n        // deploys this token indirectly through BrishopLaunchDeployer to keep its\n        // own bytecode under EIP-170's size limit, so msg.sender at construction\n        // time would otherwise resolve to that deployer helper, not the factory.\n        launchFactory = launchFactory_;\n        curve = curve_;\n        if (supply_ == 0 || creatorAllocation_ > supply_ / 4) revert InvalidAllocation();\n        initialSupply = supply_;\n        initialCreatorAllocation = creatorAllocation_;\n        logo = logo_;\n        description = description_;\n        _socials = socials_;\n\n        _mint(curve_, supply_ - creatorAllocation_);\n        if (creatorAllocation_ != 0) _mint(deployer_, creatorAllocation_);\n    }\n\n    /**\n     * @notice Returns the launch token's five social metadata fields.\n     */\n    function socials()\n        external\n        view\n        returns (\n            string memory twitter,\n            string memory telegram,\n            string memory discord,\n            string memory website,\n            string memory farcaster\n        )\n    {\n        Socials memory values = _socials;\n        return (values.twitter, values.telegram, values.discord, values.website, values.farcaster);\n    }\n\n    /**\n     * @notice Returns creator and metadata in the launcher-compatible tuple.\n     */\n    function getTokenInfo()\n        external\n        view\n        returns (\n            address tokenDeployer,\n            string memory tokenLogo,\n            string memory tokenDescription,\n            Socials memory tokenSocials\n        )\n    {\n        return (deployer, logo, description, _socials);\n    }\n}\n"},"src/interfaces/IBrishop.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ninterface IBrishopFeeEscrow {\n    function credit(address recipient) external payable;\n    function creditToken(address recipient, address token, uint256 amount) external;\n    function claim() external returns (uint256);\n    function claim(uint256 amount) external returns (uint256);\n    function claimToken(address token) external returns (uint256);\n    function claimToken(address token, uint256 amount) external returns (uint256);\n    function balanceOf(address recipient) external view returns (uint256);\n    function balanceOfToken(address recipient, address token) external view returns (uint256);\n}\n\n// Names retained from PONS for fee-policy compatibility. buybackBurnBps funds\n// purchases locked in the five-year vault; it does not burn those tokens.\nstruct FeePolicySnapshot {\n    address protocolFeeRecipient;\n    uint16 protocolFeeShareBps;\n    uint16 buybackBurnBps;\n    uint16 hookFeeBps;\n    uint16 maxInternalPriceImpactBps;\n}\n\ninterface IBrishopFeePolicy {\n    function feeSweepOperator() external view returns (address);\n    function currentFeePolicy() external view returns (FeePolicySnapshot memory);\n}\n\ninterface IBrishopSnipeTax {\n    function snipeTaxStartBps() external view returns (uint256);\n    function snipeTaxSeconds() external view returns (uint256);\n}\n\ninterface IBrishopLaunchFactory {\n    struct LaunchedToken {\n        address token;\n        address curve;\n        address deployer;\n        address creatorFeeRecipient;\n        address pairToken;\n        uint16 creatorTaxBps;\n        bool buybackEnabled;\n        bool personality;\n        bool exists;\n    }\n    function getLaunchedToken(address token) external view returns (LaunchedToken memory);\n}\n"},"src/libraries/BrishopBondingCurveMath.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n/**\n * @title BrishopBondingCurveMath\n * @notice Constant-product bonding curve math shared by BrishopBondingCurve, adapted\n * from the BootstrapPool.sol reference (code-423n4/2025-01-iq-ai). Reserves and fee\n * are passed explicitly so the same formula prices trades in either direction and can\n * also price the curve's internal buyback swap.\n */\nlibrary BrishopBondingCurveMath {\n    uint256 internal constant BASIS_POINTS = 10_000;\n\n    error InsufficientInputAmount();\n    error InsufficientOutputAmount();\n    error InsufficientLiquidity();\n    error ReserveLimit();\n\n    /**\n     * @notice Quotes the output amount for an exact input amount, net of the trade fee.\n     * @param amountIn Exact amount of the input asset being sold into the curve.\n     * @param reserveIn Curve reserve of the input asset before this trade.\n     * @param reserveOut Curve reserve of the output asset before this trade.\n     * @param feeBps Fee charged on the input amount, in basis points.\n     */\n    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountOut)\n    {\n        if (amountIn == 0) revert InsufficientInputAmount();\n        if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();\n\n        amountOut = _amountOut(amountIn, reserveIn, reserveOut, feeBps);\n        if (amountOut == 0) revert InsufficientOutputAmount();\n    }\n\n    /**\n     * @notice Same quote as `getAmountOut`, returning zero where that reverts.\n     * @dev For callers that treat an unpriceable trade as a condition to\n     * handle rather than an error, such as the curve's internal buyback,\n     * which folds the slice back into the creator's payout when the curve is\n     * too thin to execute against. Routing that case through the reverting\n     * variant would take the whole fee sweep down with it, stranding fees\n     * exactly when the curve cannot support a buyback.\n     */\n    function quoteAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountOut)\n    {\n        if (amountIn == 0 || reserveIn == 0 || reserveOut == 0 || feeBps >= BASIS_POINTS) return 0;\n        return _amountOut(amountIn, reserveIn, reserveOut, feeBps);\n    }\n\n    function _amountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        private\n        pure\n        returns (uint256)\n    {\n        if (amountIn > type(uint128).max || reserveIn > type(uint128).max || reserveOut > type(uint128).max) revert ReserveLimit();\n        uint256 amountInWithFee = amountIn * (BASIS_POINTS - feeBps);\n        uint256 denominator = reserveIn * BASIS_POINTS + amountInWithFee;\n        return Math.mulDiv(amountInWithFee, reserveOut, denominator);\n    }\n\n    /**\n     * @notice Quotes the input amount required for an exact output amount, net of the trade fee.\n     * @param amountOut Exact amount of the output asset requested from the curve.\n     * @param reserveIn Curve reserve of the input asset before this trade.\n     * @param reserveOut Curve reserve of the output asset before this trade.\n     * @param feeBps Fee charged on the input amount, in basis points.\n     */\n    function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountIn)\n    {\n        if (amountOut == 0) revert InsufficientOutputAmount();\n        if (reserveIn == 0 || reserveOut <= amountOut) revert InsufficientLiquidity();\n        // A full-fee trade has no input that produces output, and the\n        // denominator below would divide by zero rather than say so.\n        if (feeBps >= BASIS_POINTS) revert InsufficientLiquidity();\n\n        if (amountOut > type(uint128).max || reserveIn > type(uint128).max || reserveOut > type(uint128).max) revert ReserveLimit();\n        uint256 denominator = (reserveOut - amountOut) * (BASIS_POINTS - feeBps);\n        amountIn = Math.mulDiv(amountOut, reserveIn * BASIS_POINTS, denominator) + 1;\n    }\n}\n"},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n    using StorageSlot for bytes32;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev A `view` only version of {nonReentrant}. Use to block view functions\n     * from being called, preventing reading from inconsistent contract state.\n     *\n     * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n     * status. Use it only on view functions. For payable or non-payable functions,\n     * use the standard {nonReentrant} modifier instead.\n     */\n    modifier nonReentrantView() {\n        _nonReentrantBeforeView();\n        _;\n    }\n\n    function _nonReentrantBeforeView() private view {\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        _nonReentrantBeforeView();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n    }\n\n    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n        return REENTRANCY_GUARD_STORAGE;\n    }\n}\n"},"@openzeppelin/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `condition ? a : b`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `condition ? a : b`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // (a + b) / 2 can overflow.\n            return (a & b) + (a ^ b) / 2;\n        }\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory buffer) private pure returns (bool) {\n        uint256 chunk;\n        for (uint256 i = 0; i < buffer.length; i += 0x20) {\n            // See _unsafeReadBytesOffset from utils/Bytes.sol\n            assembly (\"memory-safe\") {\n                chunk := mload(add(add(buffer, 0x20), i))\n            }\n            if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n\n    /**\n     * @dev Counts the number of leading zero bits in a uint256.\n     */\n    function clz(uint256 x) internal pure returns (uint256) {\n        return ternary(x == 0, 256, 255 - log2(x));\n    }\n}\n"},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        if (!_safeTransfer(token, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        if (!_safeTransferFrom(token, from, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _safeTransfer(token, to, value, false);\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _safeTransferFrom(token, from, to, value, false);\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        if (!_safeApprove(token, spender, value, false)) {\n            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));\n            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the\n     * return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.transfer.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(to, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return\n     * value: the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param from The sender of the tokens\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value,\n        bool bubble\n    ) private returns (bool success) {\n        bytes4 selector = IERC20.transferFrom.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(from, shr(96, not(0))))\n            mstore(0x24, and(to, shr(96, not(0))))\n            mstore(0x44, value)\n            success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n            mstore(0x60, 0)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:\n     * the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param spender The spender of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.approve.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(spender, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n}\n"},"@openzeppelin/contracts/access/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},"@openzeppelin/contracts/access/Ownable2Step.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This extension of the {Ownable} contract includes a two-step mechanism to transfer\n * ownership, where the new owner must call {acceptOwnership} in order to replace the\n * old one. This can help prevent common mistakes, such as transfers of ownership to\n * incorrect accounts, or to contracts that are unable to interact with the\n * permission system.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     *\n     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n    mapping(address account => uint256) private _balances;\n\n    mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * Both values are immutable: they can only be set once during construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() public view virtual returns (uint256) {\n        return _totalSupply;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account) public view virtual returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            _totalSupply += value;\n        } else {\n            uint256 fromBalance = _balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                _balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                _totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                _balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        _allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance < type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"},"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20} from \"../ERC20.sol\";\nimport {Context} from \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n    /**\n     * @dev Destroys a `value` amount of tokens from the caller.\n     *\n     * See {ERC20-_burn}.\n     */\n    function burn(uint256 value) public virtual {\n        _burn(_msgSender(), value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, deducting from\n     * the caller's allowance.\n     *\n     * See {ERC20-_burn} and {ERC20-allowance}.\n     *\n     * Requirements:\n     *\n     * - the caller must have allowance for ``accounts``'s tokens of at least\n     * `value`.\n     */\n    function burnFrom(address account, uint256 value) public virtual {\n        _spendAllowance(account, _msgSender(), value);\n        _burn(account, value);\n    }\n}\n"},"@openzeppelin/contracts/interfaces/IERC1363.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},"@openzeppelin/contracts/utils/StorageSlot.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev A uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},"@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},"@openzeppelin/contracts/interfaces/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},"@openzeppelin/contracts/interfaces/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"}},"compilation":{"language":"Solidity","compiler":"solc","compilerVersion":"0.8.35+commit.47b9dedd","compilerSettings":{"viaIR":true,"optimizer":{"runs":200,"enabled":true},"evmVersion":"cancun"},"name":"BrishopLaunchDeployer","fullyQualifiedName":"src/BrishopLaunchDeployer.sol:BrishopLaunchDeployer"},"abi":[{"type":"constructor","inputs":[{"name":"factory_","type":"address","internalType":"address"},{"name":"escrow_","type":"address","internalType":"contract IBrishopFeeEscrow"},{"name":"vault_","type":"address","internalType":"contract BrishopBuybackVault"}],"stateMutability":"nonpayable"},{"name":"InvalidMetadata","type":"error","inputs":[]},{"name":"NotFactory","type":"error","inputs":[]},{"name":"buybackVault","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract BrishopBuybackVault"}],"stateMutability":"view"},{"name":"deployLaunch","type":"function","inputs":[{"name":"params","type":"tuple","components":[{"name":"name","type":"string","internalType":"string"},{"name":"symbol","type":"string","internalType":"string"},{"name":"logo","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"socials","type":"tuple","components":[{"name":"twitter","type":"string","internalType":"string"},{"name":"telegram","type":"string","internalType":"string"},{"name":"discord","type":"string","internalType":"string"},{"name":"website","type":"string","internalType":"string"},{"name":"farcaster","type":"string","internalType":"string"}],"internalType":"struct BrishopLauncherToken.Socials"},{"name":"creatorFeeRecipient","type":"address","internalType":"address"},{"name":"creatorTaxBps","type":"uint16","internalType":"uint16"},{"name":"buybackEnabled","type":"bool","internalType":"bool"},{"name":"expectedEconomics","type":"bytes32","internalType":"bytes32"},{"name":"salt","type":"bytes32","internalType":"bytes32"},{"name":"snipeTaxExemptions","type":"address[]","internalType":"address[]"}],"internalType":"struct TokenParams"},{"name":"terms","type":"tuple","components":[{"name":"pairToken","type":"address","internalType":"address"},{"name":"creator","type":"address","internalType":"address"},{"name":"phantomQuote","type":"uint256","internalType":"uint256"},{"name":"feeBps","type":"uint256","internalType":"uint256"},{"name":"creatorTaxBps","type":"uint256","internalType":"uint256"},{"name":"buybackEnabled","type":"bool","internalType":"bool"}],"internalType":"struct BrishopBondingCurve.Terms"},{"name":"policy","type":"tuple","components":[{"name":"protocolFeeRecipient","type":"address","internalType":"address"},{"name":"protocolFeeShareBps","type":"uint16","internalType":"uint16"},{"name":"buybackBurnBps","type":"uint16","internalType":"uint16"},{"name":"hookFeeBps","type":"uint16","internalType":"uint16"},{"name":"maxInternalPriceImpactBps","type":"uint16","internalType":"uint16"}],"internalType":"struct FeePolicySnapshot"},{"name":"creator","type":"address","internalType":"address"},{"name":"supply","type":"uint256","internalType":"uint256"},{"name":"creatorAllocation","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"token","type":"address","internalType":"address"},{"name":"curve","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"factory","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"feeEscrow","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBrishopFeeEscrow"}],"stateMutability":"view"}],"metadata":{"compiler":{"version":"0.8.35+commit.47b9dedd"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"factory_","type":"address"},{"internalType":"contract IBrishopFeeEscrow","name":"escrow_","type":"address"},{"internalType":"contract BrishopBuybackVault","name":"vault_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidMetadata","type":"error"},{"inputs":[],"name":"NotFactory","type":"error"},{"inputs":[],"name":"buybackVault","outputs":[{"internalType":"contract BrishopBuybackVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"description","type":"string"},{"components":[{"internalType":"string","name":"twitter","type":"string"},{"internalType":"string","name":"telegram","type":"string"},{"internalType":"string","name":"discord","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"farcaster","type":"string"}],"internalType":"struct BrishopLauncherToken.Socials","name":"socials","type":"tuple"},{"internalType":"address","name":"creatorFeeRecipient","type":"address"},{"internalType":"uint16","name":"creatorTaxBps","type":"uint16"},{"internalType":"bool","name":"buybackEnabled","type":"bool"},{"internalType":"bytes32","name":"expectedEconomics","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address[]","name":"snipeTaxExemptions","type":"address[]"}],"internalType":"struct TokenParams","name":"params","type":"tuple"},{"components":[{"internalType":"address","name":"pairToken","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"phantomQuote","type":"uint256"},{"internalType":"uint256","name":"feeBps","type":"uint256"},{"internalType":"uint256","name":"creatorTaxBps","type":"uint256"},{"internalType":"bool","name":"buybackEnabled","type":"bool"}],"internalType":"struct BrishopBondingCurve.Terms","name":"terms","type":"tuple"},{"components":[{"internalType":"address","name":"protocolFeeRecipient","type":"address"},{"internalType":"uint16","name":"protocolFeeShareBps","type":"uint16"},{"internalType":"uint16","name":"buybackBurnBps","type":"uint16"},{"internalType":"uint16","name":"hookFeeBps","type":"uint16"},{"internalType":"uint16","name":"maxInternalPriceImpactBps","type":"uint16"}],"internalType":"struct FeePolicySnapshot","name":"policy","type":"tuple"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"creatorAllocation","type":"uint256"}],"name":"deployLaunch","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"curve","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeEscrow","outputs":[{"internalType":"contract IBrishopFeeEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"src/BrishopLaunchDeployer.sol":"BrishopLaunchDeployer"},"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[],"viaIR":true},"sources":{"@openzeppelin/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","license":"MIT","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"]},"@openzeppelin/contracts/access/Ownable2Step.sol":{"keccak256":"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c","license":"MIT","urls":["bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0","dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek"]},"@openzeppelin/contracts/interfaces/IERC1363.sol":{"keccak256":"0xd5ea07362ab630a6a3dee4285a74cf2377044ca2e4be472755ad64d7c5d4b69d","license":"MIT","urls":["bzz-raw://da5e832b40fc5c3145d3781e2e5fa60ac2052c9d08af7e300dc8ab80c4343100","dweb:/ipfs/QmTzf7N5ZUdh5raqtzbM11yexiUoLC9z3Ws632MCuycq1d"]},"@openzeppelin/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","license":"MIT","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"]},"@openzeppelin/contracts/interfaces/IERC20.sol":{"keccak256":"0x1a6221315ce0307746c2c4827c125d821ee796c74a676787762f4778671d4f44","license":"MIT","urls":["bzz-raw://1bb2332a7ee26dd0b0de9b7fe266749f54820c99ab6a3bcb6f7e6b751d47ee2d","dweb:/ipfs/QmcRWpaBeCYkhy68PR3B4AgD7asuQk7PwkWxrvJbZcikLF"]},"@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"keccak256":"0x1b88b3fb3d85ba5496d7d5f396f83ee1fddcdd6762059ff65992655b67920998","license":"MIT","urls":["bzz-raw://89393bb3212da1c0889601b9706a07b39419ddc4d2faab9eaf6e7f9152cf6a1c","dweb:/ipfs/QmcCfzzxv1Bkdz1c1yF4gQCeYb6Us5BJANnzTFqawfd1HL"]},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"keccak256":"0x669464167428061ee0f8618b73b3ee90aff8405683e7ddde8cd77dadaa1afe29","license":"MIT","urls":["bzz-raw://0dda78587a7358b4fdf6b9fca0fde5a5e34930f36d5268a16028627fc0170195","dweb:/ipfs/QmQ1b6cCceDRWNxti9HifsTCzmVP25Haxs1bWugm52vTqH"]},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x74ed01eb66b923d0d0cfe3be84604ac04b76482a55f9dd655e1ef4d367f95bc2","license":"MIT","urls":["bzz-raw://5282825a626cfe924e504274b864a652b0023591fa66f06a067b25b51ba9b303","dweb:/ipfs/QmeCfPykghhMc81VJTrHTC7sF6CRvaA1FXVq2pJhwYp1dV"]},"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol":{"keccak256":"0x2659248df25e34000ed214b3dc8da2160bc39874c992b477d9e2b1b3283dc073","license":"MIT","urls":["bzz-raw://c345af1b0e7ea28d1216d6a04ab28f5534a5229b9edf9ca3cd0e84950ae58d26","dweb:/ipfs/QmY63jtSrYpLRe8Gj1ep2vMDCKxGNNG3hnNVKBVnrs2nmA"]},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"keccak256":"0xd6fa4088198f04eef10c5bce8a2f4d60554b7ec4b987f684393c01bf79b94d9f","license":"MIT","urls":["bzz-raw://f95ee0bbd4dd3ac730d066ba3e785ded4565e890dbec2fa7d3b9fe3bad9d0d6e","dweb:/ipfs/QmSLr6bHkPFWT7ntj34jmwfyskpwo97T9jZUrk5sz3sdtR"]},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"keccak256":"0x304d732678032a9781ae85c8f204c8fba3d3a5e31c02616964e75cfdc5049098","license":"MIT","urls":["bzz-raw://299ced486011781dc98f638059678323c03079fefae1482abaa2135b22fa92d0","dweb:/ipfs/QmbZNbcPTBxNvwChavN2kkZZs7xHhYL7mv51KrxMhsMs3j"]},"@openzeppelin/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","license":"MIT","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"]},"@openzeppelin/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","license":"MIT","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"]},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"keccak256":"0xa516cbf1c7d15d3517c2d668601ce016c54395bf5171918a14e2686977465f53","license":"MIT","urls":["bzz-raw://1e1d079e8edfb58efd23a311e315a4807b01b5d1cf153f8fa2d0608b9dec3e99","dweb:/ipfs/QmTBExeX2SDTkn5xbk5ssbYSx7VqRp9H4Ux1CY4uQM4b9N"]},"@openzeppelin/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","license":"MIT","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"]},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","license":"MIT","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"]},"@openzeppelin/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","license":"MIT","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"]},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","license":"MIT","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"]},"src/BrishopBondingCurve.sol":{"keccak256":"0x37fcd3f1b4529a9f0dbc316d071e1edf11ce3fafe2546c4ecc6f365c844f3db7","license":"MIT","urls":["bzz-raw://32a9404f802a8eb3efd56548240f9abdddb6c0f936bb95d9e05df54b0e4c0e26","dweb:/ipfs/QmTZCdLsbkGLMXAuRFY8mRf9VU5XX24K8x3qjCbpQh7nLm"]},"src/BrishopBuybackVault.sol":{"keccak256":"0x0becf05283bc8b8964a8d100e23b887a188c82c95fcad98e22f5217ffc9e58c9","license":"MIT","urls":["bzz-raw://137a6aaded4724a3474b3c08067693245523ed517a84aafc5c146353852bb32d","dweb:/ipfs/QmQ4JfAQYR3eqhowQgibERLGiTfowSnH1QRWY6D1983eFW"]},"src/BrishopLaunchDeployer.sol":{"keccak256":"0x0f81d31836aa2a5d416979c07a14635bf3d182e2a2e955e631cae8d0afe1d544","license":"MIT","urls":["bzz-raw://f6c655be8bfc3007ed89e0734a9a27d26bcd3ce27483c10648d605304b2f3526","dweb:/ipfs/QmUChkKtVzv31TgNXQY8FGaZqeajBj7QhPXXSHep9kj5pe"]},"src/BrishopLauncherToken.sol":{"keccak256":"0x1ebcf1534c80df8734078c6d29f4d03dc5ca76c762788065a845ea390452e428","license":"MIT","urls":["bzz-raw://41c43b23dc334d33209865364b3493cd9c44286868a9c94d97934bda862626f8","dweb:/ipfs/QmS7qZ19vCfUCYJEgLoKKG7hbpkHpP2Dps9SH6WMh52xt6"]},"src/interfaces/IBrishop.sol":{"keccak256":"0x329d57dfed260932f89ed7a9f0b91ed7236e12777f41ebf8599495ce294a8d2f","license":"MIT","urls":["bzz-raw://dd6053f039743beb42223b3228361129753dce8717c96291dba5820e52ef9892","dweb:/ipfs/QmeSF8Mo9XyXb3ZGp8ns6h2cLo1G8n4f8UyyUoHe8w4piF"]},"src/libraries/BrishopBondingCurveMath.sol":{"keccak256":"0x0d3088350d2c58adce273486980851b3a34b6a85705ca2b681846fca118fc75b","license":"MIT","urls":["bzz-raw://76441b39e6db97858be47e1d98ae0fde65f2060b4089f8a8395776c976ed28f5","dweb:/ipfs/QmcmmXMjzzRKKJbLJUo9tjpeikd65iGCG8Q1hdR19jjGDt"]}},"version":1},"storageLayout":{"types":null,"storage":[]},"transientStorageLayout":{"types":null,"storage":[]},"userdoc":{"kind":"user","methods":{},"version":1},"devdoc":{"kind":"dev","methods":{},"version":1},"sourceIds":{"src/BrishopBondingCurve.sol":{"id":18},"src/BrishopBuybackVault.sol":{"id":19},"src/interfaces/IBrishop.sol":{"id":25},"src/BrishopLauncherToken.sol":{"id":24},"src/BrishopLaunchDeployer.sol":{"id":22},"@openzeppelin/contracts/utils/Panic.sol":{"id":12},"@openzeppelin/contracts/utils/Context.sol":{"id":11},"src/libraries/BrishopBondingCurveMath.sol":{"id":26},"@openzeppelin/contracts/access/Ownable.sol":{"id":0},"@openzeppelin/contracts/utils/math/Math.sol":{"id":16},"@openzeppelin/contracts/interfaces/IERC20.sol":{"id":4},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"id":6},"@openzeppelin/contracts/utils/StorageSlot.sol":{"id":14},"@openzeppelin/contracts/interfaces/IERC165.sol":{"id":3},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"id":7},"@openzeppelin/contracts/access/Ownable2Step.sol":{"id":1},"@openzeppelin/contracts/interfaces/IERC1363.sol":{"id":2},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"id":17},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"id":13},"@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"id":5},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"id":10},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"id":15},"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol":{"id":8},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"id":9}},"additionalInput":null,"stdJsonInput":{"sources":{"src/BrishopBondingCurve.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from PONS v2's verified curve; see ../NOTICE.md and upstream provenance.\npragma solidity ^0.8.26;\n\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {BrishopBondingCurveMath} from \"./libraries/BrishopBondingCurveMath.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {FeePolicySnapshot, IBrishopFeeEscrow, IBrishopFeePolicy, IBrishopSnipeTax} from \"./interfaces/IBrishop.sol\";\n\n/// @notice Permanent constant-product market. Phantom quote sets pricing; only\n/// actual quote reserves, excluding earned fees, can fund a sell.\ncontract BrishopBondingCurve is ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    uint256 private constant BPS = 10_000;\n    uint256 public constant MAX_RESERVE = type(uint128).max;\n\n    struct BuyQuote { uint256 tokensOut; uint256 fee; uint256 tax; uint256 snipeTax; }\n    struct SellQuote { uint256 quoteOut; uint256 grossQuoteOut; uint256 fee; uint256 tax; bool reserveSufficient; }\n    struct Terms {\n        address pairToken;\n        address creator;\n        uint256 phantomQuote;\n        uint256 feeBps;\n        uint256 creatorTaxBps;\n        bool buybackEnabled;\n    }\n    error ZeroAddress();\n    error ZeroAmount();\n    error NotFactory();\n    error AlreadyInitialized();\n    error NotInitialized();\n    error InvalidLaunchEconomics();\n    error InvalidFeePolicy();\n    error ReserveLimit();\n    error DeadlineExpired();\n    error SlippageExceeded(uint256 actual, uint256 minimum);\n    error InsufficientRealReserve(uint256 required, uint256 available);\n    error NativeValueMismatch(uint256 supplied, uint256 expected);\n    error UnexpectedNativeValue();\n    error TransferFailed();\n    error NotFeeSweepOperator();\n    error InternalSwapRequiresOperator();\n    error MinimumOutputRequired();\n\n    event Initialized(address token);\n    event CurveBuy(address indexed buyer, address indexed recipient, uint256 quoteIn, uint256 tokensOut, uint256 fee, uint256 tax);\n    event CurveSell(address indexed seller, address indexed recipient, uint256 tokensIn, uint256 quoteOut, uint256 fee, uint256 tax);\n    event ReservesUpdated(uint256 realQuote, uint256 tokens);\n    event SnipeTaxExempted(address indexed account);\n    event SnipeTaxCharged(address indexed recipient, uint256 amount);\n    event CreatorFeeRecipientUpdated(address indexed previousRecipient, address indexed newRecipient);\n    event BuybackEnabledUpdated(bool enabled);\n    event FeesSwept(uint256 protocolAmount, uint256 buybackAmount, uint256 creatorAmount);\n    event BuybackLocked(uint256 quoteSpent, uint256 tokensLocked);\n\n    address public token;\n    address public immutable pairToken;\n    address public deployer;\n    address public immutable factory;\n    IBrishopFeePolicy public immutable feePolicy;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    address public immutable protocolFeeRecipient;\n    address public immutable buybackCreatorRecipient;\n    uint16 public immutable protocolFeeShareBps;\n    uint16 public immutable buybackBurnBps;\n    uint16 public immutable maxInternalPriceImpactBps;\n    uint256 public immutable phantomQuote;\n    uint256 public immutable feeBps;\n    uint256 public immutable creatorTaxBps;\n    bool public buybackEnabled;\n    uint256 public quoteFeeBalance;\n    uint256 public buybackQuoteBalance;\n    uint256 public creatorTaxBalance;\n    uint256 public trackedQuote;\n    uint256 public trackedTokens;\n    uint256 public launchSupply;\n    uint256 public launchedAt;\n    uint256 public snipeTaxStartBps;\n    uint256 public snipeTaxSeconds;\n    mapping(address => bool) public snipeTaxExempt;\n\n    modifier onlyFactory() { if (msg.sender != factory) revert NotFactory(); _; }\n    modifier onlyInitialized() { if (token == address(0)) revert NotInitialized(); _; }\n\n    constructor(address factory_, IBrishopFeeEscrow escrow_, BrishopBuybackVault vault_, FeePolicySnapshot memory policy, Terms memory terms) {\n        if (factory_ == address(0) || address(escrow_) == address(0) || address(vault_) == address(0) || terms.creator == address(0)) revert ZeroAddress();\n        if (policy.protocolFeeRecipient == address(0) || policy.protocolFeeShareBps > BPS || policy.buybackBurnBps > BPS || policy.maxInternalPriceImpactBps == 0 || policy.maxInternalPriceImpactBps >= BPS || terms.feeBps + terms.creatorTaxBps > 2_000) revert InvalidFeePolicy();\n        if (terms.phantomQuote == 0 || terms.phantomQuote > MAX_RESERVE) revert InvalidLaunchEconomics();\n        factory = factory_;\n        feePolicy = IBrishopFeePolicy(factory_);\n        feeEscrow = escrow_;\n        buybackVault = vault_;\n        pairToken = terms.pairToken;\n        deployer = terms.creator;\n        protocolFeeRecipient = policy.protocolFeeRecipient;\n        buybackCreatorRecipient = terms.creator;\n        protocolFeeShareBps = policy.protocolFeeShareBps;\n        buybackBurnBps = policy.buybackBurnBps;\n        maxInternalPriceImpactBps = policy.maxInternalPriceImpactBps;\n        phantomQuote = terms.phantomQuote;\n        feeBps = terms.feeBps;\n        creatorTaxBps = terms.creatorTaxBps;\n        buybackEnabled = terms.buybackEnabled;\n    }\n\n    /// @dev The caller supplies the complete immutable exemption list atomically\n    /// at initialization. There is no way to add exemptions to a live pool.\n    function initialize(address token_, address[] calldata exemptions) external onlyFactory {\n        if (token != address(0)) revert AlreadyInitialized();\n        if (token_ == address(0) || token_ == pairToken) revert ZeroAddress();\n        uint256 received = IERC20(token_).balanceOf(address(this));\n        uint256 supply = IERC20(token_).totalSupply();\n        if (received == 0 || received > supply || supply > MAX_RESERVE || exemptions.length > 34) revert InvalidLaunchEconomics();\n        token = token_;\n        launchSupply = supply;\n        trackedTokens = received;\n        launchedAt = block.timestamp;\n        snipeTaxStartBps = IBrishopSnipeTax(factory).snipeTaxStartBps();\n        snipeTaxSeconds = IBrishopSnipeTax(factory).snipeTaxSeconds();\n        if (snipeTaxStartBps > 9_900 || snipeTaxSeconds == 0 || snipeTaxSeconds > 1 days) revert InvalidFeePolicy();\n        for (uint256 i; i < exemptions.length; ++i) {\n            if (exemptions[i] == address(0)) revert ZeroAddress();\n            snipeTaxExempt[exemptions[i]] = true;\n            emit SnipeTaxExempted(exemptions[i]);\n        }\n        emit Initialized(token_);\n        emit ReservesUpdated(0, received);\n    }\n\n    function isNativeQuote() public view returns (bool) { return pairToken == address(0); }\n    function realQuoteReserve() public view returns (uint256) { return trackedQuote - quoteFeeBalance - creatorTaxBalance; }\n    function getReserves() public view returns (uint256 quote, uint256 tokens) { return (phantomQuote + realQuoteReserve(), trackedTokens); }\n    function quoteReserve() external view returns (uint256) { return phantomQuote + realQuoteReserve(); }\n    function tokenReserve() external view returns (uint256) { return trackedTokens; }\n\n    /// @notice PONS's verified fourteen-halving decay; the live three-second\n    /// default produces 9900, 618, 19, 0 bps before the combined-fee cap.\n    function currentSnipeTaxBps(address recipient) public view returns (uint256) {\n        if (snipeTaxExempt[recipient] || snipeTaxStartBps == 0) return 0;\n        uint256 elapsed = block.timestamp - launchedAt;\n        if (elapsed >= snipeTaxSeconds) return 0;\n        return snipeTaxStartBps >> ((elapsed * 14) / snipeTaxSeconds);\n    }\n\n    function quoteBuy(uint256 quoteIn, address recipient) public view onlyInitialized returns (BuyQuote memory q) {\n        if (recipient == address(0)) revert ZeroAddress();\n        if (quoteIn == 0) revert ZeroAmount();\n        if (quoteIn > MAX_RESERVE - phantomQuote - trackedQuote) revert ReserveLimit();\n        uint256 snipeBps = currentSnipeTaxBps(recipient);\n        uint256 maxSnipe = BPS - feeBps - creatorTaxBps - 100;\n        if (snipeBps > maxSnipe) snipeBps = maxSnipe;\n        q.fee = Math.mulDiv(quoteIn, feeBps, BPS);\n        q.tax = Math.mulDiv(quoteIn, creatorTaxBps, BPS);\n        q.snipeTax = Math.mulDiv(quoteIn, snipeBps, BPS);\n        (uint256 quote, uint256 tokens) = getReserves();\n        q.tokensOut = BrishopBondingCurveMath.getAmountOut(quoteIn - q.fee - q.tax - q.snipeTax, quote, tokens, 0);\n    }\n\n    function quoteSell(uint256 tokensIn) public view onlyInitialized returns (SellQuote memory q) {\n        if (tokensIn == 0) revert ZeroAmount();\n        if (tokensIn > MAX_RESERVE - trackedTokens) revert ReserveLimit();\n        (uint256 quote, uint256 tokens) = getReserves();\n        q.grossQuoteOut = BrishopBondingCurveMath.getAmountOut(tokensIn, tokens, quote, 0);\n        q.fee = Math.mulDiv(q.grossQuoteOut, feeBps, BPS);\n        q.tax = Math.mulDiv(q.grossQuoteOut, creatorTaxBps, BPS);\n        q.quoteOut = q.grossQuoteOut - q.fee - q.tax;\n        q.reserveSufficient = q.grossQuoteOut <= realQuoteReserve();\n    }\n\n    function buy(uint256 quoteIn, uint256 minTokensOut, address recipient, uint256 deadline) external payable nonReentrant onlyInitialized returns (uint256 tokensOut) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        uint256 received = _receiveQuote(quoteIn);\n        BuyQuote memory q = quoteBuy(received, recipient);\n        tokensOut = q.tokensOut;\n        if (tokensOut < minTokensOut) revert SlippageExceeded(tokensOut, minTokensOut);\n        _accrueFees(q.fee + q.snipeTax, q.tax);\n        trackedQuote += received;\n        trackedTokens -= tokensOut;\n        IERC20(token).safeTransfer(recipient, tokensOut);\n        if (q.snipeTax != 0) emit SnipeTaxCharged(recipient, q.snipeTax);\n        emit CurveBuy(msg.sender, recipient, received, tokensOut, q.fee + q.snipeTax, q.tax);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n\n    function sell(uint256 tokensIn, uint256 minQuoteOut, address recipient, uint256 deadline) external nonReentrant onlyInitialized returns (uint256 quoteOut) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        if (recipient == address(0)) revert ZeroAddress();\n        SellQuote memory q = quoteSell(tokensIn);\n        if (!q.reserveSufficient) revert InsufficientRealReserve(q.grossQuoteOut, realQuoteReserve());\n        quoteOut = q.quoteOut;\n        if (quoteOut < minQuoteOut) revert SlippageExceeded(quoteOut, minQuoteOut);\n        IERC20(token).safeTransferFrom(msg.sender, address(this), tokensIn);\n        _accrueFees(q.fee, q.tax);\n        trackedQuote -= quoteOut;\n        trackedTokens += tokensIn;\n        _sendQuote(recipient, quoteOut);\n        emit CurveSell(msg.sender, recipient, tokensIn, quoteOut, q.fee, q.tax);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n\n    function setCreatorFeeRecipient(address recipient) external onlyFactory {\n        if (recipient == address(0)) revert ZeroAddress();\n        emit CreatorFeeRecipientUpdated(deployer, recipient);\n        deployer = recipient;\n    }\n    function setBuybackEnabled(bool enabled) external onlyFactory { buybackEnabled = enabled; emit BuybackEnabledUpdated(enabled); }\n\n    function _receiveQuote(uint256 amount) private returns (uint256) {\n        if (isNativeQuote()) {\n            if (msg.value != amount) revert NativeValueMismatch(msg.value, amount);\n            return amount;\n        }\n        if (msg.value != 0) revert UnexpectedNativeValue();\n        uint256 beforeBalance = IERC20(pairToken).balanceOf(address(this));\n        IERC20(pairToken).safeTransferFrom(msg.sender, address(this), amount);\n        return IERC20(pairToken).balanceOf(address(this)) - beforeBalance;\n    }\n    function _sendQuote(address recipient, uint256 amount) private {\n        if (isNativeQuote()) {\n            (bool sent,) = payable(recipient).call{value: amount}(\"\");\n            if (!sent) revert TransferFailed();\n        } else IERC20(pairToken).safeTransfer(recipient, amount);\n    }\n    function _creditQuote(address recipient, uint256 amount) private {\n        if (isNativeQuote()) feeEscrow.credit{value: amount}(recipient);\n        else {\n            IERC20(pairToken).forceApprove(address(feeEscrow), amount);\n            feeEscrow.creditToken(recipient, pairToken, amount);\n        }\n    }\n    function _accrueFees(uint256 fee, uint256 tax) private {\n        quoteFeeBalance += fee;\n        creatorTaxBalance += tax;\n        if (buybackEnabled && fee != 0) {\n            uint256 creatorSlice = fee - Math.mulDiv(fee, protocolFeeShareBps, BPS);\n            buybackQuoteBalance += Math.mulDiv(creatorSlice, buybackBurnBps, BPS);\n        }\n    }\n\n    /// @notice PONS fee sweep and five-year buyback behavior, with its former\n    /// graduation inventory limit removed. Minimum output bounds buyback swaps.\n    function sweepFees(uint256 minBuybackTokensOut) external nonReentrant onlyInitialized {\n        bool operator = msg.sender == feePolicy.feeSweepOperator();\n        if (!operator && msg.sender != deployer) revert NotFeeSweepOperator();\n        if (!operator && buybackQuoteBalance != 0) revert InternalSwapRequiresOperator();\n        uint256 pending = quoteFeeBalance;\n        uint256 tax = creatorTaxBalance;\n        if (pending == 0 && tax == 0) return;\n        uint256 protocolAmount = Math.mulDiv(pending, protocolFeeShareBps, BPS);\n        uint256 creatorBucket = pending - protocolAmount;\n        uint256 buybackAmount = Math.min(buybackQuoteBalance, creatorBucket);\n        uint256 creatorAmount = creatorBucket - buybackAmount + tax;\n        uint256 tokensLocked;\n        if (buybackAmount != 0) {\n            if (minBuybackTokensOut == 0) revert MinimumOutputRequired();\n            (uint256 quote, uint256 tokens) = getReserves();\n            uint256 movementBps = Math.mulDiv(buybackAmount, BPS, quote + buybackAmount);\n            if (movementBps <= maxInternalPriceImpactBps) tokensLocked = BrishopBondingCurveMath.quoteAmountOut(buybackAmount, quote, tokens, 0);\n            if (tokensLocked == 0) { creatorAmount += buybackAmount; buybackAmount = 0; }\n            else if (tokensLocked < minBuybackTokensOut) revert SlippageExceeded(tokensLocked, minBuybackTokensOut);\n        }\n        quoteFeeBalance = 0;\n        creatorTaxBalance = 0;\n        buybackQuoteBalance = 0;\n        trackedQuote -= protocolAmount + creatorAmount;\n        if (tokensLocked != 0) {\n            trackedTokens -= tokensLocked;\n            IERC20(token).forceApprove(address(buybackVault), tokensLocked);\n            buybackVault.lock(token, tokensLocked, buybackCreatorRecipient, protocolFeeRecipient, protocolFeeShareBps);\n            emit BuybackLocked(buybackAmount, tokensLocked);\n        }\n        if (protocolAmount != 0) _creditQuote(protocolFeeRecipient, protocolAmount);\n        if (creatorAmount != 0) _creditQuote(deployer, creatorAmount);\n        emit FeesSwept(protocolAmount, buybackAmount, creatorAmount);\n        emit ReservesUpdated(realQuoteReserve(), trackedTokens);\n    }\n}\n"},"src/BrishopBuybackVault.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IBrishopFeeEscrow, IBrishopFeePolicy, IBrishopLaunchFactory} from \"./interfaces/IBrishop.sol\";\n\n/**\n * @title BrishopBuybackVault\n * @notice Holds every launch's bought-back memecoin supply and releases it\n * linearly over five years instead of burning it immediately, splitting\n * every release between the creator and the protocol on the launch's\n * recorded fee shares. One shared deployment serves every launch, the same\n * \"single deployment for every token\" pattern BrishopFeeEscrow already uses.\n *\n * Note that the split applies to the release, not to the funding. The\n * permanent curve carves the buyback slice out of the creator's share of\n * the fees alone, so the creator funds the entire lock and then receives\n * only their fee share of it back. Enabling a buyback therefore moves value\n * from the creator to the protocol relative to taking the fees directly,\n * by an amount that grows with `buybackBurnBps`.\n *\n * Deposits use a weighted-average vesting clock instead of per-deposit\n * tranches: a launch's fee sweep can add to its lock on every single sweep,\n * and tracking an unbounded array of tranches would make `release()`'s gas\n * cost grow forever. Instead, each new deposit shifts the launch's single\n * `vestingStart` forward by an amount proportional to the deposit's share\n * of the new total, so a large existing lock is barely disturbed by a small\n * top-up, and a small existing lock is pulled close to the new deposit's own\n * clock. `vestedAmount` at any time reflects a fair, size-weighted blend\n * across every deposit made so far.\n */\ncontract BrishopBuybackVault is Ownable2Step, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n\n    struct LaunchVest {\n        uint256 totalLocked;\n        uint256 totalReleased;\n        uint256 vestingStart;\n        uint256 vestedUnreleased;\n        uint256 unvestedAmount;\n        uint256 lastUpdate;\n        uint256 vestingEnd;\n        address creatorRecipient;\n        address protocolRecipient;\n        uint16 protocolFeeShareBps;\n    }\n\n    uint256 private constant BASIS_POINTS = 10_000;\n    uint256 public constant VESTING_DURATION = 5 * 365 days;\n\n    error ZeroAddress();\n    error AlreadyInitialized();\n    error NotFactory();\n    error NotAuthorizedLocker();\n    error NotVestBeneficiary();\n    error InvalidVestingTerms();\n    error VestingTermsMismatch();\n    error OwnershipCannotBeRenounced();\n\n    event FactorySet(address factory);\n    event Locked(address indexed token, address indexed depositor, uint256 amount, uint256 newVestingStart);\n    event VestingTermsSnapshotted(\n        address indexed token,\n        address indexed creatorRecipient,\n        address indexed protocolRecipient,\n        uint256 protocolFeeShareBps\n    );\n    event Released(address indexed token, uint256 creatorAmount, uint256 protocolAmount);\n    event CreatorRecipientUpdated(\n        address indexed token, address indexed previousRecipient, address indexed newRecipient\n    );\n\n    IBrishopFeePolicy public immutable feePolicy;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    address public factory;\n\n    mapping(address token => LaunchVest) private _vaults;\n\n    /**\n     * @param initialOwner Administrative owner; only used to wire the factory once.\n     * @param feePolicy_ Shared Brishop protocol/creator fee policy.\n     * @param feeEscrow_ Shared claimable balance ledger releases are paid through.\n     */\n    constructor(address initialOwner, IBrishopFeePolicy feePolicy_, IBrishopFeeEscrow feeEscrow_) Ownable(initialOwner) {\n        if (address(feePolicy_) == address(0) || address(feeEscrow_) == address(0)) revert ZeroAddress();\n        feePolicy = feePolicy_;\n        feeEscrow = feeEscrow_;\n    }\n\n    /**\n     * @notice One-time wiring of the v2 factory, set after both are\n     * deployed, used to authorize each launch's bonding curve as a locker.\n     */\n    function setFactory(address factory_) external onlyOwner {\n        if (factory != address(0)) revert AlreadyInitialized();\n        if (factory_ == address(0)) revert ZeroAddress();\n        factory = factory_;\n        emit FactorySet(factory_);\n    }\n\n    /**\n     * @notice Permanently disabled. Ownership here exists only to perform the\n     * one-time factory wiring, and renouncing before that wiring would strand\n     * every future buyback lock.\n     */\n    function renounceOwnership() public pure override {\n        revert OwnershipCannotBeRenounced();\n    }\n\n    /**\n     * @notice Locks `amount` of `token` into its five-year vest, preserving\n     * the supplied beneficiaries and split for the active vesting epoch.\n     * Restricted to this token's registered Brishop curve, looked up live\n     * from the factory.\n     */\n    function lock(\n        address token,\n        uint256 amount,\n        address creatorRecipient,\n        address protocolRecipient,\n        uint16 protocolFeeShareBps\n    ) external nonReentrant {\n        if (token == address(0)) revert ZeroAddress();\n        if (factory == address(0)) revert NotFactory();\n        if (!_isAuthorizedLocker(token, msg.sender)) revert NotAuthorizedLocker();\n        if (amount == 0) return;\n        if (creatorRecipient == address(0) || protocolRecipient == address(0) || protocolFeeShareBps > BASIS_POINTS) {\n            revert InvalidVestingTerms();\n        }\n\n        // Schedule against what arrived, not what was asked for. Recording a\n        // nominal amount the vault never received would make the final\n        // release of the epoch revert on its own balance, stranding the tail\n        // of the vest. Every other ERC-20 boundary in the protocol measures\n        // this delta; this one is no different for being fed by our own\n        // launcher token today.\n        uint256 balanceBefore = IERC20(token).balanceOf(address(this));\n        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n        amount = IERC20(token).balanceOf(address(this)) - balanceBefore;\n        if (amount == 0) return;\n\n        LaunchVest storage v = _vaults[token];\n        uint256 nowTs = block.timestamp;\n        _checkpoint(v, nowTs);\n        _setOrValidateVestingTerms(v, token, creatorRecipient, protocolRecipient, protocolFeeShareBps);\n\n        uint256 existingUnvested = v.unvestedAmount;\n        uint256 combinedAmount = existingUnvested + amount;\n        uint256 remainingDuration = existingUnvested == 0 ? 0 : v.vestingEnd - nowTs;\n        uint256 combinedDuration = (existingUnvested * remainingDuration + amount * VESTING_DURATION) / combinedAmount;\n\n        v.unvestedAmount = combinedAmount;\n        v.lastUpdate = nowTs;\n        v.vestingEnd = nowTs + combinedDuration;\n        v.vestingStart = nowTs - (VESTING_DURATION - combinedDuration);\n        v.totalLocked += amount;\n\n        emit Locked(token, msg.sender, amount, v.vestingStart);\n    }\n\n    /**\n     * @notice Releases every currently vested, not-yet-released token for\n     * `token`, using the beneficiaries and split frozen for its active\n     * vesting epoch.\n     * @dev Restricted to the two parties a release pays. Letting anyone\n     * choose when value leaves the vest is harmful in two ways. A caller can\n     * time a release inside the protocol owner's creator-recipient recovery\n     * window, flushing vested tokens to the very address the recovery exists\n     * to abandon. A caller can also advance the checkpoint every second, so\n     * each step rounds its newly vested amount down to zero and the vest\n     * stalls without ever paying out.\n     */\n    function release(address token) external nonReentrant returns (uint256 released) {\n        if (factory == address(0)) revert NotFactory();\n\n        LaunchVest storage v = _vaults[token];\n        if (msg.sender != v.creatorRecipient && msg.sender != v.protocolRecipient) revert NotVestBeneficiary();\n\n        _checkpoint(v, block.timestamp);\n        released = v.vestedUnreleased;\n        if (released == 0) return 0;\n        v.vestedUnreleased = 0;\n        v.totalReleased += released;\n\n        uint256 protocolAmount = (released * v.protocolFeeShareBps) / BASIS_POINTS;\n        uint256 creatorAmount = released - protocolAmount;\n\n        IERC20(token).forceApprove(address(feeEscrow), released);\n        if (protocolAmount != 0) feeEscrow.creditToken(v.protocolRecipient, token, protocolAmount);\n        if (creatorAmount != 0) feeEscrow.creditToken(v.creatorRecipient, token, creatorAmount);\n\n        emit Released(token, creatorAmount, protocolAmount);\n    }\n\n    /**\n     * @notice Redirects a launch's buyback vest to a new creator recipient.\n     * Restricted to the factory, which forwards both self-service creator\n     * transfers and protocol-owner recovery overrides here, so vested\n     * buyback tokens track the same recipient as immediate creator fees\n     * rather than remaining stranded on the launch-time address. Vested but\n     * not-yet-released tokens follow the new recipient too, matching the\n     * intent of wallet recovery. Only the protocol split terms stay bound to\n     * the launch snapshot; the creator identity is managed here instead.\n     */\n    function updateCreatorRecipient(address token, address newRecipient) external {\n        if (msg.sender != factory) revert NotFactory();\n        if (token == address(0) || newRecipient == address(0)) revert ZeroAddress();\n\n        LaunchVest storage v = _vaults[token];\n        address previousRecipient = v.creatorRecipient;\n        if (previousRecipient == newRecipient) return;\n        v.creatorRecipient = newRecipient;\n        emit CreatorRecipientUpdated(token, previousRecipient, newRecipient);\n    }\n\n    /**\n     * @notice Total amount of `token` ever locked into this vault.\n     */\n    function totalLocked(address token) external view returns (uint256) {\n        return _vaults[token].totalLocked;\n    }\n\n    /**\n     * @notice Total amount of `token` already released from this vault.\n     */\n    function totalReleased(address token) external view returns (uint256) {\n        return _vaults[token].totalReleased;\n    }\n\n    /**\n     * @notice The launch's current weighted-average vesting start time.\n     * @dev Reporting only. Vesting is accounted from `vestedUnreleased`,\n     * `unvestedAmount`, `lastUpdate` and `vestingEnd`, which are settled on\n     * every lock and release. Interpolating this value against\n     * `VESTING_DURATION` will not reproduce `vestedAmount`, because already\n     * vested tokens are banked at each deposit rather than recomputed from\n     * the shifted clock. Read `vestedAmount` for the authoritative figure.\n     */\n    function vestingStart(address token) external view returns (uint256) {\n        return _vaults[token].vestingStart;\n    }\n\n    /**\n     * @notice Amount of `token` vested so far, released or not.\n     */\n    function vestedAmount(address token) external view returns (uint256) {\n        return _vestedAmount(_vaults[token]);\n    }\n\n    /**\n     * @notice Amount of `token` currently releasable: vested but not yet released.\n     */\n    function releasable(address token) external view returns (uint256) {\n        LaunchVest storage v = _vaults[token];\n        return v.vestedUnreleased + _previewNewlyVested(v, block.timestamp);\n    }\n\n    /**\n     * @notice Returns the immutable terms for the token's active vesting epoch.\n     */\n    function vestingTerms(address token)\n        external\n        view\n        returns (address creatorRecipient, address protocolRecipient, uint16 protocolFeeShareBps)\n    {\n        LaunchVest storage v = _vaults[token];\n        return (v.creatorRecipient, v.protocolRecipient, v.protocolFeeShareBps);\n    }\n\n    /**\n     * @dev Linear vest over VESTING_DURATION from the launch's current\n     * weighted-average start time, capped at the total ever locked.\n     */\n    function _vestedAmount(LaunchVest storage v) private view returns (uint256) {\n        return v.totalReleased + v.vestedUnreleased + _previewNewlyVested(v, block.timestamp);\n    }\n\n    /**\n     * @dev Crystallizes the linear portion vested since the previous state\n     * update while preserving the existing schedule's maturity.\n     */\n    function _checkpoint(LaunchVest storage v, uint256 nowTs) private {\n        uint256 newlyVested = _previewNewlyVested(v, nowTs);\n        if (newlyVested != 0) {\n            v.unvestedAmount -= newlyVested;\n            v.vestedUnreleased += newlyVested;\n        }\n        v.lastUpdate = nowTs;\n    }\n\n    /**\n     * @dev Previews how much of the active schedule vested since lastUpdate.\n     */\n    function _previewNewlyVested(LaunchVest storage v, uint256 nowTs) private view returns (uint256) {\n        if (v.unvestedAmount == 0 || nowTs <= v.lastUpdate) return 0;\n        if (nowTs >= v.vestingEnd) return v.unvestedAmount;\n\n        uint256 remainingDuration = v.vestingEnd - v.lastUpdate;\n        uint256 elapsed = nowTs - v.lastUpdate;\n        return (v.unvestedAmount * elapsed) / remainingDuration;\n    }\n\n    /**\n     * @dev A new epoch begins only after every token in the prior epoch has\n     * been released. This keeps every active weighted-average vest bound to\n     * one immutable set of beneficiaries without unbounded tranche storage.\n     */\n    function _setOrValidateVestingTerms(\n        LaunchVest storage v,\n        address token,\n        address creatorRecipient,\n        address protocolRecipient,\n        uint16 protocolFeeShareBps\n    ) private {\n        bool newEpoch = v.unvestedAmount == 0 && v.vestedUnreleased == 0;\n        if (newEpoch) {\n            // Seed the buyback beneficiary only when it has never been set.\n            // Once the factory has redirected the vest through\n            // updateCreatorRecipient (a creator transfer or a protocol\n            // recovery override), a later lock must not silently reset it\n            // back to the launch-time recipient, even across a fresh epoch.\n            if (v.creatorRecipient == address(0)) {\n                v.creatorRecipient = creatorRecipient;\n            }\n            v.protocolRecipient = protocolRecipient;\n            v.protocolFeeShareBps = protocolFeeShareBps;\n            emit VestingTermsSnapshotted(token, v.creatorRecipient, protocolRecipient, protocolFeeShareBps);\n            return;\n        }\n\n        // The creator recipient is deliberately excluded from this check: it\n        // is managed independently through updateCreatorRecipient, so recovery\n        // can move the vest without ever bricking a subsequent lock on a terms\n        // mismatch. The protocol split terms remain immutable per launch.\n        if (v.protocolRecipient != protocolRecipient || v.protocolFeeShareBps != protocolFeeShareBps) {\n            revert VestingTermsMismatch();\n        }\n    }\n\n    /**\n     * @dev Only the token's own registered curve may lock its buybacks.\n     * No per-launch administrator action or shared external hook is needed.\n     */\n    function _isAuthorizedLocker(address token, address caller) private view returns (bool) {\n        if (factory == address(0)) return false;\n        return caller == IBrishopLaunchFactory(factory).getLaunchedToken(token).curve;\n    }\n}\n"},"src/interfaces/IBrishop.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ninterface IBrishopFeeEscrow {\n    function credit(address recipient) external payable;\n    function creditToken(address recipient, address token, uint256 amount) external;\n    function claim() external returns (uint256);\n    function claim(uint256 amount) external returns (uint256);\n    function claimToken(address token) external returns (uint256);\n    function claimToken(address token, uint256 amount) external returns (uint256);\n    function balanceOf(address recipient) external view returns (uint256);\n    function balanceOfToken(address recipient, address token) external view returns (uint256);\n}\n\n// Names retained from PONS for fee-policy compatibility. buybackBurnBps funds\n// purchases locked in the five-year vault; it does not burn those tokens.\nstruct FeePolicySnapshot {\n    address protocolFeeRecipient;\n    uint16 protocolFeeShareBps;\n    uint16 buybackBurnBps;\n    uint16 hookFeeBps;\n    uint16 maxInternalPriceImpactBps;\n}\n\ninterface IBrishopFeePolicy {\n    function feeSweepOperator() external view returns (address);\n    function currentFeePolicy() external view returns (FeePolicySnapshot memory);\n}\n\ninterface IBrishopSnipeTax {\n    function snipeTaxStartBps() external view returns (uint256);\n    function snipeTaxSeconds() external view returns (uint256);\n}\n\ninterface IBrishopLaunchFactory {\n    struct LaunchedToken {\n        address token;\n        address curve;\n        address deployer;\n        address creatorFeeRecipient;\n        address pairToken;\n        uint16 creatorTaxBps;\n        bool buybackEnabled;\n        bool personality;\n        bool exists;\n    }\n    function getLaunchedToken(address token) external view returns (LaunchedToken memory);\n}\n"},"src/BrishopLauncherToken.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Burnable} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\n/**\n * @title BrishopLauncherToken\n * @notice Fixed-supply ERC-20 deployed by BrishopLaunchFactory for a v2 launch.\n * Community supply mints to the curve. An administrator personality launch\n * assigns 25% to its creator and 75% to the curve. Purchases are limited by\n * curve pricing and inventory. `deployer` is carried here\n * as immutable reference data for off-chain attribution only, and confers no\n * privileges over the token.\n * `ERC20Burnable` lets any holder voluntarily burn their own balance; the\n * protocol's buyback mechanism does not use it, bought-back tokens are\n * locked into `BrishopBuybackVault` for a five-year vest instead of being\n * burned.\n */\ncontract BrishopLauncherToken is ERC20, ERC20Burnable {\n    struct Socials {\n        string twitter;\n        string telegram;\n        string discord;\n        string website;\n        string farcaster;\n    }\n\n    error ZeroAddress();\n    error InvalidAllocation();\n\n    address public immutable deployer;\n    address public immutable launchFactory;\n    address public immutable curve;\n    uint256 public immutable initialSupply;\n    uint256 public immutable initialCreatorAllocation;\n\n    string public logo;\n    string public description;\n\n    Socials private _socials;\n\n    /**\n     * @notice Mints the fixed initial supply between the curve and creator allocation.\n     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        string memory logo_,\n        string memory description_,\n        Socials memory socials_,\n        address deployer_,\n        address curve_,\n        address launchFactory_,\n        uint256 supply_,\n        uint256 creatorAllocation_\n    ) ERC20(name_, symbol_) {\n        if (deployer_ == address(0) || curve_ == address(0) || launchFactory_ == address(0)) {\n            revert ZeroAddress();\n        }\n\n        deployer = deployer_;\n        // Passed explicitly rather than read from msg.sender: BrishopLaunchFactory\n        // deploys this token indirectly through BrishopLaunchDeployer to keep its\n        // own bytecode under EIP-170's size limit, so msg.sender at construction\n        // time would otherwise resolve to that deployer helper, not the factory.\n        launchFactory = launchFactory_;\n        curve = curve_;\n        if (supply_ == 0 || creatorAllocation_ > supply_ / 4) revert InvalidAllocation();\n        initialSupply = supply_;\n        initialCreatorAllocation = creatorAllocation_;\n        logo = logo_;\n        description = description_;\n        _socials = socials_;\n\n        _mint(curve_, supply_ - creatorAllocation_);\n        if (creatorAllocation_ != 0) _mint(deployer_, creatorAllocation_);\n    }\n\n    /**\n     * @notice Returns the launch token's five social metadata fields.\n     */\n    function socials()\n        external\n        view\n        returns (\n            string memory twitter,\n            string memory telegram,\n            string memory discord,\n            string memory website,\n            string memory farcaster\n        )\n    {\n        Socials memory values = _socials;\n        return (values.twitter, values.telegram, values.discord, values.website, values.farcaster);\n    }\n\n    /**\n     * @notice Returns creator and metadata in the launcher-compatible tuple.\n     */\n    function getTokenInfo()\n        external\n        view\n        returns (\n            address tokenDeployer,\n            string memory tokenLogo,\n            string memory tokenDescription,\n            Socials memory tokenSocials\n        )\n    {\n        return (deployer, logo, description, _socials);\n    }\n}\n"},"src/BrishopLaunchDeployer.sol":{"content":"// SPDX-License-Identifier: MIT\n// Deployment/metadata pattern derived from PONS v2; see ../NOTICE.md.\npragma solidity ^0.8.26;\nimport {BrishopLauncherToken} from \"./BrishopLauncherToken.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {FeePolicySnapshot, IBrishopFeeEscrow} from \"./interfaces/IBrishop.sol\";\n\nstruct TokenParams {\n    string name;\n    string symbol;\n    string logo;\n    string description;\n    BrishopLauncherToken.Socials socials;\n    address creatorFeeRecipient;\n    uint16 creatorTaxBps;\n    bool buybackEnabled;\n    bytes32 expectedEconomics;\n    bytes32 salt;\n    address[] snipeTaxExemptions;\n}\n\ncontract BrishopLaunchDeployer {\n    error NotFactory();\n    error InvalidMetadata();\n    address public immutable factory;\n    IBrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    constructor(address factory_, IBrishopFeeEscrow escrow_, BrishopBuybackVault vault_) {\n        factory = factory_; feeEscrow = escrow_; buybackVault = vault_;\n    }\n    function deployLaunch(TokenParams calldata params, BrishopBondingCurve.Terms calldata terms, FeePolicySnapshot calldata policy, address creator, uint256 supply, uint256 creatorAllocation) external returns (address token, address curve) {\n        if (msg.sender != factory) revert NotFactory();\n        _checkMetadata(params);\n        bytes32 salt = keccak256(abi.encode(creator, params.salt));\n        curve = address(new BrishopBondingCurve{salt: salt}(factory, feeEscrow, buybackVault, policy, terms));\n        token = address(new BrishopLauncherToken{salt: salt}(params.name, params.symbol, params.logo, params.description, params.socials, creator, curve, factory, supply, creatorAllocation));\n    }\n    function _checkMetadata(TokenParams calldata p) private pure {\n        if (bytes(p.name).length == 0 || bytes(p.name).length > 64 || bytes(p.symbol).length == 0 || bytes(p.symbol).length > 16 || bytes(p.logo).length > 512 || bytes(p.description).length > 2048) revert InvalidMetadata();\n        if (bytes(p.socials.twitter).length > 256 || bytes(p.socials.telegram).length > 256 || bytes(p.socials.discord).length > 256 || bytes(p.socials.website).length > 256 || bytes(p.socials.farcaster).length > 256) revert InvalidMetadata();\n    }\n}\n"},"@openzeppelin/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"src/libraries/BrishopBondingCurveMath.sol":{"content":"// SPDX-License-Identifier: MIT\n// Derived from the MIT PONS v2 verified source. See ../NOTICE.md.\npragma solidity ^0.8.26;\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n/**\n * @title BrishopBondingCurveMath\n * @notice Constant-product bonding curve math shared by BrishopBondingCurve, adapted\n * from the BootstrapPool.sol reference (code-423n4/2025-01-iq-ai). Reserves and fee\n * are passed explicitly so the same formula prices trades in either direction and can\n * also price the curve's internal buyback swap.\n */\nlibrary BrishopBondingCurveMath {\n    uint256 internal constant BASIS_POINTS = 10_000;\n\n    error InsufficientInputAmount();\n    error InsufficientOutputAmount();\n    error InsufficientLiquidity();\n    error ReserveLimit();\n\n    /**\n     * @notice Quotes the output amount for an exact input amount, net of the trade fee.\n     * @param amountIn Exact amount of the input asset being sold into the curve.\n     * @param reserveIn Curve reserve of the input asset before this trade.\n     * @param reserveOut Curve reserve of the output asset before this trade.\n     * @param feeBps Fee charged on the input amount, in basis points.\n     */\n    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountOut)\n    {\n        if (amountIn == 0) revert InsufficientInputAmount();\n        if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();\n\n        amountOut = _amountOut(amountIn, reserveIn, reserveOut, feeBps);\n        if (amountOut == 0) revert InsufficientOutputAmount();\n    }\n\n    /**\n     * @notice Same quote as `getAmountOut`, returning zero where that reverts.\n     * @dev For callers that treat an unpriceable trade as a condition to\n     * handle rather than an error, such as the curve's internal buyback,\n     * which folds the slice back into the creator's payout when the curve is\n     * too thin to execute against. Routing that case through the reverting\n     * variant would take the whole fee sweep down with it, stranding fees\n     * exactly when the curve cannot support a buyback.\n     */\n    function quoteAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountOut)\n    {\n        if (amountIn == 0 || reserveIn == 0 || reserveOut == 0 || feeBps >= BASIS_POINTS) return 0;\n        return _amountOut(amountIn, reserveIn, reserveOut, feeBps);\n    }\n\n    function _amountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        private\n        pure\n        returns (uint256)\n    {\n        if (amountIn > type(uint128).max || reserveIn > type(uint128).max || reserveOut > type(uint128).max) revert ReserveLimit();\n        uint256 amountInWithFee = amountIn * (BASIS_POINTS - feeBps);\n        uint256 denominator = reserveIn * BASIS_POINTS + amountInWithFee;\n        return Math.mulDiv(amountInWithFee, reserveOut, denominator);\n    }\n\n    /**\n     * @notice Quotes the input amount required for an exact output amount, net of the trade fee.\n     * @param amountOut Exact amount of the output asset requested from the curve.\n     * @param reserveIn Curve reserve of the input asset before this trade.\n     * @param reserveOut Curve reserve of the output asset before this trade.\n     * @param feeBps Fee charged on the input amount, in basis points.\n     */\n    function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut, uint256 feeBps)\n        internal\n        pure\n        returns (uint256 amountIn)\n    {\n        if (amountOut == 0) revert InsufficientOutputAmount();\n        if (reserveIn == 0 || reserveOut <= amountOut) revert InsufficientLiquidity();\n        // A full-fee trade has no input that produces output, and the\n        // denominator below would divide by zero rather than say so.\n        if (feeBps >= BASIS_POINTS) revert InsufficientLiquidity();\n\n        if (amountOut > type(uint128).max || reserveIn > type(uint128).max || reserveOut > type(uint128).max) revert ReserveLimit();\n        uint256 denominator = (reserveOut - amountOut) * (BASIS_POINTS - feeBps);\n        amountIn = Math.mulDiv(amountOut, reserveIn * BASIS_POINTS, denominator) + 1;\n    }\n}\n"},"@openzeppelin/contracts/access/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},"@openzeppelin/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `condition ? a : b`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `condition ? a : b`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // (a + b) / 2 can overflow.\n            return (a & b) + (a ^ b) / 2;\n        }\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory buffer) private pure returns (bool) {\n        uint256 chunk;\n        for (uint256 i = 0; i < buffer.length; i += 0x20) {\n            // See _unsafeReadBytesOffset from utils/Bytes.sol\n            assembly (\"memory-safe\") {\n                chunk := mload(add(add(buffer, 0x20), i))\n            }\n            if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n\n    /**\n     * @dev Counts the number of leading zero bits in a uint256.\n     */\n    function clz(uint256 x) internal pure returns (uint256) {\n        return ternary(x == 0, 256, 255 - log2(x));\n    }\n}\n"},"@openzeppelin/contracts/interfaces/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n    mapping(address account => uint256) private _balances;\n\n    mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * Both values are immutable: they can only be set once during construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() public view virtual returns (uint256) {\n        return _totalSupply;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account) public view virtual returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            _totalSupply += value;\n        } else {\n            uint256 fromBalance = _balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                _balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                _totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                _balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        _allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance < type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/StorageSlot.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},"@openzeppelin/contracts/interfaces/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},"@openzeppelin/contracts/access/Ownable2Step.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This extension of the {Ownable} contract includes a two-step mechanism to transfer\n * ownership, where the new owner must call {acceptOwnership} in order to replace the\n * old one. This can help prevent common mistakes, such as transfers of ownership to\n * incorrect accounts, or to contracts that are unable to interact with the\n * permission system.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     *\n     * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"},"@openzeppelin/contracts/interfaces/IERC1363.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev A uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\nimport {StorageSlot} from \"./StorageSlot.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n *\n * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced\n * by the {ReentrancyGuardTransient} variant in v6.0.\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuard {\n    using StorageSlot for bytes32;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev A `view` only version of {nonReentrant}. Use to block view functions\n     * from being called, preventing reading from inconsistent contract state.\n     *\n     * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n     * status. Use it only on view functions. For payable or non-payable functions,\n     * use the standard {nonReentrant} modifier instead.\n     */\n    modifier nonReentrantView() {\n        _nonReentrantBeforeView();\n        _;\n    }\n\n    function _nonReentrantBeforeView() private view {\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        _nonReentrantBeforeView();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;\n    }\n\n    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n        return REENTRANCY_GUARD_STORAGE;\n    }\n}\n"},"@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        if (!_safeTransfer(token, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        if (!_safeTransferFrom(token, from, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _safeTransfer(token, to, value, false);\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _safeTransferFrom(token, from, to, value, false);\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        if (!_safeApprove(token, spender, value, false)) {\n            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));\n            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the\n     * return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.transfer.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(to, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return\n     * value: the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param from The sender of the tokens\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value,\n        bool bubble\n    ) private returns (bool success) {\n        bytes4 selector = IERC20.transferFrom.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(from, shr(96, not(0))))\n            mstore(0x24, and(to, shr(96, not(0))))\n            mstore(0x44, value)\n            success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n            mstore(0x60, 0)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:\n     * the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param spender The spender of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.approve.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(spender, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0x00, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ERC20} from \"../ERC20.sol\";\nimport {Context} from \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n    /**\n     * @dev Destroys a `value` amount of tokens from the caller.\n     *\n     * See {ERC20-_burn}.\n     */\n    function burn(uint256 value) public virtual {\n        _burn(_msgSender(), value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, deducting from\n     * the caller's allowance.\n     *\n     * See {ERC20-_burn} and {ERC20-allowance}.\n     *\n     * Requirements:\n     *\n     * - the caller must have allowance for ``accounts``'s tokens of at least\n     * `value`.\n     */\n    function burnFrom(address account, uint256 value) public virtual {\n        _spendAllowance(account, _msgSender(), value);\n        _burn(account, value);\n    }\n}\n"},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"}},"language":"Solidity","settings":{"viaIR":true,"optimizer":{"runs":200,"enabled":true},"evmVersion":"cancun"}},"stdJsonOutput":{"sources":{"src/BrishopBondingCurve.sol":{"id":18},"src/BrishopBuybackVault.sol":{"id":19},"src/interfaces/IBrishop.sol":{"id":25},"src/BrishopLauncherToken.sol":{"id":24},"src/BrishopLaunchDeployer.sol":{"id":22},"@openzeppelin/contracts/utils/Panic.sol":{"id":12},"@openzeppelin/contracts/utils/Context.sol":{"id":11},"src/libraries/BrishopBondingCurveMath.sol":{"id":26},"@openzeppelin/contracts/access/Ownable.sol":{"id":0},"@openzeppelin/contracts/utils/math/Math.sol":{"id":16},"@openzeppelin/contracts/interfaces/IERC20.sol":{"id":4},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"id":6},"@openzeppelin/contracts/utils/StorageSlot.sol":{"id":14},"@openzeppelin/contracts/interfaces/IERC165.sol":{"id":3},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"id":7},"@openzeppelin/contracts/access/Ownable2Step.sol":{"id":1},"@openzeppelin/contracts/interfaces/IERC1363.sol":{"id":2},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"id":17},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"id":13},"@openzeppelin/contracts/interfaces/draft-IERC6093.sol":{"id":5},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"id":10},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"id":15},"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol":{"id":8},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"id":9}},"contracts":{"src/BrishopLaunchDeployer.sol":{"BrishopLaunchDeployer":{"abi":[{"type":"constructor","inputs":[{"name":"factory_","type":"address","internalType":"address"},{"name":"escrow_","type":"address","internalType":"contract IBrishopFeeEscrow"},{"name":"vault_","type":"address","internalType":"contract BrishopBuybackVault"}],"stateMutability":"nonpayable"},{"name":"InvalidMetadata","type":"error","inputs":[]},{"name":"NotFactory","type":"error","inputs":[]},{"name":"buybackVault","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract BrishopBuybackVault"}],"stateMutability":"view"},{"name":"deployLaunch","type":"function","inputs":[{"name":"params","type":"tuple","components":[{"name":"name","type":"string","internalType":"string"},{"name":"symbol","type":"string","internalType":"string"},{"name":"logo","type":"string","internalType":"string"},{"name":"description","type":"string","internalType":"string"},{"name":"socials","type":"tuple","components":[{"name":"twitter","type":"string","internalType":"string"},{"name":"telegram","type":"string","internalType":"string"},{"name":"discord","type":"string","internalType":"string"},{"name":"website","type":"string","internalType":"string"},{"name":"farcaster","type":"string","internalType":"string"}],"internalType":"struct BrishopLauncherToken.Socials"},{"name":"creatorFeeRecipient","type":"address","internalType":"address"},{"name":"creatorTaxBps","type":"uint16","internalType":"uint16"},{"name":"buybackEnabled","type":"bool","internalType":"bool"},{"name":"expectedEconomics","type":"bytes32","internalType":"bytes32"},{"name":"salt","type":"bytes32","internalType":"bytes32"},{"name":"snipeTaxExemptions","type":"address[]","internalType":"address[]"}],"internalType":"struct TokenParams"},{"name":"terms","type":"tuple","components":[{"name":"pairToken","type":"address","internalType":"address"},{"name":"creator","type":"address","internalType":"address"},{"name":"phantomQuote","type":"uint256","internalType":"uint256"},{"name":"feeBps","type":"uint256","internalType":"uint256"},{"name":"creatorTaxBps","type":"uint256","internalType":"uint256"},{"name":"buybackEnabled","type":"bool","internalType":"bool"}],"internalType":"struct BrishopBondingCurve.Terms"},{"name":"policy","type":"tuple","components":[{"name":"protocolFeeRecipient","type":"address","internalType":"address"},{"name":"protocolFeeShareBps","type":"uint16","internalType":"uint16"},{"name":"buybackBurnBps","type":"uint16","internalType":"uint16"},{"name":"hookFeeBps","type":"uint16","internalType":"uint16"},{"name":"maxInternalPriceImpactBps","type":"uint16","internalType":"uint16"}],"internalType":"struct FeePolicySnapshot"},{"name":"creator","type":"address","internalType":"address"},{"name":"supply","type":"uint256","internalType":"uint256"},{"name":"creatorAllocation","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"token","type":"address","internalType":"address"},{"name":"curve","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"factory","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"feeEscrow","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBrishopFeeEscrow"}],"stateMutability":"view"}],"metadata":"{\"compiler\":{\"version\":\"0.8.35+commit.47b9dedd\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"factory_\",\"type\":\"address\"},{\"internalType\":\"contract IBrishopFeeEscrow\",\"name\":\"escrow_\",\"type\":\"address\"},{\"internalType\":\"contract BrishopBuybackVault\",\"name\":\"vault_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidMetadata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotFactory\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"buybackVault\",\"outputs\":[{\"internalType\":\"contract BrishopBuybackVault\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logo\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"twitter\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"telegram\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"discord\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"website\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"farcaster\",\"type\":\"string\"}],\"internalType\":\"struct BrishopLauncherToken.Socials\",\"name\":\"socials\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creatorFeeRecipient\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"creatorTaxBps\",\"type\":\"uint16\"},{\"internalType\":\"bool\",\"name\":\"buybackEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"expectedEconomics\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"address[]\",\"name\":\"snipeTaxExemptions\",\"type\":\"address[]\"}],\"internalType\":\"struct TokenParams\",\"name\":\"params\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"pairToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"phantomQuote\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeBps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creatorTaxBps\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"buybackEnabled\",\"type\":\"bool\"}],\"internalType\":\"struct BrishopBondingCurve.Terms\",\"name\":\"terms\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"protocolFeeRecipient\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"protocolFeeShareBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"buybackBurnBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"hookFeeBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"maxInternalPriceImpactBps\",\"type\":\"uint16\"}],\"internalType\":\"struct FeePolicySnapshot\",\"name\":\"policy\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creatorAllocation\",\"type\":\"uint256\"}],\"name\":\"deployLaunch\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curve\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeEscrow\",\"outputs\":[{\"internalType\":\"contract IBrishopFeeEscrow\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/BrishopLaunchDeployer.sol\":\"BrishopLaunchDeployer\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"@openzeppelin/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0\",\"dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek\"]},\"@openzeppelin/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0xd5ea07362ab630a6a3dee4285a74cf2377044ca2e4be472755ad64d7c5d4b69d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da5e832b40fc5c3145d3781e2e5fa60ac2052c9d08af7e300dc8ab80c4343100\",\"dweb:/ipfs/QmTzf7N5ZUdh5raqtzbM11yexiUoLC9z3Ws632MCuycq1d\"]},\"@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"@openzeppelin/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0x1a6221315ce0307746c2c4827c125d821ee796c74a676787762f4778671d4f44\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1bb2332a7ee26dd0b0de9b7fe266749f54820c99ab6a3bcb6f7e6b751d47ee2d\",\"dweb:/ipfs/QmcRWpaBeCYkhy68PR3B4AgD7asuQk7PwkWxrvJbZcikLF\"]},\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\":{\"keccak256\":\"0x1b88b3fb3d85ba5496d7d5f396f83ee1fddcdd6762059ff65992655b67920998\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://89393bb3212da1c0889601b9706a07b39419ddc4d2faab9eaf6e7f9152cf6a1c\",\"dweb:/ipfs/QmcCfzzxv1Bkdz1c1yF4gQCeYb6Us5BJANnzTFqawfd1HL\"]},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x669464167428061ee0f8618b73b3ee90aff8405683e7ddde8cd77dadaa1afe29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0dda78587a7358b4fdf6b9fca0fde5a5e34930f36d5268a16028627fc0170195\",\"dweb:/ipfs/QmQ1b6cCceDRWNxti9HifsTCzmVP25Haxs1bWugm52vTqH\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x74ed01eb66b923d0d0cfe3be84604ac04b76482a55f9dd655e1ef4d367f95bc2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5282825a626cfe924e504274b864a652b0023591fa66f06a067b25b51ba9b303\",\"dweb:/ipfs/QmeCfPykghhMc81VJTrHTC7sF6CRvaA1FXVq2pJhwYp1dV\"]},\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\":{\"keccak256\":\"0x2659248df25e34000ed214b3dc8da2160bc39874c992b477d9e2b1b3283dc073\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c345af1b0e7ea28d1216d6a04ab28f5534a5229b9edf9ca3cd0e84950ae58d26\",\"dweb:/ipfs/QmY63jtSrYpLRe8Gj1ep2vMDCKxGNNG3hnNVKBVnrs2nmA\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0xd6fa4088198f04eef10c5bce8a2f4d60554b7ec4b987f684393c01bf79b94d9f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f95ee0bbd4dd3ac730d066ba3e785ded4565e890dbec2fa7d3b9fe3bad9d0d6e\",\"dweb:/ipfs/QmSLr6bHkPFWT7ntj34jmwfyskpwo97T9jZUrk5sz3sdtR\"]},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x304d732678032a9781ae85c8f204c8fba3d3a5e31c02616964e75cfdc5049098\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://299ced486011781dc98f638059678323c03079fefae1482abaa2135b22fa92d0\",\"dweb:/ipfs/QmbZNbcPTBxNvwChavN2kkZZs7xHhYL7mv51KrxMhsMs3j\"]},\"@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"@openzeppelin/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"@openzeppelin/contracts/utils/ReentrancyGuard.sol\":{\"keccak256\":\"0xa516cbf1c7d15d3517c2d668601ce016c54395bf5171918a14e2686977465f53\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1e1d079e8edfb58efd23a311e315a4807b01b5d1cf153f8fa2d0608b9dec3e99\",\"dweb:/ipfs/QmTBExeX2SDTkn5xbk5ssbYSx7VqRp9H4Ux1CY4uQM4b9N\"]},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"src/BrishopBondingCurve.sol\":{\"keccak256\":\"0x37fcd3f1b4529a9f0dbc316d071e1edf11ce3fafe2546c4ecc6f365c844f3db7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://32a9404f802a8eb3efd56548240f9abdddb6c0f936bb95d9e05df54b0e4c0e26\",\"dweb:/ipfs/QmTZCdLsbkGLMXAuRFY8mRf9VU5XX24K8x3qjCbpQh7nLm\"]},\"src/BrishopBuybackVault.sol\":{\"keccak256\":\"0x0becf05283bc8b8964a8d100e23b887a188c82c95fcad98e22f5217ffc9e58c9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://137a6aaded4724a3474b3c08067693245523ed517a84aafc5c146353852bb32d\",\"dweb:/ipfs/QmQ4JfAQYR3eqhowQgibERLGiTfowSnH1QRWY6D1983eFW\"]},\"src/BrishopLaunchDeployer.sol\":{\"keccak256\":\"0x0f81d31836aa2a5d416979c07a14635bf3d182e2a2e955e631cae8d0afe1d544\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6c655be8bfc3007ed89e0734a9a27d26bcd3ce27483c10648d605304b2f3526\",\"dweb:/ipfs/QmUChkKtVzv31TgNXQY8FGaZqeajBj7QhPXXSHep9kj5pe\"]},\"src/BrishopLauncherToken.sol\":{\"keccak256\":\"0x1ebcf1534c80df8734078c6d29f4d03dc5ca76c762788065a845ea390452e428\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://41c43b23dc334d33209865364b3493cd9c44286868a9c94d97934bda862626f8\",\"dweb:/ipfs/QmS7qZ19vCfUCYJEgLoKKG7hbpkHpP2Dps9SH6WMh52xt6\"]},\"src/interfaces/IBrishop.sol\":{\"keccak256\":\"0x329d57dfed260932f89ed7a9f0b91ed7236e12777f41ebf8599495ce294a8d2f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dd6053f039743beb42223b3228361129753dce8717c96291dba5820e52ef9892\",\"dweb:/ipfs/QmeSF8Mo9XyXb3ZGp8ns6h2cLo1G8n4f8UyyUoHe8w4piF\"]},\"src/libraries/BrishopBondingCurveMath.sol\":{\"keccak256\":\"0x0d3088350d2c58adce273486980851b3a34b6a85705ca2b681846fca118fc75b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://76441b39e6db97858be47e1d98ae0fde65f2060b4089f8a8395776c976ed28f5\",\"dweb:/ipfs/QmcmmXMjzzRKKJbLJUo9tjpeikd65iGCG8Q1hdR19jjGDt\"]}},\"version\":1}","userdoc":{"kind":"user","methods":{},"version":1},"devdoc":{"kind":"dev","methods":{},"version":1},"storageLayout":{"types":null,"storage":[]},"transientStorageLayout":{"types":null,"storage":[]},"evm":{"bytecode":{"object":"60e0346100c157601f614e1938819003918201601f19168301916001600160401b038311848410176100c5578084926060946040528339810103126100c1578051906001600160a01b03821682036100c1576020810151906001600160a01b03821682036100c15760400151916001600160a01b03831683036100c15760805260a05260c052604051614d3f90816100da823960805181818160e90152610182015260a05181818160a5015261028d015260c051818181605d01526102b50152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660808301527f0000000000000000000000000000000000000000000000000000000000000000811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","sourceMap":"710:1647:22:-:0;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;1038:18;;1058:19;;1079:21;;710:1647;;;;;;;;1038:18;710:1647;;;;;;;;;;1058:19;710:1647;;;;;;;;;;1079:21;710:1647;;;;;;;;;;;;-1:-1:-1;710:1647:22;;;;;;-1:-1:-1;710:1647:22;;;;;-1:-1:-1;710:1647:22","linkReferences":{}},"deployedBytecode":{"object":"6080806040526004361015610012575f80fd5b5f3560e01c9081638dabdc831461011857508063c45a0155146100d4578063c4b7de97146100905763f1f5c99314610048575f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c575f36600319011261008c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461008c576101e036600319011261008c576004359067ffffffffffffffff821161008c578160040191610160600319823603011261008c5760c036602319011261008c5760a03660e319011261008c57610184356001600160a01b038116939084900361008c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316933385900361068e576101bd828061069d565b9050158015610679575b8015610663575b801561064b575b8015610632575b8015610619575b61057e5760848301916101006102026101fc85846106d0565b8061069d565b90501180156105f6575b80156105d3575b80156105b0575b801561058d575b61057e576020850194828652610124850135604082015260408152606081019581871067ffffffffffffffff88111761056a578660405281519020956128b1808301906060820183811067ffffffffffffffff82111761056a578a916107388539526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660808301527f0000000000000000000000000000000000000000000000000000000000000000811660a083015260e4359081169081900361008c5760c08201526101043561ffff811680910361008c5760e08201526101243561ffff811680910361008c576101008201526101443561ffff811680910361008c576101208201526101643561ffff811680910361008c576101408201526024356001600160a01b0381169081900361008c576101608201526044356001600160a01b0381169081900361008c576101808201526064356101a08201526084356101c082015260a4356101e082015260c43580151580910361008c5761020082015287926101c0910301905ff5801561055f576001600160a01b0316956103ce828061069d565b929060646103df602489018461069d565b9390976104076103ff6103f560448d018561069d565b95909c018461069d565b9290936106d0565b936040519a611d2194858d01998d8b1067ffffffffffffffff8c111761056a578d9c610515996104528f96610460948f6101409061047c9d61046e9b612fe9903981815201916106e5565b8d810360208f0152916106e5565b918a830360408c01526106e5565b9187830360608901526106e5565b84810360808601526105076104fc6104e16104c66104ab61049d8780610705565b60a0885260a08801916106e5565b6104b86020880188610705565b9087830360208901526106e5565b6104d36040870187610705565b9086830360408801526106e5565b6104ee6060860186610705565b9085830360608701526106e5565b926080810190610705565b9160808185039101526106e5565b9260a08301528660c083015260e08201526101a4356101008201526101206101c43591015203905ff5801561055f57604080516001600160a01b0390921682526020820192909252f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b635e765b2560e11b5f5260045ffd5b506101006105a861059e85846106d0565b608081019061069d565b905011610221565b506101006105cb6105c185846106d0565b606081019061069d565b90501161021a565b506101006105ee6105e485846106d0565b604081019061069d565b905011610213565b5061010061061161060785846106d0565b602081019061069d565b90501161020c565b5061080061062a606485018461069d565b9050116101e3565b50610200610643604485018461069d565b9050116101dc565b50601061065b602485018461069d565b9050116101d5565b50610671602484018361069d565b9050156101ce565b506040610686838061069d565b9050116101c7565b631966391b60e11b5f5260045ffd5b903590601e198136030182121561008c570180359067ffffffffffffffff821161008c5760200191813603831361008c57565b903590609e198136030182121561008c570190565b908060209392818452848401375f828201840152601f01601f1916010190565b9035601e198236030181121561008c57016020813591019167ffffffffffffffff821161008c57813603831361008c5756fe610220604052346104b1576040516128b138819003601f8101601f191683016001600160401b038111848210176104b557839282916040528339810103906101c082126104b15761004f816104c9565b602082015190916001600160a01b0382168083036104b15760408201516001600160a01b038116938482036104b15760a0605f198801126104b1576040519660a088016001600160401b038111898210176104b5576040526100b3606086016104c9565b88526100c1608086016104dd565b95602089019687526100d560a087016104dd565b60408a019081526100e860c088016104dd565b60608b015260c06100fb60e089016104dd565b60808c019081529360ff1901126104b1576040519860c08a016001600160401b0381118b8210176104b55760405261013661010089016104c9565b8a5261014561012089016104c9565b9860208b019a8a8c526101408a015197604082019889526101608b015199606083019a8b526101a06101808d01519c608085019d8e5201519c8d801515036104b15760a084019d8e5260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556001600160a01b0386169788159283156104a8575b50821561049f575b50811561048d575b5061047e578d516001600160a01b031615801561046e575b801561045e575b8015610451575b8015610440575b8015610415575b61040657885180159081156103f5575b506103e65761ffff978896879560a05260c05260e0526101005260018060a01b0390511660805260018060a01b038b51169a6001549c60018060a01b039051166101205260018060a01b039051166101405251166101605251166101805251166101a052516101c052516101e052516102005260ff60a01b9051151560a01b169160018060a81b03191617176001556040516123c490816104ed823960805181818161029e01528181610a7301528181610bd30152818161112301528181611eab0152611ff3015260a05181818161044801528181610605015281816106e90152610f7f015260c051818181610f350152611347015260e05181818161040401528181611edb0152611f6d01526101005181818161021c015261152c01526101205181818161104d015281816114e401526115be0152610140518181816111670152611596015261016051818181610b08015281816113b901526121760152610180518181816110cd01526121a701526101a051818181610aca01526116a401526101c0518181816103cc015281816105c1015261183e01526101e0518181816111f4015281816118850152611a1901526102005181818161048e015281816118b80152611a4f0152f35b63bc0ecfe360e01b5f5260045ffd5b6001600160801b031090505f61021b565b637a34030f60e01b5f5260045ffd5b5089518b51810180911161042c576107d01061020b565b634e487b7160e01b5f52601160045260245ffd5b5061271061ffff8851161015610204565b5061ffff875116156101fd565b5061271061ffff865116116101f6565b5061271061ffff845116116101ef565b63d92e233d60e01b5f5260045ffd5b6001600160a01b03161590505f6101d7565b1591505f6101cf565b1592505f6101c7565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036104b157565b519061ffff821682036104b15756fe60806040526004361015610011575f80fd5b5f3560e01c80630902f1ac1461123c578063160d0da51461121757806324a9d853146111dd5780633729bb9a146111965780633cd1fb8f146111525780633de35b791461110e5780633f7ed6b7146110f157806349127e2a146110b35780634c37ef231461037b5780634f1f58fd1461109957806350e25ac21461107c57806364df049e146110385780636783774b1461101b5780637809452a14610ffe5780637b04ea6214610f645780638258903814610f205780638945257c14610d995780638a038a5414610b2c5780639040f86614610aee57806390addc1e14610ab0578063946d9204146106895780639a9b567d146105e55780639da771f4146105a2578063a4afe0bf14610527578063a64190c4146104ce578063bf56b371146104b1578063c1bb890114610477578063c45a015514610433578063c4b7de97146103ef578063c57eadfc146103b5578063ca52b0b714610398578063cbcb31711461037b578063d44bdfe71461033e578063d5f3948814610316578063d7e1ef39146102eb578063db2bd533146102ce578063dc08e09414610289578063ed479c471461026c578063eff31e9e1461024b578063f1f5c993146102075763fc0c546a146101dc575f80fd5b34610203575f366003190112610203575f546040516001600160a01b039091168152602090f35b5f80fd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040516001600160801b038152f35b34610203575f366003190112610203576020600254604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158152602090f35b34610203575f366003190112610203576020600454604051908152f35b3461020357602036600319011261020357602061030e610309611268565b611ab9565b604051908152f35b34610203575f366003190112610203576001546040516001600160a01b039091168152602090f35b34610203576020366003190112610203576001600160a01b0361035f611268565b165f52600b602052602060ff60405f2054166040519015158152f35b34610203575f366003190112610203576020600654604051908152f35b34610203575f366003190112610203576020600554604051908152f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f366003190112610203576020600854604051908152f35b346102035760203660031901126102035760a06104f46004356104ef61198d565b6119c8565b60806040519180518352602081015160208401526040810151604084015260608101516060840152015115156080820152f35b34610203576040366003190112610203576024356001600160a01b03811681036102035761057b60809160405161055d816112cd565b5f81525f60208201525f60408201525f606082015260043590611814565b60606040519180518352602081015160208401526040810151604084015201516060820152f35b34610203575f36600319011261020357602061030e6105bf6117be565b7f00000000000000000000000000000000000000000000000000000000000000006112ac565b3461020357602036600319011261020357600435801515809103610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001805460ff60a01b191660a083901b60ff60a01b161790556040519081527fbfe799fb5e0148a5f2590ff531306d42a5d512b74a5029ceb805abb808b0f1a090602090a1005b631966391b60e11b5f5260045ffd5b34610203576040366003190112610203576106a2611268565b60243567ffffffffffffffff8111610203573660238201121561020357806004013567ffffffffffffffff8111610203576024820191602436918360051b010111610203577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316913383900361067a575f54936001600160a01b038516610aa2576001600160a01b03169283158015610a70575b61092c576040516370a0823160e01b815230600482015294602086602481885afa958615610996575f96610a3c575b506040516318160ddd60e01b815290602082600481895afa918215610996575f92610a08575b50861580156109ff575b80156109ef575b80156109e5575b6109d6576001600160a01b03191685175f556007556006859055426008556040516328712d6160e11b815290602082600481845afa918215610996575f926109a1575b509060206004928260095560405193848092636783774b60e01b82525afa918215610996575f92610960575b506126ac9082600a5511908115610957575b811561094a575b5061093b575f5b82811061089d577f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040867f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e66020888451908152a18151905f82526020820152a1005b6001600160a01b036108b86108b38386866117dc565b611800565b161561092c576001906001600160a01b036108d76108b38387876117dc565b165f52600b60205260405f208260ff19825416179055818060a01b036109016108b38387876117dc565b167fe4b7e48fbd47c2f602bacadee76ad33b16542ddb4997cfc0de04c311adcfa8c75f80a20161083a565b63d92e233d60e01b5f5260045ffd5b637a34030f60e01b5f5260045ffd5b6201518091501185610833565b8015915061082c565b9091506020813d60201161098e575b8161097c602093836112e9565b810103126102035751906126ac61081a565b3d915061096f565b6040513d5f823e3d90fd5b91506020823d6020116109ce575b816109bc602093836112e9565b810103126102035790519060206107ee565b3d91506109af565b63bc0ecfe360e01b5f5260045ffd5b50602285116107ab565b506001600160801b0382116107a4565b5081871161079d565b9091506020813d602011610a34575b81610a24602093836112e9565b8101031261020357519087610793565b3d9150610a17565b9095506020813d602011610a68575b81610a58602093836112e9565b810103126102035751948661076d565b3d9150610a4b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316841461073e565b62dc149f60e41b5f5260045ffd5b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357610b3a3661127e565b92610b43611b2e565b5f546001600160a01b0316938415610d8a574211610d7b576001600160a01b03821691821561092c57610b78826104ef61198d565b94608086015115610d5857855194808610610d42575082610b9c9130903390612222565b6040850190610bb36060835197019687519061212f565b610bbf85600554611325565b600555610bce836006546112ac565b6006557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680610d0d5750505f80808087875af13d15610d08573d67ffffffffffffffff8111610cf45760405190610c38601f8201601f1916602001836112e9565b81525f60203d92013e5b15610ce5576020947f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df915b51905160408051948552602085018790528401919091526060830152339180608081015b0390a37f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e6040610cbf6117be565b600654825191825285820152a160015f51602061236f5f395f51905f5255604051908152f35b6312171d8360e31b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b610c42565b91610d3d86602098937f8113d738abdcb6b38357e9d53a54a7157861a09031b453651f0fe7fe151f59df956121e3565b610c6d565b856371c4efed60e01b5f5260045260245260445ffd5b6020860151610d656117be565b90630865175560e11b5f5260045260245260445ffd5b631ab7da6b60e01b5f5260045ffd5b6321c4e35760e21b5f5260045ffd5b610da23661127e565b610dad939193611b2e565b5f546001600160a01b031615610d8a574211610d7b57610dcc90611ff1565b610df78382604051610ddd816112cd565b5f81525f60208201525f60408201525f6060820152611814565b90815192808410610f0a57507fec36bf571f136799e8dc0b0b8bea4b04d8bd3d43de838aab0d5fc21d4cbfc455602094610e98868501805190610e506040610e4560608a01948551906112ac565b98019788519061212f565b610e5c866005546112ac565b600555610e6b88600654611325565b6006555f54610e8690899086906001600160a01b03166121e3565b815180610ece575b50519051906112ac565b9351604080519485526020850187905284019490945260608301939093526001600160a01b039092169133918060808101610c91565b6040519081526001600160a01b038516907f3bc39a5562b28f5fe8f36cecabfbaa12bb969acf05717994709225fc412a9934908b90a289610e8e565b836371c4efed60e01b5f5260045260245260445ffd5b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461020357602036600319011261020357610f7d611268565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361067a576001600160a01b0316801561092c57600154816001600160a01b0382167f2cc664e1ac1e2d05c0d4637bb63ec8189113b6ac39276be8977e26216a8cdd195f80a36001600160a01b03191617600155005b34610203575f366003190112610203576020600354604051908152f35b34610203575f366003190112610203576020600a54604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576020600954604051908152f35b34610203575f36600319011261020357602061030e6117be565b34610203575f36600319011261020357602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203575f366003190112610203576020600754604051908152f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203575f366003190112610203576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610203576020366003190112610203576111af611b2e565b5f546001600160a01b031615610d8a576111ca600435611332565b60015f51602061236f5f395f51905f5255005b34610203575f3660031901126102035760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610203575f36600319011261020357602060ff60015460a01c166040519015158152f35b34610203575f3660031901126102035760406112596105bf6117be565b60065482519182526020820152f35b600435906001600160a01b038216820361020357565b60809060031901126102035760043590602435906044356001600160a01b0381168103610203579060643590565b919082018092116112b957565b634e487b7160e01b5f52601160045260245ffd5b6080810190811067ffffffffffffffff821117610cf457604052565b90601f8019910116810190811067ffffffffffffffff821117610cf457604052565b6001600160801b0303906001600160801b0382116112b957565b919082039182116112b957565b604051638a36a6bb60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610996575f9161177c575b506001600160a01b03163314158080611767575b611758578061174d575b61173e5760025490600454821580611736575b6117315761ffff7f0000000000000000000000000000000000000000000000000000000000000000166113ed6113e68286611b66565b8095611325565b600354818082109118029361140e858318946114098685611325565b6112ac565b945f9203611672575b505f6002555f6004555f60035561143961143185876112ac565b600554611325565b6005558061150d575b5050916060917f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f93826114de575b816114c2575b60405192835260208301526040820152a17f5141ecc84a35c12ca2bf76bb33d393bd2fc22f906da0743534beef4ae63c6c8e60406114b26117be565b60065482519182526020820152a1565b6001546114d99083906001600160a01b0316611ea6565b611476565b611508837f0000000000000000000000000000000000000000000000000000000000000000611ea6565b611470565b9290939161151d84600654611325565b6006555f546001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116969161155d918791899116611d6f565b5f546001600160a01b031690863b156102035760405163892823f760e01b81526004810192909252602482018690526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448401527f00000000000000000000000000000000000000000000000000000000000000001660648301526084820152945f90869060a490829084905af19485156109965760406060957f5feba9b0d52c92ada4b9c571c2bee52390c54f2947208ab250221e6ee32f12ff927f9f4cd7c4ed99d08a797804560c9c5d71d2cf7e101f2e3b5e7d1ca8a24c370e4f98611662575b508151908482526020820152a19193819350611442565b5f61166c916112e9565b5f61164b565b80949193929415611722576116886105bf6117be565b6006549061169f61169986836112ac565b86611bea565b61ffff7f000000000000000000000000000000000000000000000000000000000000000016101561170e575b5050836116e75750906116dd916112ac565b915f915b5f611417565b808492959394106116f857506116e1565b906371c4efed60e01b5f5260045260245260445ffd5b61171a92955084611d29565b925f806116cb565b633672d25f60e01b5f5260045ffd5b505050565b5080156113b0565b630c736d4160e21b5f5260045ffd5b50600354151561139d565b63235084c360e21b5f5260045ffd5b506001546001600160a01b0316331415611393565b90506020813d6020116117b6575b81611797602093836112e9565b8101031261020357516001600160a01b0381168103610203575f61137f565b3d915061178a565b6117d96117d060055460025490611325565b60045490611325565b90565b91908110156117ec5760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036102035790565b5f549092906001600160a01b031615610d8a576001600160a01b0381161561092c57811561197e577f00000000000000000000000000000000000000000000000000000000000000009061187361186a8361130b565b60055490611325565b831161196f5761188290611ab9565b917f000000000000000000000000000000000000000000000000000000000000000080612710039261271084116112b9576118de7f00000000000000000000000000000000000000000000000000000000000000008095611325565b60631981019081116112b9578561195b9382611953936119609911611965575b50611947611931611923611915611953948a611b66565b9960208d019a8b5289611b66565b9360408c0194855288611b66565b9460608b019586526119416117be565b906112ac565b95600654975190611325565b905190611325565b61228b565b815290565b91506119476118fe565b63b026649f60e01b5f5260045ffd5b631f2a200560e01b5f5260045ffd5b6040519060a0820182811067ffffffffffffffff821117610cf4576040525f6080838281528260208201528260408201528260608201520152565b5f549091906001600160a01b031615610d8a57801561197e57600654906119ee8261130b565b811161196f57611a0991611a036105bf6117be565b9161228b565b611a86611a3e60208401928084527f000000000000000000000000000000000000000000000000000000000000000090611b66565b60408401908152611953611a7484517f000000000000000000000000000000000000000000000000000000000000000090611b66565b91606086019283528451905190611325565b825251611a916117be565b1015608082015290565b8115611aa5570490565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03165f908152600b602052604090205460ff168015611b24575b611b2057611aea60085442611325565b600a549081811015611b1a5760095491600e820291808304600e14901517156112b957611b1691611a9b565b1c90565b50505f90565b5f90565b5060095415611ada565b60025f51602061236f5f395f51905f525414611b575760025f51602061236f5f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b9091905f905f198482099084810292838084109303928084039314611bdd57826127101115611bcb57507fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e919394612710910990828211900360fc1b910360041c170290565b634e487b71905260116020526024601cfd5b5050506127109192500490565b5f19612710820991612710820291828085109403938085039414611c7f5783821115611c6757612710829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b50634e487b715f52156003026011186020526024601cfd5b50906117d99250611a9b565b90915f198383099280830292838086109503948086039514611d1c5784831115611d045790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906117d99250611a9b565b909181158015611d67575b8015611d5f575b8015611d58575b611d51576117d9925f926122e9565b5050505f90565b505f611d42565b508015611d3b565b508215611d34565b916040519163095ea7b360e01b5f5260018060a01b031691826004528160245260205f60448180885af19060015f5114821615611e97575b60405215611db457505050565b60405163095ea7b360e01b5f52826004525f60245260205f60448180885af19060015f5114821615611e7f575b60405215611e61576040519163095ea7b360e01b5f5260045260245260205f60448180865af19060015f5114821615611e40575b60405215611e205750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b906001811516611e5857823b15153d15161690611e15565b503d5f823e3d90fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b906001811516611e5857843b15153d15161690611de1565b90843b15153d15161690611da7565b5f91907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031680611f6757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15611f63576040516301aba89b60e71b81526001600160a01b03909116600482015291839183916024918391905af18015611f5857611f43575050565b611f4e8280926112e9565b611f555750565b80fd5b6040513d84823e3d90fd5b8380fd5b919250907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611fa0848284611d6f565b803b15610203575f928360649260405196879586946309ad4dd960e01b865260018060a01b03166004860152602485015260448401525af1801561099657611fe55750565b5f611fef916112e9565b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561210d57346120fe576040516370a0823160e01b815230600482015290602082602481865afa918215610996575f926120c9575b50602492612064602092303384612222565b6040516370a0823160e01b815230600482015293849182905afa8015610996575f90612095575b6117d99250611325565b506020823d6020116120c1575b816120af602093836112e9565b81010312610203576117d9915161208b565b3d91506120a2565b9091506020813d6020116120f6575b816120e5602093836112e9565b810103126102035751906024612052565b3d91506120d8565b63e0aeda7d60e01b5f5260045ffd5b80915034036121195790565b635e3b067f60e11b5f523460045260245260445ffd5b9061214b90612140836002546112ac565b6002556004546112ac565b60045560ff60015460a01c16806121da575b6121645750565b6121cd6121a26121d59261219c61ffff7f00000000000000000000000000000000000000000000000000000000000000001682611b66565b90611325565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001690611b66565b6003546112ac565b600355565b5080151561215d565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af19060015f5114821615611e405760405215611e205750565b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af19060015f5114821615612273575b6040525f60605215611e205750565b906001811516611e5857823b15153d15161690612264565b909181156122da57821580156122d2575b6122c3576122ab925f926122e9565b9081156122b457565b6342301c2360e01b5f5260045ffd5b63bb55fd2760e01b5f5260045ffd5b50801561229c565b63098fb56160e01b5f5260045ffd5b9190926001600160801b038311801561235e575b801561234e575b61196f57612710039161271083116112b9578281029281840414901517156112b95761271083029280840461271014901517156112b957612348826117d9946112ac565b91611c8b565b506001600160801b038211612304565b506001600160801b0384116122fd56fe9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220c396fb92a5ef51329f53b3c8ce5519ab28c8758717be69300871383bbaf4223064736f6c6343000823003361012060405234610ee557611d218038038061001a81610ee9565b92833981019061014081830312610ee55780516001600160401b038111610ee55782610047918301610f0e565b60208201519091906001600160401b038111610ee55783610069918301610f0e565b60408201519091906001600160401b038111610ee5578461008b918301610f0e565b60608201519094906001600160401b038111610ee557816100ad918401610f0e565b60808301519091906001600160401b038111610ee557830160a081830312610ee55760405160a081016001600160401b038111828210176107195760405281516001600160401b038111610ee55783610107918401610f0e565b815260208201516001600160401b038111610ee55783610128918401610f0e565b6020820190815260408301519091906001600160401b038111610ee55784610151918501610f0e565b6040820190815260608401519093906001600160401b038111610ee5578561017a918301610f0e565b6060830190815260808201519095906001600160401b038111610ee5576101a19201610f0e565b94608082019586526101b560a08801610f5f565b996101c260c08901610f5f565b986101cf60e08a01610f5f565b906101206101008b01519a01519b80519060018060401b0382116107195760035490600182811c92168015610edb575b60208310146106fb5781601f849311610e65575b50602090601f8311600114610dff575f92610df4575b50508160011b915f199060031b1c1916176003555b8051906001600160401b0382116107195760045490600182811c92168015610dea575b60208310146106fb5781601f849311610d74575b50602090601f8311600114610d0e575f92610d03575b50508160011b915f199060031b1c1916176004555b6001600160a01b038c16158015610cf2575b8015610ce1575b610cd2578b60805260a0528860c05287158015610cc6575b610cb75760e08890526101008a90528051906001600160401b0382116107195760055490600182811c92168015610cad575b60208310146106fb5781601f849311610c53575b50602090601f8311600114610bed575f92610be2575b50508160011b915f199060031b1c1916176005555b8051906001600160401b0382116107195760065490600182811c92168015610bd8575b60208310146106fb5781601f849311610b62575b50602090601f8311600114610afc575f92610af1575b50508160011b915f199060031b1c1916176006555b518051906001600160401b0382116107195760075490600182811c92168015610ae7575b60208310146106fb5781601f849311610a71575b50602090601f8311600114610a0b575f92610a00575b50508160011b915f199060031b1c1916176007555b518051906001600160401b0382116107195760085490600182811c921680156109f6575b60208310146106fb5781601f849311610980575b50602090601f831160011461091a575f9261090f575b50508160011b915f199060031b1c1916176008555b518051906001600160401b0382116107195760095490600182811c92168015610905575b60208310146106fb5781601f84931161088f575b50602090601f8311600114610829575f9261081e575b50508160011b915f199060031b1c1916176009555b518051906001600160401b03821161071957600a5490600182811c92168015610814575b60208310146106fb5781601f84931161079e575b50602090601f8311600114610738575f9261072d575b50508160011b915f199060031b1c191617600a555b518051906001600160401b03821161071957600b5490600182811c9216801561070f575b60208310146106fb5781601f849311610685575b50602090601f831160011461061f575f92610614575b50508160011b915f199060031b1c191617600b555b828103908111610600576105a691610f73565b806105f0575b604051610d3a9081610fe782396080518181816101cb0152610261015260a0518161059d015260c05181610496015260e05181610600015261010051816101430152f35b6105f991610f73565b5f806105ac565b634e487b7160e01b5f52601160045260245ffd5b015190505f8061057e565b600b5f9081528281209350601f198516905b81811061066d5750908460019594939210610655575b505050811b01600b55610593565b01515f1960f88460031b161c191690555f8080610647565b92936020600181928786015181550195019301610631565b8281111561056857600b5f52909150601f830160051c7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9602085106106f3575b849392601f0160051c82900391015f5b8281106106e3575050610568565b5f818301558594506001016106d5565b5f91506106c5565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610554565b634e487b7160e01b5f52604160045260245ffd5b015190505f8061051b565b600a5f9081528281209350601f198516905b818110610786575090846001959493921061076e575b505050811b01600a55610530565b01515f1960f88460031b161c191690555f8080610760565b9293602060018192878601518155019501930161074a565b8281111561050557600a5f52909150601f830160051c7fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a86020851061080c575b849392601f0160051c82900391015f5b8281106107fc575050610505565b5f818301558594506001016107ee565b5f91506107de565b91607f16916104f1565b015190505f806104b8565b60095f9081528281209350601f198516905b818110610877575090846001959493921061085f575b505050811b016009556104cd565b01515f1960f88460031b161c191690555f8080610851565b9293602060018192878601518155019501930161083b565b828111156104a25760095f52909150601f830160051c7f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af602085106108fd575b849392601f0160051c82900391015f5b8281106108ed5750506104a2565b5f818301558594506001016108df565b5f91506108cf565b91607f169161048e565b015190505f80610455565b60085f9081528281209350601f198516905b8181106109685750908460019594939210610950575b505050811b0160085561046a565b01515f1960f88460031b161c191690555f8080610942565b9293602060018192878601518155019501930161092c565b8281111561043f5760085f52909150601f830160051c7ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee3602085106109ee575b849392601f0160051c82900391015f5b8281106109de57505061043f565b5f818301558594506001016109d0565b5f91506109c0565b91607f169161042b565b015190505f806103f2565b60075f9081528281209350601f198516905b818110610a595750908460019594939210610a41575b505050811b01600755610407565b01515f1960f88460031b161c191690555f8080610a33565b92936020600181928786015181550195019301610a1d565b828111156103dc5760075f52909150601f830160051c7fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68860208510610adf575b849392601f0160051c82900391015f5b828110610acf5750506103dc565b5f81830155859450600101610ac1565b5f9150610ab1565b91607f16916103c8565b015190505f8061038f565b60065f9081528281209350601f198516905b818110610b4a5750908460019594939210610b32575b505050811b016006556103a4565b01515f1960f88460031b161c191690555f8080610b24565b92936020600181928786015181550195019301610b0e565b828111156103795760065f52909150601f830160051c7ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f60208510610bd0575b849392601f0160051c82900391015f5b828110610bc0575050610379565b5f81830155859450600101610bb2565b5f9150610ba2565b91607f1691610365565b015190505f8061032d565b60055f9081528281209350601f198516905b818110610c3b5750908460019594939210610c23575b505050811b01600555610342565b01515f1960f88460031b161c191690555f8080610c15565b92936020600181928786015181550195019301610bff565b828111156103175790915060055f5260205f20601f840160051c9060208510610ca5575b849392601f0160051c82900391015f5b828110610c95575050610317565b5f81830155859450600101610c87565b5f9150610c77565b91607f1691610303565b6305d7ba1960e11b5f5260045ffd5b508760021c8a116102d1565b63d92e233d60e01b5f5260045ffd5b506001600160a01b038116156102b9565b506001600160a01b038a16156102b2565b015190505f8061028b565b60045f9081528281209350601f198516905b818110610d5c5750908460019594939210610d44575b505050811b016004556102a0565b01515f1960f88460031b161c191690555f8080610d36565b92936020600181928786015181550195019301610d20565b828111156102755760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610de2575b849392601f0160051c82900391015f5b828110610dd2575050610275565b5f81830155859450600101610dc4565b5f9150610db4565b91607f1691610261565b015190505f80610229565b60035f9081528281209350601f198516905b818110610e4d5750908460019594939210610e35575b505050811b0160035561023e565b01515f1960f88460031b161c191690555f8080610e27565b92936020600181928786015181550195019301610e11565b828111156102135760035f52909150601f830160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208510610ed3575b849392601f0160051c82900391015f5b828110610ec3575050610213565b5f81830155859450600101610eb5565b5f9150610ea5565b91607f16916101ff565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761071957604052565b81601f82011215610ee5578051906001600160401b03821161071957610f3d601f8301601f1916602001610ee9565b9282845260208383010111610ee557815f9260208093018386015e8301015290565b51906001600160a01b0382168203610ee557565b6001600160a01b0316908115610fd357600254908082018092116106005760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3565b63ec442f0560e01b5f525f60045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806306fdde031461073b578063095ea7b31461069357806318160ddd1461067657806323b872dd1461063e578063313ce56714610623578063378dc3dc146105e957806342966c68146105cc578063536dac9b1461058857806353cd512a146104fc57806370a08231146104c55780637165485d146104815780637284e4161461046657806379cc67901461043457806395d89b4114610340578063a9059cbb1461030f578063abb1dc44146101fa578063d5f39488146101b6578063dd62ed3e14610166578063e029607c1461012c5763fb7f21eb146100f5575f80fd5b34610128575f36600319011261012857610124610110610966565b6040519182916020835260208301906107f6565b0390f35b5f80fd5b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346101285760403660031901126101285761017f61081a565b610187610830565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128575f366003190112610128576060608060405161021a81610846565b8281528260208201528260408201528280820152015261029461023b610966565b610124610246610898565b6102a2610251610ac8565b9160405195869560018060a01b037f00000000000000000000000000000000000000000000000000000000000000001687526080602088015260808701906107f6565b9085820360408701526107f6565b838103606085015260806102fe6102ec6102da6102c8865160a0875260a08701906107f6565b602087015186820360208801526107f6565b604086015185820360408701526107f6565b606085015184820360608601526107f6565b9201519060808184039101526107f6565b346101285760403660031901126101285761033561032b61081a565b6024359033610bc3565b602060405160018152f35b34610128575f366003190112610128576040515f6004548060011c9060018116801561042a575b602083108114610416578285529081156103f25750600114610394575b6101248361011081850382610876565b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b8082106103d857509091508101602001610110610384565b9192600181602092548385880101520191019092916103c0565b60ff191660208086019190915291151560051b840190910191506101109050610384565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610367565b346101285760403660031901126101285761046461045061081a565b6024359061045f823383610b20565b610c80565b005b34610128575f36600319011261012857610124610110610898565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610128576020366003190112610128576001600160a01b036104e661081a565b165f525f602052602060405f2054604051908152f35b34610128575f36600319011261012857610550610517610ac8565b61012481519161057a60208201519161056c604082015161055e6080606085015194015195604051998a9960a08b5260a08b01906107f6565b9089820360208b01526107f6565b9087820360408901526107f6565b9085820360608701526107f6565b9083820360808501526107f6565b34610128575f366003190112610128576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101285760203660031901126101285761046460043533610c80565b34610128575f3660031901126101285760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610128575f36600319011261012857602060405160128152f35b346101285760603660031901126101285761033561065a61081a565b610662610830565b60443591610671833383610b20565b610bc3565b34610128575f366003190112610128576020600254604051908152f35b34610128576040366003190112610128576106ac61081a565b602435903315610728576001600160a01b031690811561071557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b34610128575f366003190112610128576040515f6003548060011c906001811680156107ec575b602083108114610416578285529081156103f2575060011461078e576101248361011081850382610876565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106107d257509091508101602001610110610384565b9192600181602092548385880101520191019092916107ba565b91607f1691610762565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012857565b602435906001600160a01b038216820361012857565b60a0810190811067ffffffffffffffff82111761086257604052565b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff82111761086257604052565b604051905f6006548060011c916001821691821561095c575b60208410831461041657838652859290811561093d57506001146108de575b6108dc92500383610876565b565b5060065f90815290917ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f5b8183106109215750509060206108dc928201016108d0565b6020919350806001915483858901015201910190918492610909565b602092506108dc94915060ff191682840152151560051b8201016108d0565b92607f16926108b1565b604051905f6005548060011c9160018216918215610a08575b60208410831461041657838652859290811561093d57506001146109a9576108dc92500383610876565b5060055f90815290917f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b8183106109ec5750509060206108dc928201016108d0565b60209193508060019154838589010152019101909184926109d4565b92607f169261097f565b90604051915f8154908160011c9260018316928315610abe575b602085108414610416578487528693908115610a9c5750600114610a58575b506108dc92500383610876565b90505f9291925260205f20905f915b818310610a805750509060206108dc928201015f610a4b565b6020919350806001915483858901015201910190918492610a67565b9050602092506108dc94915060ff191682840152151560051b8201015f610a4b565b93607f1693610a2c565b60405190610ad582610846565b81610ae06007610a12565b8152610aec6008610a12565b6020820152610afb6009610a12565b6040820152610b0a600a610a12565b60608201526080610b1b600b610a12565b910152565b6001600160a01b039081165f818152600160209081526040808320948616835293905291909120549291905f198410610b5a575b50505050565b828410610ba0578015610728576001600160a01b03821615610715575f52600160205260405f209060018060a01b03165f5260205260405f20910390555f808080610b54565b508290637dc7a0d960e11b5f5260018060a01b031660045260245260445260645ffd5b6001600160a01b0316908115610c6d576001600160a01b0316918215610c5a57815f525f60205260405f2054818110610c4157817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b9091906001600160a01b03168015610c6d57805f525f60205260405f2054838110610cea576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b915063391434e360e21b5f5260045260245260445260645ffdfea26469706673582212201aca4a2b55465a13b08ec36674fca845ba424b771f3ea8c117e712cc7ec430c264736f6c63430008230033a2646970667358221220272ca8beeb8120e5fcea1f6abad3910174ee29119b3514eea8a2ceccb1bdce8764736f6c63430008230033","sourceMap":"710:1647:22:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;888:49;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;838:44;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;800:32;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;710:1647:22;;;;;;-1:-1:-1;;710:1647:22;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;1376:7;-1:-1:-1;;;;;710:1647:22;;1362:10;:21;;;1358:46;;1900:6;;;;:::i;:::-;1894:25;;;:54;;;;710:1647;1894:85;;;;710:1647;1894:116;;;;710:1647;1894:146;;;;710:1647;1894:184;;;;710:1647;1890:214;;2124:9;;;;2152:3;2124:17;:9;;;;:::i;:::-;:17;;:::i;:::-;2118:37;;;:79;;;;710:1647;2118:120;;;;710:1647;2118:161;;;;710:1647;2118:204;;;;710:1647;2114:234;;710:1647;1471:32;;710:1647;;;;1491:11;;;710:1647;;;;;;1471:32;;;710:1647;;;;;;;;;;;;;;;;;1461:43;;1530:84;;;;;;1471:32;1530:84;;;;;710:1647;1530:84;;;;;;;;;;710:1647;-1:-1:-1;;;;;1575:9:22;710:1647;;2124:9;710:1647;;;1586:12;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1491:11;710:1647;;;;;;;;;2152:3;710:1647;;;;;;;;;;;;;1491:11;710:1647;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;;;;;;2124:9;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;1530:84;;;;;710:1647;1530:84;;;;;-1:-1:-1;;;;;710:1647:22;;1678:11;;;;:::i;:::-;1691:13;;710:1647;1691:13;710:1647;1691:13;;;;:::i;:::-;1706:11;;;1739:14;1719:18;1706:11;710:1647;1706:11;;;;:::i;:::-;1719:18;;;;;;:::i;:::-;1739:14;;;;:::i;:::-;710:1647;;;1641:165;;;;;;;;;;710:1647;1641:165;;;;;;;710:1647;1641:165;710:1647;1641:165;;710:1647;1641:165;;710:1647;1641:165;710:1647;1641:165;710:1647;1641:165;;;;710:1647;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;1471:32;710:1647;;;;:::i;:::-;;;;2124:9;710:1647;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;1471:32;710:1647;;;;:::i;:::-;;;;;1471:32;710:1647;;;;:::i;:::-;;2124:9;710:1647;;;;:::i;:::-;;2124:9;710:1647;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2152:3;710:1647;;;1491:11;710:1647;;;;;1641:165;;710:1647;1641:165;;;;;710:1647;;;-1:-1:-1;;;;;710:1647:22;;;;;;;;;;;;;1641:165;710:1647;;;;;;;;;1641:165;710:1647;;;;;;;;;;;2114:234;2087:17;;;710:1647;2331:17;710:1647;;2331:17;2118:204;2289:9;2152:3;2289:19;:9;;;;:::i;:::-;2124;2289:19;;;;:::i;:::-;2283:39;;;2118:204;;:161;2248:9;2152:3;2248:17;:9;;;;:::i;:::-;:17;;;;;:::i;:::-;2242:37;;;2118:161;;:120;2207:9;2152:3;2207:17;:9;;;;:::i;:::-;710:1647;2207:17;;;;:::i;:::-;2201:37;;;2118:120;;:79;2165:9;2152:3;2165:18;:9;;;;:::i;:::-;710:1647;2165:18;;;;:::i;:::-;2159:38;;;2118:79;;1894:184;2050:13;2074:4;2050:13;;;;;;:::i;:::-;2044:34;;;1894:184;;:146;2020:6;2037:3;2020:6;;;;;;:::i;:::-;2014:26;;;1894:146;;:116;1989:8;2008:2;1989:8;710:1647;1989:8;;;;:::i;:::-;1983:27;;;1894:116;;:85;1958:8;;710:1647;1958:8;;;;:::i;:::-;1952:27;;;1894:85;;:54;1929:6;710:1647;1929:6;;;;:::i;:::-;1923:25;;;1894:54;;1358:46;1392:12;;;710:1647;1392:12;710:1647;;1392:12;710:1647;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;710:1647:22;;;;;;;;-1:-1:-1;;710:1647:22;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o","linkReferences":{},"immutableReferences":{"8651":[{"start":233,"length":32},{"start":386,"length":32}],"8654":[{"start":165,"length":32},{"start":653,"length":32}],"8657":[{"start":93,"length":32},{"start":693,"length":32}]}}}}}}},"signatures":{"function":[{"signature":"buybackVault()","signatureHash4":"0xf1f5c993","signatureHash32":"0xf1f5c993ccb3f93b450c0d36b9999158ea17a56907576709d04c9a76cf5f7d06"},{"signature":"deployLaunch((string,string,string,string,(string,string,string,string,string),address,uint16,bool,bytes32,bytes32,address[]),(address,address,uint256,uint256,uint256,bool),(address,uint16,uint16,uint16,uint16),address,uint256,uint256)","signatureHash4":"0x8dabdc83","signatureHash32":"0x8dabdc837d90fa58929bc03d3ca43b4a763a8c30d00c60a72de8b08c5312ecef"},{"signature":"factory()","signatureHash4":"0xc45a0155","signatureHash32":"0xc45a01550ceb4bc5c6b2e6f722b5033a03078f9bd6673457375ba94c26ac1cf0"},{"signature":"feeEscrow()","signatureHash4":"0xc4b7de97","signatureHash32":"0xc4b7de97cd4ac57ef574c54dc88537fe05d3734b2fab89e3bb031fccc9d91d6d"}],"event":[],"error":[{"signature":"InvalidMetadata()","signatureHash4":"0xbcecb64a","signatureHash32":"0xbcecb64a064c6f73f45dff9d011acd14cfeb2e05129a3a1a7281e7d4a2bfce1d"},{"signature":"NotFactory()","signatureHash4":"0x32cc7236","signatureHash32":"0x32cc723614e775fc4a8386492bc9a860c12fe98d5f5f28ec17e265818645b229"}]},"proxyResolution":{"isProxy":false,"proxyType":null,"implementations":[]},"match":"exact_match","chainId":"4663","address":"0xE39E27560A0c6bb38E54771Bf3Dc8E4C79928F93"}