{"matchId":"47533022","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-09-08T16:11:15Z","creationBytecode":{"onchainBytecode":"0x60a034609057601f610a1f38819003918201601f19168301916001600160401b03831184841017609457808492602094604052833981010312609057516001600160a01b038116810360905760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005560805260405161097690816100a98239608051818181604701526101320152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0","recompiledBytecode":"0x60a034609057601f610a1f38819003918201601f19168301916001600160401b03831184841017609457808492602094604052833981010312609057516001600160a01b038116810360905760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005560805260405161097690816100a98239608051818181604701526101320152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","sourceMap":"545:1579:21:-:0;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;;;;;2365:1:13;1505:66;2365:1;810:18:21;;545:1579;;;;;;;;810:18;545:1579;;;;;;;;;;;;-1:-1:-1;545:1579:21;;;;;;-1:-1:-1;545:1579:21;;;;;-1:-1:-1;545:1579:21","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","offset":2538}},"transformations":[{"type":"insert","offset":2591,"reason":"constructorArguments"}],"transformationValues":{"constructorArguments":"0x000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0"}},"runtimeBytecode":{"onchainBytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b06001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b06001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","recompiledBytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","sourceMap":"545:1579:21:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;631:45;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;2407:1:13;1505:66;545:1579:21;4560:63:13;3644:93;;2407:1;1505:66;2407:1;545:1579:21;1073:15;;;:26;1069:56;;-1:-1:-1;;;1149:19:21;;:7;-1:-1:-1;;;;;545:1579:21;;;;;;;1149:19;;;;;;;545:1579;1149:19;;;545:1579;-1:-1:-1;1202:23:21;;;:41;;;;;;545:1579;;;;;;;1182:9;:62;1178:89;;1281:16;;;;;:38;;1202:41;1277:67;;545:1579;;-1:-1:-1;;;1371:65:21;;545:1579;;1371:65;;545:1579;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;-1:-1:-1;;545:1579:21;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;-1:-1:-1;;545:1579:21;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;-1:-1:-1;;;;;545:1579:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1425:10;545:1579;;;;1371:65;;;;;;;;;545:1579;;;1371:65;;;545:1579;1450:16;;1446:670;;545:1579;;1505:66:13;2407:1;545:1579:21;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;;;;1446:670;1482:624;;;;;;;;;;-1:-1:-1;545:1579:21;;-1:-1:-1;;;1526:100:21;;545:1579;1526:100;;545:1579;;;;;;;;;;1425:10;545:1579;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;1526:100;;;;;;545:1579;1526:100;;;1482:624;545:1579;1511:115;;1482:624;;1446:670;;;;;;1526:100;;545:1579;1526:100;;545:1579;1526:100;;;;;;545:1579;1526:100;;;:::i;:::-;;;545:1579;;;;;;;1526:100;;;;;-1:-1:-1;1526:100:21;;;545:1579;;;;;;;;;1482:624;545:1579;;;;;;;1687:42;;1723:4;545:1579;1687:42;;545:1579;;1687:42;545:1579;1687:42;;;;;;;;;545:1579;1687:42;;;1482:624;1767:47:10;545:1579:21;10404:1148:10;10365:28;;;;545:1579:21;10404:1148:10;1425:10:21;545:1579;10404:1148:10;1723:4:21;545:1579;10404:1148:10;545:1579:21;10404:1148:10;545:1579:21;;;10404:1148:10;;;;;545:1579:21;;10404:1148:10;;;;;;;1482:624:21;10404:1148:10;545:1579:21;10404:1148:10;545:1579:21;;10404:1148:10;1766:48;1762:126;;-1:-1:-1;;;1858:42:21;;1723:4;545:1579;1858:42;;545:1579;;1858:42;545:1579;1858:42;;;;;;;;;545:1579;1858:42;;;1482:624;545:1579;;;;;;;;;12233:1072:10;-1:-1:-1;;;545:1579:21;12233:1072:10;;;-1:-1:-1;;;;;12233:1072:10;;545:1579:21;12233:1072:10;;;545:1579:21;12233:1072:10;;;;12199:23;12233:1072;545:1579:21;;;;;12199:23:10;12233:1072;;;545:1579:21;;12233:1072:10;;;;;;;1482:624:21;545:1579;12233:1072:10;5189:43;5185:274;;1482:624:21;-1:-1:-1;545:1579:21;;-1:-1:-1;;;2014:77:21;;545:1579;2014:77;;545:1579;;;;;;;;1425:10;545:1579;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2014:77:21;;;;;;545:1579;2014:77;;;1482:624;545:1579;1999:92;;1482:624;;;2014:77;;545:1579;2014:77;;545:1579;2014:77;;;;;;545:1579;2014:77;;;:::i;:::-;;;545:1579;;;;;;;2014:77;;;;;-1:-1:-1;2014:77:21;;5185:274:10;545:1579:21;12233:1072:10;12199:23;;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;545:1579:21;;12233:1072:10;545:1579:21;;;12233:1072:10;;;;;;545:1579:21;;12233:1072:10;;;;;;;5185:274;545:1579:21;12233:1072:10;5252:38;5248:91;;545:1579:21;12233:1072:10;12199:23;;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;545:1579:21;;;12233:1072:10;;;;;;545:1579:21;;12233:1072:10;;;;;;;5185:274;545:1579:21;12233:1072:10;5185:274;5353:95;;1837:40;;;545:1579:21;5408:40:10;545:1579:21;;;;5408:40:10;12233:1072;;545:1579:21;12233:1072:10;;;;;;;;;;;;;;;;;;;545:1579:21;12233:1072:10;;;;;;;545:1579:21;12233:1072:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;545:1579:21;;;;;;;;;;;;1858:42;;;;545:1579;1858:42;;545:1579;1858:42;;;;;;545:1579;1858:42;;;:::i;:::-;;;545:1579;;;;;1858:42;;;;;;;-1:-1:-1;1858:42:21;;1762:126:10;1837:40;;;;545:1579:21;1837:40:10;545:1579:21;;;;1837:40:10;10404:1148;545:1579:21;10404:1148:10;;;;;;;;;;;;;;;;;;545:1579:21;10404:1148:10;;;;;1687:42:21;;;545:1579;1687:42;;545:1579;1687:42;;;;;;545:1579;1687:42;;;:::i;:::-;;;545:1579;;;;;1687:42;;;;;;-1:-1:-1;1687:42:21;;1371:65;;;;;545:1579;1371:65;;545:1579;1371:65;;;;;;545:1579;1371:65;;;:::i;:::-;;;545:1579;;;;;;;;;:::i;:::-;;;;:::i;:::-;1371:65;;;;;;;-1:-1:-1;1371:65:21;;545:1579;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1277:67;1328:16;;;545:1579;1328:16;545:1579;;1328:16;1281:38;1301:18;;;;1281:38;;1178:89;1253:14;;;545:1579;1253:14;545:1579;;1253:14;1202:41;545:1579;1202:41;;1149:19;;;545:1579;1149:19;;545:1579;1149:19;;;;;;545:1579;1149:19;;;:::i;:::-;;;545:1579;;;;;1149:19;;;;;;-1:-1:-1;1149:19:21;;1069:56;1108:17;;;545:1579;1108:17;545:1579;;1108:17;3644:93:13;3696:30;;;545:1579:21;3696:30:13;545:1579:21;;3696:30:13;545:1579:21;;;-1:-1:-1;;;;;545:1579:21;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;545:1579:21;;;;;-1:-1:-1;545:1579:21;;;;-1:-1:-1;;;;;545:1579:21;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;545:1579:21;;;;;;;;-1:-1:-1;;545:1579:21;;;;:::o","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","offset":2369}},"immutableReferences":{"8422":[{"start":71,"length":32},{"start":306,"length":32}]},"transformations":[{"id":"8422","type":"replace","offset":71,"reason":"immutable"},{"id":"8422","type":"replace","offset":306,"reason":"immutable"}],"transformationValues":{"immutables":{"8422":"0x000000000000000000000000b60ea6a621613ff22263ba160e0e8accaca704b0"}}},"deployment":{"transactionHash":"0x501b0965ef5da1522b49887efbf6482938ef66e82f1ef06bc3398883a56db483","blockNumber":"57816704","transactionIndex":"1","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/BrishopFeeEscrow.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 {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} from \"./interfaces/IBrishop.sol\";\n\n/**\n * @title BrishopFeeEscrow\n * @notice Holds every v2 recipient's claimable balance in one place, so\n * protocol and creators claim revenue from across all of their pools in a\n * single transaction instead of collecting per position. Revenue arrives in\n * whichever asset the launch trades against: native ETH for a native launch,\n * and the launch's ERC-20 quote asset otherwise. Brishop's permanent curves\n * and buyback vault credit this same ledger.\n */\ncontract BrishopFeeEscrow is ReentrancyGuard, IBrishopFeeEscrow {\n    using SafeERC20 for IERC20;\n\n    error ZeroAddress();\n    error NoBalance();\n    error TransferFailed();\n    error InsufficientBalance(uint256 requested, uint256 available);\n\n    event Credited(address indexed recipient, address indexed depositor, uint256 amount);\n    event CreditedToken(address indexed recipient, address indexed token, address indexed depositor, uint256 amount);\n    event Claimed(address indexed recipient, uint256 amount);\n    event ClaimedToken(address indexed recipient, address indexed token, uint256 amount);\n\n    mapping(address recipient => uint256 amount) private _balances;\n    mapping(address recipient => mapping(address token => uint256 amount)) private _tokenBalances;\n\n    /**\n     * @notice Credits `msg.value` to `recipient`'s claimable native ETH balance.\n     * @dev Permissionless by design: the caller can only ever add value they\n     * already attached to the call, so there is no privilege to gate.\n     */\n    function credit(address recipient) external payable {\n        if (recipient == address(0)) revert ZeroAddress();\n        if (msg.value == 0) return;\n        _balances[recipient] += msg.value;\n        emit Credited(recipient, msg.sender, msg.value);\n    }\n\n    /**\n     * @notice Pulls `amount` of `token` from the caller and credits it to `recipient`.\n     * @dev Permissionless by design: the caller can only credit tokens they\n     * already hold and approve, so there is no privilege to gate. Credits\n     * the actual balance delta rather than the nominal `amount`, so a\n     * fee-on-transfer or deflationary pairToken can never make this\n     * contract record more credited liability than it actually holds,\n     * which would otherwise starve whichever recipient claims that token\n     * last.\n     */\n    function creditToken(address recipient, address token, uint256 amount) external nonReentrant {\n        if (recipient == address(0) || token == address(0)) revert ZeroAddress();\n        if (amount == 0) return;\n        uint256 balanceBefore = IERC20(token).balanceOf(address(this));\n        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n        uint256 received = IERC20(token).balanceOf(address(this)) - balanceBefore;\n        if (received == 0) return;\n        _tokenBalances[recipient][token] += received;\n        emit CreditedToken(recipient, token, msg.sender, received);\n    }\n\n    /**\n     * @notice Pays out the caller's entire claimable native ETH balance.\n     */\n    function claim() external nonReentrant returns (uint256 amount) {\n        amount = _claim(_balances[msg.sender]);\n    }\n\n    /**\n     * @notice Pays out `amount` of the caller's claimable native ETH balance.\n     */\n    function claim(uint256 amount) external nonReentrant returns (uint256) {\n        return _claim(amount);\n    }\n\n    /**\n     * @notice Pays out the caller's entire claimable balance of `token`.\n     */\n    function claimToken(address token) external nonReentrant returns (uint256 amount) {\n        amount = _claimToken(token, _tokenBalances[msg.sender][token]);\n    }\n\n    /**\n     * @notice Pays out `amount` of the caller's claimable balance of `token`.\n     * @dev A recipient's balance aggregates credits from every launch, curve,\n     * curve and buyback release, and `creditToken` is permissionless, so a\n     * third party can enlarge that figure at will. Against a token with a\n     * fixed maximum per transfer, a single full-balance claim would then\n     * revert and leave the recipient unable to draw any of it. Choosing the\n     * amount keeps the aggregate from being a single point of failure, and\n     * lets a recipient work around any per-transfer limit its quote asset\n     * imposes.\n     */\n    function claimToken(address token, uint256 amount) external nonReentrant returns (uint256) {\n        return _claimToken(token, amount);\n    }\n\n    /**\n     * @dev Shared debit path for both native claim entry points.\n     */\n    function _claim(uint256 amount) private returns (uint256) {\n        if (amount == 0) revert NoBalance();\n        uint256 balance = _balances[msg.sender];\n        if (amount > balance) revert InsufficientBalance(amount, balance);\n\n        _balances[msg.sender] = balance - amount;\n        (bool sent,) = payable(msg.sender).call{value: amount}(\"\");\n        if (!sent) revert TransferFailed();\n\n        emit Claimed(msg.sender, amount);\n        return amount;\n    }\n\n    /**\n     * @dev Shared debit path for both ERC-20 claim entry points.\n     */\n    function _claimToken(address token, uint256 amount) private returns (uint256) {\n        if (amount == 0) revert NoBalance();\n        uint256 balance = _tokenBalances[msg.sender][token];\n        if (amount > balance) revert InsufficientBalance(amount, balance);\n\n        _tokenBalances[msg.sender][token] = balance - amount;\n        IERC20(token).safeTransfer(msg.sender, amount);\n\n        emit ClaimedToken(msg.sender, token, amount);\n        return amount;\n    }\n\n    /**\n     * @notice Returns the claimable native ETH balance for `recipient`.\n     */\n    function balanceOf(address recipient) external view returns (uint256) {\n        return _balances[recipient];\n    }\n\n    /**\n     * @notice Returns the claimable balance of `token` for `recipient`.\n     */\n    function balanceOfToken(address recipient, address token) external view returns (uint256) {\n        return _tokenBalances[recipient][token];\n    }\n}\n"},"src/BrishopLaunchAndBuy.sol":{"content":"// SPDX-License-Identifier: MIT\n// Atomic launch pattern derived from PONS v2; see ../NOTICE.md.\npragma solidity ^0.8.26;\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 {BrishopLaunchFactory} from \"./BrishopLaunchFactory.sol\";\nimport {TokenParams} from \"./BrishopLaunchDeployer.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\n\ncontract BrishopLaunchAndBuy is ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    BrishopLaunchFactory public immutable factory;\n    error InvalidValue();\n    error DeadlineExpired();\n    error InvalidMinimum();\n    constructor(BrishopLaunchFactory factory_) { factory = factory_; }\n    function launchAndBuy(TokenParams calldata params, address pairToken, uint256 quoteAmount, uint256 minimumTokens, uint256 deadline) external payable nonReentrant returns (address token, address curve, uint256 tokensBought) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        uint256 fee = factory.launchFee();\n        if (msg.value != fee + (pairToken == address(0) ? quoteAmount : 0)) revert InvalidValue();\n        if (quoteAmount == 0 && minimumTokens != 0) revert InvalidMinimum();\n        (token, curve) = factory.launchTokenFor{value: fee}(params, pairToken, msg.sender);\n        if (quoteAmount != 0) {\n            if (pairToken == address(0)) tokensBought = BrishopBondingCurve(curve).buy{value: quoteAmount}(quoteAmount, minimumTokens, msg.sender, deadline);\n            else {\n                uint256 beforeBalance = IERC20(pairToken).balanceOf(address(this));\n                IERC20(pairToken).safeTransferFrom(msg.sender, address(this), quoteAmount);\n                uint256 received = IERC20(pairToken).balanceOf(address(this)) - beforeBalance;\n                IERC20(pairToken).forceApprove(curve, received);\n                tokensBought = BrishopBondingCurve(curve).buy(received, minimumTokens, msg.sender, deadline);\n            }\n        }\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/BrishopLaunchFactory.sol":{"content":"// SPDX-License-Identifier: MIT\n// PONS-derived launch/fee policy, with permanent Brishop markets. See ../NOTICE.md.\npragma solidity ^0.8.26;\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 {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {BrishopFeeEscrow} from \"./BrishopFeeEscrow.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {BrishopLaunchDeployer, TokenParams} from \"./BrishopLaunchDeployer.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\nimport {FeePolicySnapshot, IBrishopFeePolicy, IBrishopFeeEscrow, IBrishopLaunchFactory} from \"./interfaces/IBrishop.sol\";\n\ninterface IEthUsdFeed {\n    function decimals() external view returns (uint8);\n    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);\n}\n\ncontract BrishopLaunchFactory is Ownable2Step, ReentrancyGuard, IBrishopFeePolicy, IBrishopLaunchFactory {\n    uint256 public constant SUPPLY = 1_000_000_000 ether;\n    uint256 public constant BASE_PHANTOM_ETH = 1.68 ether;\n    uint256 public constant CREATOR_RECOVERY_DELAY = 3 days;\n    uint256 public constant CREATOR_RECOVERY_WINDOW = 3 days;\n    uint256 public constant ORACLE_MAX_AGE = 1 days;\n    uint256 public launchFee = 0.0005 ether;\n    uint256 public maxCreatorTaxBps = 1_000;\n    uint256 public snipeTaxStartBps = 9_900;\n    uint256 public snipeTaxSeconds = 3;\n    address public feeSweepOperator;\n    address public launchForwarder;\n    BrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    BrishopLaunchDeployer public immutable launchDeployer;\n    IEthUsdFeed public immutable ethUsdFeed;\n    uint8 public immutable oracleDecimals;\n    FeePolicySnapshot private _policy;\n    mapping(address => LaunchedToken) private _launches;\n    mapping(address => FeePolicySnapshot) private _launchPolicies;\n    address[] private _tokens;\n    mapping(bytes32 => address) public personalities;\n    mapping(address => mapping(bytes32 => bool)) public usedSalt;\n    struct PairEconomics { uint256 phantomQuote; bool enabled; }\n    mapping(address => PairEconomics) public pairEconomics;\n    struct PendingRecipient { address recipient; uint256 effectiveAt; uint256 expiresAt; }\n    mapping(address => PendingRecipient) public pendingCreatorFeeRecipient;\n\n    error ZeroAddress();\n    error AlreadySet();\n    error PairTokenNotApproved();\n    error LaunchEconomicsMismatch();\n    error LaunchFeeNotPaid();\n    error CreatorTaxTooHigh();\n    error InvalidTerms();\n    error SaltAlreadyUsed();\n    error UnknownToken();\n    error NotLaunchForwarder();\n    error NotCreatorFeeRecipient();\n    error InvalidOraclePrice();\n    error InvalidPersonalityValuation();\n    error DuplicatePersonality();\n    error RecoveryNotExecutable();\n    event TokenLaunched(address indexed token, address indexed curve, address indexed deployer, address pairToken, uint256 phantomQuote, bool personality, uint256 creatorAllocation);\n    event PersonalityLaunched(bytes32 indexed id, address indexed token, uint256 targetFdvUsd, uint256 ethUsdAnswer);\n    event PairEconomicsUpdated(address indexed pairToken, uint256 phantomQuote, bool enabled);\n    event LaunchForwarderSet(address forwarder);\n    event TermsUpdated();\n    event FeeSweepOperatorUpdated(address operator);\n    event CreatorFeeRecipientUpdated(address indexed token, address indexed oldRecipient, address indexed newRecipient);\n    event CreatorFeeRecipientChangeProposed(address indexed token, address recipient, uint256 effectiveAt, uint256 expiresAt);\n    event CreatorFeeRecipientChangeCancelled(address indexed token);\n\n    constructor(address initialOwner, IEthUsdFeed feed) Ownable(initialOwner) {\n        if (address(feed).code.length == 0) revert ZeroAddress();\n        ethUsdFeed = feed;\n        uint8 decimals_ = feed.decimals();\n        if (decimals_ > 18) revert InvalidOraclePrice();\n        oracleDecimals = decimals_;\n        feeSweepOperator = initialOwner;\n        _policy = FeePolicySnapshot(initialOwner, 3_000, 5_000, 100, 300);\n        feeEscrow = new BrishopFeeEscrow();\n        buybackVault = new BrishopBuybackVault(address(this), IBrishopFeePolicy(address(this)), IBrishopFeeEscrow(address(feeEscrow)));\n        buybackVault.setFactory(address(this));\n        launchDeployer = new BrishopLaunchDeployer(address(this), IBrishopFeeEscrow(address(feeEscrow)), buybackVault);\n        pairEconomics[address(0)] = PairEconomics(BASE_PHANTOM_ETH, true);\n    }\n\n    function currentFeePolicy() external view returns (FeePolicySnapshot memory) { return _policy; }\n    function getLaunchFeePolicy(address token) external view returns (FeePolicySnapshot memory) { _requireLaunch(token); return _launchPolicies[token]; }\n    function getLaunchedToken(address token) external view returns (LaunchedToken memory) { return _launches[token]; }\n    function launchCount() external view returns (uint256) { return _tokens.length; }\n    function launchedTokenAt(uint256 index) external view returns (address) { return _tokens[index]; }\n    function canLaunch(address) external pure returns (bool) { return true; }\n\n    function previewLaunchEconomics(address pairToken) public view returns (bytes32) {\n        PairEconomics memory pair = pairEconomics[pairToken];\n        if (!pair.enabled) revert PairTokenNotApproved();\n        return _economicsHash(pairToken, pair.phantomQuote, false);\n    }\n\n    function previewPersonalityEconomics(uint256 targetFdvUsd) public view returns (bytes32 economics, uint256 phantomQuote, uint256 price) {\n        if (targetFdvUsd < 18_000 || targetFdvUsd > 25_000) revert InvalidPersonalityValuation();\n        (, int256 answer,, uint256 updatedAt,) = ethUsdFeed.latestRoundData();\n        if (answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || block.timestamp - updatedAt > ORACLE_MAX_AGE) revert InvalidOraclePrice();\n        price = uint256(answer);\n        // 75% inventory: FDV = phantomQuote / 0.75 * ETH/USD.\n        phantomQuote = Math.mulDiv(targetFdvUsd * 1 ether, 3 * 10 ** oracleDecimals, 4 * price);\n        if (phantomQuote == 0 || phantomQuote > type(uint128).max) revert InvalidPersonalityValuation();\n        economics = _economicsHash(address(0), phantomQuote, true);\n    }\n\n    function _economicsHash(address pairToken, uint256 phantomQuote, bool personality) private view returns (bytes32) {\n        return keccak256(abi.encode(block.chainid, address(this), SUPPLY, pairToken, phantomQuote, personality, launchFee, maxCreatorTaxBps, snipeTaxStartBps, snipeTaxSeconds, _policy));\n    }\n\n    function launchToken(TokenParams calldata params, address pairToken) external payable nonReentrant returns (address token, address curve) {\n        return _launchCommunity(params, pairToken, msg.sender);\n    }\n    function launchTokenFor(TokenParams calldata params, address pairToken, address creator) external payable nonReentrant returns (address token, address curve) {\n        if (msg.sender != launchForwarder || creator == address(0)) revert NotLaunchForwarder();\n        return _launchCommunity(params, pairToken, creator);\n    }\n    function _launchCommunity(TokenParams calldata params, address pairToken, address creator) private returns (address token, address curve) {\n        if (params.expectedEconomics != previewLaunchEconomics(pairToken)) revert LaunchEconomicsMismatch();\n        return _launch(params, pairToken, creator, pairEconomics[pairToken].phantomQuote, false);\n    }\n\n    /// @notice Only the administrator may mint a personality. The 25% allocation\n    /// goes directly to that administrator, is transferable, and receives no ETH.\n    function launchPersonality(TokenParams calldata params, bytes32 id, uint256 targetFdvUsd) external payable onlyOwner nonReentrant returns (address token, address curve) {\n        if (id == bytes32(0) || personalities[id] != address(0)) revert DuplicatePersonality();\n        (bytes32 economics, uint256 phantomQuote, uint256 price) = previewPersonalityEconomics(targetFdvUsd);\n        if (params.expectedEconomics != economics) revert LaunchEconomicsMismatch();\n        (token, curve) = _launch(params, address(0), msg.sender, phantomQuote, true);\n        personalities[id] = token;\n        uint256 quotePhantom = Math.mulDiv(BASE_PHANTOM_ETH, SUPPLY * 3 / 4, phantomQuote);\n        pairEconomics[token] = PairEconomics(quotePhantom, true);\n        emit PairEconomicsUpdated(token, quotePhantom, true);\n        emit PersonalityLaunched(id, token, targetFdvUsd, price);\n    }\n\n    function _launch(TokenParams calldata params, address pairToken, address creator, uint256 phantomQuote, bool personality) private returns (address token, address curve) {\n        if (msg.value != launchFee) revert LaunchFeeNotPaid();\n        if (params.creatorTaxBps > maxCreatorTaxBps || uint256(params.creatorTaxBps) + _policy.hookFeeBps > 2_000) revert CreatorTaxTooHigh();\n        if (usedSalt[creator][params.salt]) revert SaltAlreadyUsed();\n        if (params.snipeTaxExemptions.length > 32) revert InvalidTerms();\n        usedSalt[creator][params.salt] = true;\n        address recipient = params.creatorFeeRecipient == address(0) ? creator : params.creatorFeeRecipient;\n        uint256 allocation = personality ? SUPPLY / 4 : 0;\n        BrishopBondingCurve.Terms memory terms = BrishopBondingCurve.Terms(pairToken, recipient, phantomQuote, _policy.hookFeeBps, params.creatorTaxBps, params.buybackEnabled);\n        (token, curve) = launchDeployer.deployLaunch(params, terms, _policy, creator, SUPPLY, allocation);\n        _launches[token] = LaunchedToken(token, curve, creator, recipient, pairToken, params.creatorTaxBps, params.buybackEnabled, personality, true);\n        _launchPolicies[token] = _policy;\n        _tokens.push(token);\n        address[] memory exemptions = new address[](params.snipeTaxExemptions.length + 2);\n        exemptions[0] = creator;\n        exemptions[1] = recipient;\n        for (uint256 i; i < params.snipeTaxExemptions.length; ++i) exemptions[i + 2] = params.snipeTaxExemptions[i];\n        BrishopBondingCurve(curve).initialize(token, exemptions);\n        if (launchFee != 0) feeEscrow.credit{value: launchFee}(_policy.protocolFeeRecipient);\n        emit TokenLaunched(token, curve, creator, pairToken, phantomQuote, personality, allocation);\n    }\n\n    function setLaunchForwarder(address forwarder) external onlyOwner {\n        if (launchForwarder != address(0)) revert AlreadySet();\n        if (forwarder.code.length == 0) revert ZeroAddress();\n        launchForwarder = forwarder;\n        emit LaunchForwarderSet(forwarder);\n    }\n    function setFeeSweepOperator(address operator) external onlyOwner {\n        if (operator == address(0)) revert ZeroAddress();\n        feeSweepOperator = operator;\n        emit FeeSweepOperatorUpdated(operator);\n    }\n    /// @notice Updates terms for future launches only; existing curves snapshot them.\n    function setLaunchTerms(uint256 newLaunchFee, uint256 creatorTaxMax, uint256 snipeStart, uint256 snipeWindow, FeePolicySnapshot calldata policy) external onlyOwner {\n        if (creatorTaxMax > 1_000 || snipeStart > 9_900 || snipeWindow == 0 || snipeWindow > 1 days || policy.protocolFeeRecipient == address(0) || policy.protocolFeeShareBps > 10_000 || policy.buybackBurnBps > 10_000 || policy.hookFeeBps > 1_000 || policy.maxInternalPriceImpactBps == 0 || policy.maxInternalPriceImpactBps >= 10_000) revert InvalidTerms();\n        launchFee = newLaunchFee; maxCreatorTaxBps = creatorTaxMax; snipeTaxStartBps = snipeStart; snipeTaxSeconds = snipeWindow; _policy = policy;\n        emit TermsUpdated();\n    }\n    function setPairEconomics(address pairToken, uint256 phantomQuote, bool enabled) external onlyOwner {\n        if (pairToken != address(0) && !_launches[pairToken].personality) revert PairTokenNotApproved();\n        if (phantomQuote == 0 || phantomQuote > type(uint128).max) revert InvalidTerms();\n        pairEconomics[pairToken] = PairEconomics(phantomQuote, enabled);\n        emit PairEconomicsUpdated(pairToken, phantomQuote, enabled);\n    }\n    function setBuybackEnabled(address token, bool enabled) external {\n        LaunchedToken storage launch = _requireLaunch(token);\n        if (msg.sender != launch.creatorFeeRecipient && (msg.sender != owner() || enabled)) revert NotCreatorFeeRecipient();\n        launch.buybackEnabled = enabled;\n        BrishopBondingCurve(launch.curve).setBuybackEnabled(enabled);\n    }\n    function transferCreatorFeeRecipient(address token, address recipient) external {\n        LaunchedToken storage launch = _requireLaunch(token);\n        if (msg.sender != launch.creatorFeeRecipient) revert NotCreatorFeeRecipient();\n        _updateRecipient(token, recipient);\n    }\n    function proposeCreatorFeeRecipient(address token, address recipient) external onlyOwner {\n        _requireLaunch(token);\n        if (recipient == address(0)) revert ZeroAddress();\n        uint256 effective = block.timestamp + CREATOR_RECOVERY_DELAY;\n        pendingCreatorFeeRecipient[token] = PendingRecipient(recipient, effective, effective + CREATOR_RECOVERY_WINDOW);\n        emit CreatorFeeRecipientChangeProposed(token, recipient, effective, effective + CREATOR_RECOVERY_WINDOW);\n    }\n    function cancelCreatorFeeRecipientChange(address token) external onlyOwner {\n        delete pendingCreatorFeeRecipient[token];\n        emit CreatorFeeRecipientChangeCancelled(token);\n    }\n    function executeCreatorFeeRecipientChange(address token) external onlyOwner {\n        PendingRecipient memory pending = pendingCreatorFeeRecipient[token];\n        if (pending.recipient == address(0) || block.timestamp < pending.effectiveAt || block.timestamp > pending.expiresAt) revert RecoveryNotExecutable();\n        delete pendingCreatorFeeRecipient[token];\n        _updateRecipient(token, pending.recipient);\n    }\n    function _updateRecipient(address token, address recipient) private {\n        if (recipient == address(0)) revert ZeroAddress();\n        LaunchedToken storage launch = _requireLaunch(token);\n        address previous = launch.creatorFeeRecipient;\n        launch.creatorFeeRecipient = recipient;\n        BrishopBondingCurve(launch.curve).setCreatorFeeRecipient(recipient);\n        buybackVault.updateCreatorRecipient(token, recipient);\n        emit CreatorFeeRecipientUpdated(token, previous, recipient);\n    }\n    function _requireLaunch(address token) private view returns (LaunchedToken storage launch) {\n        launch = _launches[token];\n        if (!launch.exists) revert UnknownToken();\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":"BrishopLaunchAndBuy","fullyQualifiedName":"src/BrishopLaunchAndBuy.sol:BrishopLaunchAndBuy"},"abi":[{"type":"constructor","inputs":[{"name":"factory_","type":"address","internalType":"contract BrishopLaunchFactory"}],"stateMutability":"nonpayable"},{"name":"DeadlineExpired","type":"error","inputs":[]},{"name":"InvalidMinimum","type":"error","inputs":[]},{"name":"InvalidValue","type":"error","inputs":[]},{"name":"ReentrancyGuardReentrantCall","type":"error","inputs":[]},{"name":"SafeERC20FailedOperation","type":"error","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"name":"factory","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract BrishopLaunchFactory"}],"stateMutability":"view"},{"name":"launchAndBuy","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":"pairToken","type":"address","internalType":"address"},{"name":"quoteAmount","type":"uint256","internalType":"uint256"},{"name":"minimumTokens","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"token","type":"address","internalType":"address"},{"name":"curve","type":"address","internalType":"address"},{"name":"tokensBought","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"}],"metadata":{"compiler":{"version":"0.8.35+commit.47b9dedd"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"contract BrishopLaunchFactory","name":"factory_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[],"name":"InvalidMinimum","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract BrishopLaunchFactory","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"},{"internalType":"address","name":"pairToken","type":"address"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"uint256","name":"minimumTokens","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"launchAndBuy","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"curve","type":"address"},{"internalType":"uint256","name":"tokensBought","type":"uint256"}],"stateMutability":"payable","type":"function"}],"devdoc":{"errors":{"ReentrancyGuardReentrantCall()":[{"details":"Unauthorized reentrant call."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"src/BrishopLaunchAndBuy.sol":"BrishopLaunchAndBuy"},"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/BrishopFeeEscrow.sol":{"keccak256":"0x361a29a736f82d65989960e20cc37d80e5f0ec1ee909a4799df91bcef1141ca0","license":"MIT","urls":["bzz-raw://27624435e94dd282fc36e0d39ceceff413cbcf314b9c38350168b4accb739988","dweb:/ipfs/QmT73E2hkE4UKyy6ZqujJsNEjHLYvMnnQSyw2Xhcin4UU4"]},"src/BrishopLaunchAndBuy.sol":{"keccak256":"0x769f389c1c33f71da625ac1fe28cfa628b74069b91a2d179e47d52ab692cbfb3","license":"MIT","urls":["bzz-raw://a6ee7e7a69fe35058298f1cd26175a71106db3789057d4b83a4e5401bb281d8f","dweb:/ipfs/Qmd7JGTYNNoKTaeZRm6Yi26wvcUcUmkqjN1hn4ajWu3pUa"]},"src/BrishopLaunchDeployer.sol":{"keccak256":"0x0f81d31836aa2a5d416979c07a14635bf3d182e2a2e955e631cae8d0afe1d544","license":"MIT","urls":["bzz-raw://f6c655be8bfc3007ed89e0734a9a27d26bcd3ce27483c10648d605304b2f3526","dweb:/ipfs/QmUChkKtVzv31TgNXQY8FGaZqeajBj7QhPXXSHep9kj5pe"]},"src/BrishopLaunchFactory.sol":{"keccak256":"0x4bf1ae68473202a8688fc818b97fbd6ed91fe27574e60859a8bf68b345b91ef9","license":"MIT","urls":["bzz-raw://c48a43af297f76683a83c086b05cbe5cfeeae87098c78ad8b228e2d9558a9f53","dweb:/ipfs/QmboPttLauLG6HzvRznmgGA7QRsodv6CoLtUDK5iej48sC"]},"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","errors":{"ReentrancyGuardReentrantCall()":[{"details":"Unauthorized reentrant call."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"methods":{},"version":1},"sourceIds":{"src/BrishopFeeEscrow.sol":{"id":20},"src/BrishopBondingCurve.sol":{"id":18},"src/BrishopBuybackVault.sol":{"id":19},"src/BrishopLaunchAndBuy.sol":{"id":21},"src/interfaces/IBrishop.sol":{"id":25},"src/BrishopLaunchFactory.sol":{"id":23},"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/BrishopFeeEscrow.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 {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} from \"./interfaces/IBrishop.sol\";\n\n/**\n * @title BrishopFeeEscrow\n * @notice Holds every v2 recipient's claimable balance in one place, so\n * protocol and creators claim revenue from across all of their pools in a\n * single transaction instead of collecting per position. Revenue arrives in\n * whichever asset the launch trades against: native ETH for a native launch,\n * and the launch's ERC-20 quote asset otherwise. Brishop's permanent curves\n * and buyback vault credit this same ledger.\n */\ncontract BrishopFeeEscrow is ReentrancyGuard, IBrishopFeeEscrow {\n    using SafeERC20 for IERC20;\n\n    error ZeroAddress();\n    error NoBalance();\n    error TransferFailed();\n    error InsufficientBalance(uint256 requested, uint256 available);\n\n    event Credited(address indexed recipient, address indexed depositor, uint256 amount);\n    event CreditedToken(address indexed recipient, address indexed token, address indexed depositor, uint256 amount);\n    event Claimed(address indexed recipient, uint256 amount);\n    event ClaimedToken(address indexed recipient, address indexed token, uint256 amount);\n\n    mapping(address recipient => uint256 amount) private _balances;\n    mapping(address recipient => mapping(address token => uint256 amount)) private _tokenBalances;\n\n    /**\n     * @notice Credits `msg.value` to `recipient`'s claimable native ETH balance.\n     * @dev Permissionless by design: the caller can only ever add value they\n     * already attached to the call, so there is no privilege to gate.\n     */\n    function credit(address recipient) external payable {\n        if (recipient == address(0)) revert ZeroAddress();\n        if (msg.value == 0) return;\n        _balances[recipient] += msg.value;\n        emit Credited(recipient, msg.sender, msg.value);\n    }\n\n    /**\n     * @notice Pulls `amount` of `token` from the caller and credits it to `recipient`.\n     * @dev Permissionless by design: the caller can only credit tokens they\n     * already hold and approve, so there is no privilege to gate. Credits\n     * the actual balance delta rather than the nominal `amount`, so a\n     * fee-on-transfer or deflationary pairToken can never make this\n     * contract record more credited liability than it actually holds,\n     * which would otherwise starve whichever recipient claims that token\n     * last.\n     */\n    function creditToken(address recipient, address token, uint256 amount) external nonReentrant {\n        if (recipient == address(0) || token == address(0)) revert ZeroAddress();\n        if (amount == 0) return;\n        uint256 balanceBefore = IERC20(token).balanceOf(address(this));\n        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n        uint256 received = IERC20(token).balanceOf(address(this)) - balanceBefore;\n        if (received == 0) return;\n        _tokenBalances[recipient][token] += received;\n        emit CreditedToken(recipient, token, msg.sender, received);\n    }\n\n    /**\n     * @notice Pays out the caller's entire claimable native ETH balance.\n     */\n    function claim() external nonReentrant returns (uint256 amount) {\n        amount = _claim(_balances[msg.sender]);\n    }\n\n    /**\n     * @notice Pays out `amount` of the caller's claimable native ETH balance.\n     */\n    function claim(uint256 amount) external nonReentrant returns (uint256) {\n        return _claim(amount);\n    }\n\n    /**\n     * @notice Pays out the caller's entire claimable balance of `token`.\n     */\n    function claimToken(address token) external nonReentrant returns (uint256 amount) {\n        amount = _claimToken(token, _tokenBalances[msg.sender][token]);\n    }\n\n    /**\n     * @notice Pays out `amount` of the caller's claimable balance of `token`.\n     * @dev A recipient's balance aggregates credits from every launch, curve,\n     * curve and buyback release, and `creditToken` is permissionless, so a\n     * third party can enlarge that figure at will. Against a token with a\n     * fixed maximum per transfer, a single full-balance claim would then\n     * revert and leave the recipient unable to draw any of it. Choosing the\n     * amount keeps the aggregate from being a single point of failure, and\n     * lets a recipient work around any per-transfer limit its quote asset\n     * imposes.\n     */\n    function claimToken(address token, uint256 amount) external nonReentrant returns (uint256) {\n        return _claimToken(token, amount);\n    }\n\n    /**\n     * @dev Shared debit path for both native claim entry points.\n     */\n    function _claim(uint256 amount) private returns (uint256) {\n        if (amount == 0) revert NoBalance();\n        uint256 balance = _balances[msg.sender];\n        if (amount > balance) revert InsufficientBalance(amount, balance);\n\n        _balances[msg.sender] = balance - amount;\n        (bool sent,) = payable(msg.sender).call{value: amount}(\"\");\n        if (!sent) revert TransferFailed();\n\n        emit Claimed(msg.sender, amount);\n        return amount;\n    }\n\n    /**\n     * @dev Shared debit path for both ERC-20 claim entry points.\n     */\n    function _claimToken(address token, uint256 amount) private returns (uint256) {\n        if (amount == 0) revert NoBalance();\n        uint256 balance = _tokenBalances[msg.sender][token];\n        if (amount > balance) revert InsufficientBalance(amount, balance);\n\n        _tokenBalances[msg.sender][token] = balance - amount;\n        IERC20(token).safeTransfer(msg.sender, amount);\n\n        emit ClaimedToken(msg.sender, token, amount);\n        return amount;\n    }\n\n    /**\n     * @notice Returns the claimable native ETH balance for `recipient`.\n     */\n    function balanceOf(address recipient) external view returns (uint256) {\n        return _balances[recipient];\n    }\n\n    /**\n     * @notice Returns the claimable balance of `token` for `recipient`.\n     */\n    function balanceOfToken(address recipient, address token) external view returns (uint256) {\n        return _tokenBalances[recipient][token];\n    }\n}\n"},"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/BrishopLaunchAndBuy.sol":{"content":"// SPDX-License-Identifier: MIT\n// Atomic launch pattern derived from PONS v2; see ../NOTICE.md.\npragma solidity ^0.8.26;\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 {BrishopLaunchFactory} from \"./BrishopLaunchFactory.sol\";\nimport {TokenParams} from \"./BrishopLaunchDeployer.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\n\ncontract BrishopLaunchAndBuy is ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    BrishopLaunchFactory public immutable factory;\n    error InvalidValue();\n    error DeadlineExpired();\n    error InvalidMinimum();\n    constructor(BrishopLaunchFactory factory_) { factory = factory_; }\n    function launchAndBuy(TokenParams calldata params, address pairToken, uint256 quoteAmount, uint256 minimumTokens, uint256 deadline) external payable nonReentrant returns (address token, address curve, uint256 tokensBought) {\n        if (block.timestamp > deadline) revert DeadlineExpired();\n        uint256 fee = factory.launchFee();\n        if (msg.value != fee + (pairToken == address(0) ? quoteAmount : 0)) revert InvalidValue();\n        if (quoteAmount == 0 && minimumTokens != 0) revert InvalidMinimum();\n        (token, curve) = factory.launchTokenFor{value: fee}(params, pairToken, msg.sender);\n        if (quoteAmount != 0) {\n            if (pairToken == address(0)) tokensBought = BrishopBondingCurve(curve).buy{value: quoteAmount}(quoteAmount, minimumTokens, msg.sender, deadline);\n            else {\n                uint256 beforeBalance = IERC20(pairToken).balanceOf(address(this));\n                IERC20(pairToken).safeTransferFrom(msg.sender, address(this), quoteAmount);\n                uint256 received = IERC20(pairToken).balanceOf(address(this)) - beforeBalance;\n                IERC20(pairToken).forceApprove(curve, received);\n                tokensBought = BrishopBondingCurve(curve).buy(received, minimumTokens, msg.sender, deadline);\n            }\n        }\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/BrishopLaunchFactory.sol":{"content":"// SPDX-License-Identifier: MIT\n// PONS-derived launch/fee policy, with permanent Brishop markets. See ../NOTICE.md.\npragma solidity ^0.8.26;\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 {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {BrishopFeeEscrow} from \"./BrishopFeeEscrow.sol\";\nimport {BrishopBuybackVault} from \"./BrishopBuybackVault.sol\";\nimport {BrishopLaunchDeployer, TokenParams} from \"./BrishopLaunchDeployer.sol\";\nimport {BrishopBondingCurve} from \"./BrishopBondingCurve.sol\";\nimport {FeePolicySnapshot, IBrishopFeePolicy, IBrishopFeeEscrow, IBrishopLaunchFactory} from \"./interfaces/IBrishop.sol\";\n\ninterface IEthUsdFeed {\n    function decimals() external view returns (uint8);\n    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);\n}\n\ncontract BrishopLaunchFactory is Ownable2Step, ReentrancyGuard, IBrishopFeePolicy, IBrishopLaunchFactory {\n    uint256 public constant SUPPLY = 1_000_000_000 ether;\n    uint256 public constant BASE_PHANTOM_ETH = 1.68 ether;\n    uint256 public constant CREATOR_RECOVERY_DELAY = 3 days;\n    uint256 public constant CREATOR_RECOVERY_WINDOW = 3 days;\n    uint256 public constant ORACLE_MAX_AGE = 1 days;\n    uint256 public launchFee = 0.0005 ether;\n    uint256 public maxCreatorTaxBps = 1_000;\n    uint256 public snipeTaxStartBps = 9_900;\n    uint256 public snipeTaxSeconds = 3;\n    address public feeSweepOperator;\n    address public launchForwarder;\n    BrishopFeeEscrow public immutable feeEscrow;\n    BrishopBuybackVault public immutable buybackVault;\n    BrishopLaunchDeployer public immutable launchDeployer;\n    IEthUsdFeed public immutable ethUsdFeed;\n    uint8 public immutable oracleDecimals;\n    FeePolicySnapshot private _policy;\n    mapping(address => LaunchedToken) private _launches;\n    mapping(address => FeePolicySnapshot) private _launchPolicies;\n    address[] private _tokens;\n    mapping(bytes32 => address) public personalities;\n    mapping(address => mapping(bytes32 => bool)) public usedSalt;\n    struct PairEconomics { uint256 phantomQuote; bool enabled; }\n    mapping(address => PairEconomics) public pairEconomics;\n    struct PendingRecipient { address recipient; uint256 effectiveAt; uint256 expiresAt; }\n    mapping(address => PendingRecipient) public pendingCreatorFeeRecipient;\n\n    error ZeroAddress();\n    error AlreadySet();\n    error PairTokenNotApproved();\n    error LaunchEconomicsMismatch();\n    error LaunchFeeNotPaid();\n    error CreatorTaxTooHigh();\n    error InvalidTerms();\n    error SaltAlreadyUsed();\n    error UnknownToken();\n    error NotLaunchForwarder();\n    error NotCreatorFeeRecipient();\n    error InvalidOraclePrice();\n    error InvalidPersonalityValuation();\n    error DuplicatePersonality();\n    error RecoveryNotExecutable();\n    event TokenLaunched(address indexed token, address indexed curve, address indexed deployer, address pairToken, uint256 phantomQuote, bool personality, uint256 creatorAllocation);\n    event PersonalityLaunched(bytes32 indexed id, address indexed token, uint256 targetFdvUsd, uint256 ethUsdAnswer);\n    event PairEconomicsUpdated(address indexed pairToken, uint256 phantomQuote, bool enabled);\n    event LaunchForwarderSet(address forwarder);\n    event TermsUpdated();\n    event FeeSweepOperatorUpdated(address operator);\n    event CreatorFeeRecipientUpdated(address indexed token, address indexed oldRecipient, address indexed newRecipient);\n    event CreatorFeeRecipientChangeProposed(address indexed token, address recipient, uint256 effectiveAt, uint256 expiresAt);\n    event CreatorFeeRecipientChangeCancelled(address indexed token);\n\n    constructor(address initialOwner, IEthUsdFeed feed) Ownable(initialOwner) {\n        if (address(feed).code.length == 0) revert ZeroAddress();\n        ethUsdFeed = feed;\n        uint8 decimals_ = feed.decimals();\n        if (decimals_ > 18) revert InvalidOraclePrice();\n        oracleDecimals = decimals_;\n        feeSweepOperator = initialOwner;\n        _policy = FeePolicySnapshot(initialOwner, 3_000, 5_000, 100, 300);\n        feeEscrow = new BrishopFeeEscrow();\n        buybackVault = new BrishopBuybackVault(address(this), IBrishopFeePolicy(address(this)), IBrishopFeeEscrow(address(feeEscrow)));\n        buybackVault.setFactory(address(this));\n        launchDeployer = new BrishopLaunchDeployer(address(this), IBrishopFeeEscrow(address(feeEscrow)), buybackVault);\n        pairEconomics[address(0)] = PairEconomics(BASE_PHANTOM_ETH, true);\n    }\n\n    function currentFeePolicy() external view returns (FeePolicySnapshot memory) { return _policy; }\n    function getLaunchFeePolicy(address token) external view returns (FeePolicySnapshot memory) { _requireLaunch(token); return _launchPolicies[token]; }\n    function getLaunchedToken(address token) external view returns (LaunchedToken memory) { return _launches[token]; }\n    function launchCount() external view returns (uint256) { return _tokens.length; }\n    function launchedTokenAt(uint256 index) external view returns (address) { return _tokens[index]; }\n    function canLaunch(address) external pure returns (bool) { return true; }\n\n    function previewLaunchEconomics(address pairToken) public view returns (bytes32) {\n        PairEconomics memory pair = pairEconomics[pairToken];\n        if (!pair.enabled) revert PairTokenNotApproved();\n        return _economicsHash(pairToken, pair.phantomQuote, false);\n    }\n\n    function previewPersonalityEconomics(uint256 targetFdvUsd) public view returns (bytes32 economics, uint256 phantomQuote, uint256 price) {\n        if (targetFdvUsd < 18_000 || targetFdvUsd > 25_000) revert InvalidPersonalityValuation();\n        (, int256 answer,, uint256 updatedAt,) = ethUsdFeed.latestRoundData();\n        if (answer <= 0 || updatedAt == 0 || updatedAt > block.timestamp || block.timestamp - updatedAt > ORACLE_MAX_AGE) revert InvalidOraclePrice();\n        price = uint256(answer);\n        // 75% inventory: FDV = phantomQuote / 0.75 * ETH/USD.\n        phantomQuote = Math.mulDiv(targetFdvUsd * 1 ether, 3 * 10 ** oracleDecimals, 4 * price);\n        if (phantomQuote == 0 || phantomQuote > type(uint128).max) revert InvalidPersonalityValuation();\n        economics = _economicsHash(address(0), phantomQuote, true);\n    }\n\n    function _economicsHash(address pairToken, uint256 phantomQuote, bool personality) private view returns (bytes32) {\n        return keccak256(abi.encode(block.chainid, address(this), SUPPLY, pairToken, phantomQuote, personality, launchFee, maxCreatorTaxBps, snipeTaxStartBps, snipeTaxSeconds, _policy));\n    }\n\n    function launchToken(TokenParams calldata params, address pairToken) external payable nonReentrant returns (address token, address curve) {\n        return _launchCommunity(params, pairToken, msg.sender);\n    }\n    function launchTokenFor(TokenParams calldata params, address pairToken, address creator) external payable nonReentrant returns (address token, address curve) {\n        if (msg.sender != launchForwarder || creator == address(0)) revert NotLaunchForwarder();\n        return _launchCommunity(params, pairToken, creator);\n    }\n    function _launchCommunity(TokenParams calldata params, address pairToken, address creator) private returns (address token, address curve) {\n        if (params.expectedEconomics != previewLaunchEconomics(pairToken)) revert LaunchEconomicsMismatch();\n        return _launch(params, pairToken, creator, pairEconomics[pairToken].phantomQuote, false);\n    }\n\n    /// @notice Only the administrator may mint a personality. The 25% allocation\n    /// goes directly to that administrator, is transferable, and receives no ETH.\n    function launchPersonality(TokenParams calldata params, bytes32 id, uint256 targetFdvUsd) external payable onlyOwner nonReentrant returns (address token, address curve) {\n        if (id == bytes32(0) || personalities[id] != address(0)) revert DuplicatePersonality();\n        (bytes32 economics, uint256 phantomQuote, uint256 price) = previewPersonalityEconomics(targetFdvUsd);\n        if (params.expectedEconomics != economics) revert LaunchEconomicsMismatch();\n        (token, curve) = _launch(params, address(0), msg.sender, phantomQuote, true);\n        personalities[id] = token;\n        uint256 quotePhantom = Math.mulDiv(BASE_PHANTOM_ETH, SUPPLY * 3 / 4, phantomQuote);\n        pairEconomics[token] = PairEconomics(quotePhantom, true);\n        emit PairEconomicsUpdated(token, quotePhantom, true);\n        emit PersonalityLaunched(id, token, targetFdvUsd, price);\n    }\n\n    function _launch(TokenParams calldata params, address pairToken, address creator, uint256 phantomQuote, bool personality) private returns (address token, address curve) {\n        if (msg.value != launchFee) revert LaunchFeeNotPaid();\n        if (params.creatorTaxBps > maxCreatorTaxBps || uint256(params.creatorTaxBps) + _policy.hookFeeBps > 2_000) revert CreatorTaxTooHigh();\n        if (usedSalt[creator][params.salt]) revert SaltAlreadyUsed();\n        if (params.snipeTaxExemptions.length > 32) revert InvalidTerms();\n        usedSalt[creator][params.salt] = true;\n        address recipient = params.creatorFeeRecipient == address(0) ? creator : params.creatorFeeRecipient;\n        uint256 allocation = personality ? SUPPLY / 4 : 0;\n        BrishopBondingCurve.Terms memory terms = BrishopBondingCurve.Terms(pairToken, recipient, phantomQuote, _policy.hookFeeBps, params.creatorTaxBps, params.buybackEnabled);\n        (token, curve) = launchDeployer.deployLaunch(params, terms, _policy, creator, SUPPLY, allocation);\n        _launches[token] = LaunchedToken(token, curve, creator, recipient, pairToken, params.creatorTaxBps, params.buybackEnabled, personality, true);\n        _launchPolicies[token] = _policy;\n        _tokens.push(token);\n        address[] memory exemptions = new address[](params.snipeTaxExemptions.length + 2);\n        exemptions[0] = creator;\n        exemptions[1] = recipient;\n        for (uint256 i; i < params.snipeTaxExemptions.length; ++i) exemptions[i + 2] = params.snipeTaxExemptions[i];\n        BrishopBondingCurve(curve).initialize(token, exemptions);\n        if (launchFee != 0) feeEscrow.credit{value: launchFee}(_policy.protocolFeeRecipient);\n        emit TokenLaunched(token, curve, creator, pairToken, phantomQuote, personality, allocation);\n    }\n\n    function setLaunchForwarder(address forwarder) external onlyOwner {\n        if (launchForwarder != address(0)) revert AlreadySet();\n        if (forwarder.code.length == 0) revert ZeroAddress();\n        launchForwarder = forwarder;\n        emit LaunchForwarderSet(forwarder);\n    }\n    function setFeeSweepOperator(address operator) external onlyOwner {\n        if (operator == address(0)) revert ZeroAddress();\n        feeSweepOperator = operator;\n        emit FeeSweepOperatorUpdated(operator);\n    }\n    /// @notice Updates terms for future launches only; existing curves snapshot them.\n    function setLaunchTerms(uint256 newLaunchFee, uint256 creatorTaxMax, uint256 snipeStart, uint256 snipeWindow, FeePolicySnapshot calldata policy) external onlyOwner {\n        if (creatorTaxMax > 1_000 || snipeStart > 9_900 || snipeWindow == 0 || snipeWindow > 1 days || policy.protocolFeeRecipient == address(0) || policy.protocolFeeShareBps > 10_000 || policy.buybackBurnBps > 10_000 || policy.hookFeeBps > 1_000 || policy.maxInternalPriceImpactBps == 0 || policy.maxInternalPriceImpactBps >= 10_000) revert InvalidTerms();\n        launchFee = newLaunchFee; maxCreatorTaxBps = creatorTaxMax; snipeTaxStartBps = snipeStart; snipeTaxSeconds = snipeWindow; _policy = policy;\n        emit TermsUpdated();\n    }\n    function setPairEconomics(address pairToken, uint256 phantomQuote, bool enabled) external onlyOwner {\n        if (pairToken != address(0) && !_launches[pairToken].personality) revert PairTokenNotApproved();\n        if (phantomQuote == 0 || phantomQuote > type(uint128).max) revert InvalidTerms();\n        pairEconomics[pairToken] = PairEconomics(phantomQuote, enabled);\n        emit PairEconomicsUpdated(pairToken, phantomQuote, enabled);\n    }\n    function setBuybackEnabled(address token, bool enabled) external {\n        LaunchedToken storage launch = _requireLaunch(token);\n        if (msg.sender != launch.creatorFeeRecipient && (msg.sender != owner() || enabled)) revert NotCreatorFeeRecipient();\n        launch.buybackEnabled = enabled;\n        BrishopBondingCurve(launch.curve).setBuybackEnabled(enabled);\n    }\n    function transferCreatorFeeRecipient(address token, address recipient) external {\n        LaunchedToken storage launch = _requireLaunch(token);\n        if (msg.sender != launch.creatorFeeRecipient) revert NotCreatorFeeRecipient();\n        _updateRecipient(token, recipient);\n    }\n    function proposeCreatorFeeRecipient(address token, address recipient) external onlyOwner {\n        _requireLaunch(token);\n        if (recipient == address(0)) revert ZeroAddress();\n        uint256 effective = block.timestamp + CREATOR_RECOVERY_DELAY;\n        pendingCreatorFeeRecipient[token] = PendingRecipient(recipient, effective, effective + CREATOR_RECOVERY_WINDOW);\n        emit CreatorFeeRecipientChangeProposed(token, recipient, effective, effective + CREATOR_RECOVERY_WINDOW);\n    }\n    function cancelCreatorFeeRecipientChange(address token) external onlyOwner {\n        delete pendingCreatorFeeRecipient[token];\n        emit CreatorFeeRecipientChangeCancelled(token);\n    }\n    function executeCreatorFeeRecipientChange(address token) external onlyOwner {\n        PendingRecipient memory pending = pendingCreatorFeeRecipient[token];\n        if (pending.recipient == address(0) || block.timestamp < pending.effectiveAt || block.timestamp > pending.expiresAt) revert RecoveryNotExecutable();\n        delete pendingCreatorFeeRecipient[token];\n        _updateRecipient(token, pending.recipient);\n    }\n    function _updateRecipient(address token, address recipient) private {\n        if (recipient == address(0)) revert ZeroAddress();\n        LaunchedToken storage launch = _requireLaunch(token);\n        address previous = launch.creatorFeeRecipient;\n        launch.creatorFeeRecipient = recipient;\n        BrishopBondingCurve(launch.curve).setCreatorFeeRecipient(recipient);\n        buybackVault.updateCreatorRecipient(token, recipient);\n        emit CreatorFeeRecipientUpdated(token, previous, recipient);\n    }\n    function _requireLaunch(address token) private view returns (LaunchedToken storage launch) {\n        launch = _launches[token];\n        if (!launch.exists) revert UnknownToken();\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/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/BrishopFeeEscrow.sol":{"id":20},"src/BrishopBondingCurve.sol":{"id":18},"src/BrishopBuybackVault.sol":{"id":19},"src/BrishopLaunchAndBuy.sol":{"id":21},"src/interfaces/IBrishop.sol":{"id":25},"src/BrishopLaunchFactory.sol":{"id":23},"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/BrishopLaunchAndBuy.sol":{"BrishopLaunchAndBuy":{"abi":[{"type":"constructor","inputs":[{"name":"factory_","type":"address","internalType":"contract BrishopLaunchFactory"}],"stateMutability":"nonpayable"},{"name":"DeadlineExpired","type":"error","inputs":[]},{"name":"InvalidMinimum","type":"error","inputs":[]},{"name":"InvalidValue","type":"error","inputs":[]},{"name":"ReentrancyGuardReentrantCall","type":"error","inputs":[]},{"name":"SafeERC20FailedOperation","type":"error","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"name":"factory","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract BrishopLaunchFactory"}],"stateMutability":"view"},{"name":"launchAndBuy","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":"pairToken","type":"address","internalType":"address"},{"name":"quoteAmount","type":"uint256","internalType":"uint256"},{"name":"minimumTokens","type":"uint256","internalType":"uint256"},{"name":"deadline","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"token","type":"address","internalType":"address"},{"name":"curve","type":"address","internalType":"address"},{"name":"tokensBought","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"}],"metadata":"{\"compiler\":{\"version\":\"0.8.35+commit.47b9dedd\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract BrishopLaunchFactory\",\"name\":\"factory_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DeadlineExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMinimum\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"contract BrishopLaunchFactory\",\"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\"},{\"internalType\":\"address\",\"name\":\"pairToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"quoteAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimumTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"launchAndBuy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"curve\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokensBought\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/BrishopLaunchAndBuy.sol\":\"BrishopLaunchAndBuy\"},\"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/BrishopFeeEscrow.sol\":{\"keccak256\":\"0x361a29a736f82d65989960e20cc37d80e5f0ec1ee909a4799df91bcef1141ca0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://27624435e94dd282fc36e0d39ceceff413cbcf314b9c38350168b4accb739988\",\"dweb:/ipfs/QmT73E2hkE4UKyy6ZqujJsNEjHLYvMnnQSyw2Xhcin4UU4\"]},\"src/BrishopLaunchAndBuy.sol\":{\"keccak256\":\"0x769f389c1c33f71da625ac1fe28cfa628b74069b91a2d179e47d52ab692cbfb3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a6ee7e7a69fe35058298f1cd26175a71106db3789057d4b83a4e5401bb281d8f\",\"dweb:/ipfs/Qmd7JGTYNNoKTaeZRm6Yi26wvcUcUmkqjN1hn4ajWu3pUa\"]},\"src/BrishopLaunchDeployer.sol\":{\"keccak256\":\"0x0f81d31836aa2a5d416979c07a14635bf3d182e2a2e955e631cae8d0afe1d544\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6c655be8bfc3007ed89e0734a9a27d26bcd3ce27483c10648d605304b2f3526\",\"dweb:/ipfs/QmUChkKtVzv31TgNXQY8FGaZqeajBj7QhPXXSHep9kj5pe\"]},\"src/BrishopLaunchFactory.sol\":{\"keccak256\":\"0x4bf1ae68473202a8688fc818b97fbd6ed91fe27574e60859a8bf68b345b91ef9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c48a43af297f76683a83c086b05cbe5cfeeae87098c78ad8b228e2d9558a9f53\",\"dweb:/ipfs/QmboPttLauLG6HzvRznmgGA7QRsodv6CoLtUDK5iej48sC\"]},\"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","errors":{"ReentrancyGuardReentrantCall()":[{"details":"Unauthorized reentrant call."}],"SafeERC20FailedOperation(address)":[{"details":"An operation with an ERC-20 token failed."}]},"methods":{},"version":1},"storageLayout":{"types":null,"storage":[]},"transientStorageLayout":{"types":null,"storage":[]},"evm":{"bytecode":{"object":"60a034609057601f610a1f38819003918201601f19168301916001600160401b03831184841017609457808492602094604052833981010312609057516001600160a01b038116810360905760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005560805260405161097690816100a98239608051818181604701526101320152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","sourceMap":"545:1579:21:-:0;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;;;;;2365:1:13;1505:66;2365:1;810:18:21;;545:1579;;;;;;;;810:18;545:1579;;;;;;;;;;;;-1:-1:-1;545:1579:21;;;;;;-1:-1:-1;545:1579:21;;;;;-1:-1:-1;545:1579:21","linkReferences":{}},"deployedBytecode":{"object":"6080806040526004361015610012575f80fd5b5f3560e01c9081637db087de1461007a575063c45a015514610032575f80fd5b34610076575f366003190112610076576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b60a0366003190112610076576004359067ffffffffffffffff821161007657816004019082360392610160600319850112610076576024356001600160a01b038116908190036100765760443590606435906084359660027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146108815760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00555f958842116108725763cf3cf57360e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa9081156104c0575f91610840575b50831592831561083a57865b82018083116106f257340361082b578615978880610822575b61081357604051631b356f3960e21b8152606060048201529a610239908c61022761021c6101fd6101de6101cb86806108ee565b61016060648801526101c4870191610920565b6101eb60248901876108ee565b86830360631901608488015290610920565b61020a60448801866108ee565b8583036063190160a487015290610920565b9260648601906108ee565b9160c460631982860301910152610920565b608482013560a2198401811215610076578c82036063190160e48e01526102f291908301906102e46004830160846102dc6102c16102a661028b61027d86806108ee565b60a08a5260a08a0191610920565b61029860248a01876108ee565b9089830360208b0152610920565b6102b360448901866108ee565b9088830360408a0152610920565b6102ce60648801856108ee565b908783036060890152610920565b9401906108ee565b916080818503910152610920565b916001600160a01b0361030760a48401610890565b166101048d015260c482013561ffff8116809103610076576101248d015260e4820135801515809103610076576101448d01526101048201356101648d01526101248201356101848d0152610144820135906022190181121561007657016024600482013591019167ffffffffffffffff8211610076578160051b36038313610076578b8103606319016101a48d01528181528b93926020909101915f5b8181106107e7575050506040939183809288602483015233604483015203925af19485156104c0575f975f9661079e575b5015610424575b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604080516001600160a01b03808a16825287166020820152908101879052606090f35b9091929394505f146104cb5750604051632251495f60e21b81526004810183905260248101919091523360448201526064810194909452602090849060849082906001600160a01b0386165af180156104c0575f9061048d575b60609350905b848080806103dd565b506020833d6020116104b8575b816104a7602093836108a4565b81010312610076576060925161047e565b3d915061049a565b6040513d5f823e3d90fd5b91906040516370a0823160e01b8152306004820152602081602481875afa9081156104c0575f9161076c575b50604051926323b872dd60e01b5f52336004523060245260445260205f60648180885af160015f511481161561074d575b836040525f6060521561073a576370a0823160e01b8352306004840152602083602481875afa9283156104c0575f93610706575b5082039182116106f25760405163095ea7b360e01b5f9081526001600160a01b0386166004819052602485905294919060209060448180865af19060015f51148216156106e3575b6040521561062e575b50604051632251495f60e21b8152600481019290925260248201523360448201526064810194909452602090849060849082905f905af180156104c0575f906105fb575b6060935090610484565b506020833d602011610626575b81610615602093836108a4565b8101031261007657606092516105f1565b3d9150610608565b60405163095ea7b360e01b5f52846004525f60245260205f60448180865af19060015f51148216156106cb575b604052156106985760405163095ea7b360e01b5f52846004528360245260205f60448180865af19060015f51148216156106aa575b6040526105ad575b635274afe760e01b5f5260045260245ffd5b9060018115166106c257823b15153d15161690610690565b503d5f823e3d90fd5b9060018115166106c257823b15153d1516169061065b565b90823b15153d151616906105a4565b634e487b7160e01b5f52601160045260245ffd5b9092506020813d602011610732575b81610722602093836108a4565b810103126100765751918761055c565b3d9150610715565b83635274afe760e01b5f5260045260245ffd5b600181151661076357843b15153d151616610528565b833d5f823e3d90fd5b90506020813d602011610796575b81610787602093836108a4565b810103126100765751876104f7565b3d915061077a565b975094506040873d6040116107df575b816107bb604093836108a4565b81010312610076576107d860206107d1896108da565b98016108da565b94896103d6565b3d91506107ae565b9193945091602080600192838060a01b0361080188610890565b1681520194019101918c9493926103a5565b631b617b5760e21b5f5260045ffd5b50861515610197565b632a9ffab760e21b5f5260045ffd5b5f61017e565b90506020813d60201161086a575b8161085b602093836108a4565b8101031261007657518a610172565b3d915061084e565b631ab7da6b60e01b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b35906001600160a01b038216820361007657565b90601f8019910116810190811067ffffffffffffffff8211176108c657604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361007657565b9035601e198236030181121561007657016020813591019167ffffffffffffffff821161007657813603831361007657565b908060209392818452848401375f828201840152601f01601f191601019056fea2646970667358221220a500f93ff02b2d21575e9474353598d57f068beba4225a8e62b6c4cce7d761a464736f6c63430008230033","sourceMap":"545:1579:21:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;631:45;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;2407:1:13;1505:66;545:1579:21;4560:63:13;3644:93;;2407:1;1505:66;2407:1;545:1579:21;1073:15;;;:26;1069:56;;-1:-1:-1;;;1149:19:21;;:7;-1:-1:-1;;;;;545:1579:21;;;;;;;1149:19;;;;;;;545:1579;1149:19;;;545:1579;-1:-1:-1;1202:23:21;;;:41;;;;;;545:1579;;;;;;;1182:9;:62;1178:89;;1281:16;;;;;:38;;1202:41;1277:67;;545:1579;;-1:-1:-1;;;1371:65:21;;545:1579;;1371:65;;545:1579;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;-1:-1:-1;;545:1579:21;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;-1:-1:-1;;545:1579:21;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;-1:-1:-1;;;;;545:1579:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;545:1579:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1425:10;545:1579;;;;1371:65;;;;;;;;;545:1579;;;1371:65;;;545:1579;1450:16;;1446:670;;545:1579;;1505:66:13;2407:1;545:1579:21;;;-1:-1:-1;;;;;545:1579:21;;;;;;;;;;;;;;;;;;;;1446:670;1482:624;;;;;;;;;;-1:-1:-1;545:1579:21;;-1:-1:-1;;;1526:100:21;;545:1579;1526:100;;545:1579;;;;;;;;;;1425:10;545:1579;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;545:1579:21;;1526:100;;;;;;545:1579;1526:100;;;1482:624;545:1579;1511:115;;1482:624;;1446:670;;;;;;1526:100;;545:1579;1526:100;;545:1579;1526:100;;;;;;545:1579;1526:100;;;:::i;:::-;;;545:1579;;;;;;;1526:100;;;;;-1:-1:-1;1526:100:21;;;545:1579;;;;;;;;;1482:624;545:1579;;;;;;;1687:42;;1723:4;545:1579;1687:42;;545:1579;;1687:42;545:1579;1687:42;;;;;;;;;545:1579;1687:42;;;1482:624;1767:47:10;545:1579:21;10404:1148:10;10365:28;;;;545:1579:21;10404:1148:10;1425:10:21;545:1579;10404:1148:10;1723:4:21;545:1579;10404:1148:10;545:1579:21;10404:1148:10;545:1579:21;;;10404:1148:10;;;;;545:1579:21;;10404:1148:10;;;;;;;1482:624:21;10404:1148:10;545:1579:21;10404:1148:10;545:1579:21;;10404:1148:10;1766:48;1762:126;;-1:-1:-1;;;1858:42:21;;1723:4;545:1579;1858:42;;545:1579;;1858:42;545:1579;1858:42;;;;;;;;;545:1579;1858:42;;;1482:624;545:1579;;;;;;;;;12233:1072:10;-1:-1:-1;;;545:1579:21;12233:1072:10;;;-1:-1:-1;;;;;12233:1072:10;;545:1579:21;12233:1072:10;;;545:1579:21;12233:1072:10;;;;12199:23;12233:1072;545:1579:21;;;;;12199:23:10;12233:1072;;;545:1579:21;;12233:1072:10;;;;;;;1482:624:21;545:1579;12233:1072:10;5189:43;5185:274;;1482:624:21;-1:-1:-1;545:1579:21;;-1:-1:-1;;;2014:77:21;;545:1579;2014:77;;545:1579;;;;;;;;1425:10;545:1579;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2014:77:21;;;;;;545:1579;2014:77;;;1482:624;545:1579;1999:92;;1482:624;;;2014:77;;545:1579;2014:77;;545:1579;2014:77;;;;;;545:1579;2014:77;;;:::i;:::-;;;545:1579;;;;;;;2014:77;;;;;-1:-1:-1;2014:77:21;;5185:274:10;545:1579:21;12233:1072:10;12199:23;;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;545:1579:21;;12233:1072:10;545:1579:21;;;12233:1072:10;;;;;;545:1579:21;;12233:1072:10;;;;;;;5185:274;545:1579:21;12233:1072:10;5252:38;5248:91;;545:1579:21;12233:1072:10;12199:23;;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;;545:1579:21;12233:1072:10;545:1579:21;;;12233:1072:10;;;;;;545:1579:21;;12233:1072:10;;;;;;;5185:274;545:1579:21;12233:1072:10;5185:274;5353:95;;1837:40;;;545:1579:21;5408:40:10;545:1579:21;;;;5408:40:10;12233:1072;;545:1579:21;12233:1072:10;;;;;;;;;;;;;;;;;;;545:1579:21;12233:1072:10;;;;;;;545:1579:21;12233:1072:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;545:1579:21;;;;;;;;;;;;1858:42;;;;545:1579;1858:42;;545:1579;1858:42;;;;;;545:1579;1858:42;;;:::i;:::-;;;545:1579;;;;;1858:42;;;;;;;-1:-1:-1;1858:42:21;;1762:126:10;1837:40;;;;545:1579:21;1837:40:10;545:1579:21;;;;1837:40:10;10404:1148;545:1579:21;10404:1148:10;;;;;;;;;;;;;;;;;;545:1579:21;10404:1148:10;;;;;1687:42:21;;;545:1579;1687:42;;545:1579;1687:42;;;;;;545:1579;1687:42;;;:::i;:::-;;;545:1579;;;;;1687:42;;;;;;-1:-1:-1;1687:42:21;;1371:65;;;;;545:1579;1371:65;;545:1579;1371:65;;;;;;545:1579;1371:65;;;:::i;:::-;;;545:1579;;;;;;;;;:::i;:::-;;;;:::i;:::-;1371:65;;;;;;;-1:-1:-1;1371:65:21;;545:1579;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1277:67;1328:16;;;545:1579;1328:16;545:1579;;1328:16;1281:38;1301:18;;;;1281:38;;1178:89;1253:14;;;545:1579;1253:14;545:1579;;1253:14;1202:41;545:1579;1202:41;;1149:19;;;545:1579;1149:19;;545:1579;1149:19;;;;;;545:1579;1149:19;;;:::i;:::-;;;545:1579;;;;;1149:19;;;;;;-1:-1:-1;1149:19:21;;1069:56;1108:17;;;545:1579;1108:17;545:1579;;1108:17;3644:93:13;3696:30;;;545:1579:21;3696:30:13;545:1579:21;;3696:30:13;545:1579:21;;;-1:-1:-1;;;;;545:1579:21;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;545:1579:21;;;;;-1:-1:-1;545:1579:21;;;;-1:-1:-1;;;;;545:1579:21;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;545:1579:21;;;;;;;;-1:-1:-1;;545:1579:21;;;;:::o","linkReferences":{},"immutableReferences":{"8422":[{"start":71,"length":32},{"start":306,"length":32}]}}}}}}},"signatures":{"function":[{"signature":"factory()","signatureHash4":"0xc45a0155","signatureHash32":"0xc45a01550ceb4bc5c6b2e6f722b5033a03078f9bd6673457375ba94c26ac1cf0"},{"signature":"launchAndBuy((string,string,string,string,(string,string,string,string,string),address,uint16,bool,bytes32,bytes32,address[]),address,uint256,uint256,uint256)","signatureHash4":"0x7db087de","signatureHash32":"0x7db087dec3f6355a760b09f52fe78de614767e8c2951a9681b3ce4bdb4c4afb0"}],"event":[],"error":[{"signature":"DeadlineExpired()","signatureHash4":"0x1ab7da6b","signatureHash32":"0x1ab7da6b04cf80fcc6534c1f63ce7b24fd7488ab40444b4e5271ccc1c7f64567"},{"signature":"InvalidMinimum()","signatureHash4":"0x6d85ed5c","signatureHash32":"0x6d85ed5c6efd88e4a5761b2edc60322a1f0dc49d6a33ecd7af550b992f473edb"},{"signature":"InvalidValue()","signatureHash4":"0xaa7feadc","signatureHash32":"0xaa7feadc1a228aee3d4475b95bb4402ebafd3841876f41c4469039f5ee2998d5"},{"signature":"ReentrancyGuardReentrantCall()","signatureHash4":"0x3ee5aeb5","signatureHash32":"0x3ee5aeb571de7fc460830b4d0017439a1ca56fb0bc39062227ade4fe4a24c1ca"},{"signature":"SafeERC20FailedOperation(address)","signatureHash4":"0x5274afe7","signatureHash32":"0x5274afe73c98b4749fc91ffae6b7b574e7842cb2144a159e9377a5f20b32edf9"}]},"proxyResolution":{"isProxy":false,"proxyType":null,"implementations":[]},"match":"exact_match","chainId":"4663","address":"0x83bcc70207479937E6026BfF1bCd87Ee3Fb19375"}