{"matchId":"6356664","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2025-05-14T04:59:26Z","creationBytecode":{"onchainBytecode":"0x6103606040523480156200001257600080fd5b5060405162005f4938038062005f49833981016040819052620000359162000518565b3060e052805160805260208101516001600160a01b0390811661018052604082015181166101a05260a08083015182169081905260c080840151909216918290528291829110620000a2576040516317f71f0760e11b815261c76160048201526024015b60405180910390fd5b60a051620000b09062000313565b610120526101005260c051620000c69062000313565b61016052610140526060810151516001600160a01b031615620000fc576060810151516001600160a01b03166101c05262000102565b306101c0525b6060810151602001516001600160a01b03161562000136576060810151602001516001600160a01b03166101e0526200013c565b306101e0525b6060810151604001516001600160a01b03161562000170576060810151604001516001600160a01b03166102005262000176565b30610200525b60608082015101516001600160a01b031615620001a85760608082015101516001600160a01b031661022052620001ae565b30610220525b6060810151608001516001600160a01b031615620001e2576060810151608001516001600160a01b031661024052620001e8565b30610240525b60808101516001600160a01b03166102605260e0810151610280526101008101516102a0526101208101516102c0526101408101516102e05261016081015161030052610180810151610320526101a081015161ffff101562000263576040516317f71f0760e11b815261c762600482015260240162000099565b6101a0015161034052506060810151516001600160a01b031615806200029857506060810151602001516001600160a01b0316155b80620002b357506060810151604001516001600160a01b0316155b80620002cd575060608082015101516001600160a01b0316155b80620002e857506060810151608001516001600160a01b0316155b156200030c576040516317f71f0760e11b815261c772600482015260240162000099565b5062000771565b6000808062000322846200037b565b9050600c8111156200035457600192506200033f600c8262000624565b6200034c90600a62000737565b915062000375565b6200036181600c62000624565b6200036e90600a62000737565b9250600191505b50915091565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146200041057816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040791906200074c565b60ff1662000413565b60125b92915050565b6040516101c081016001600160401b03811182821017156200044b57634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b03811681146200046957600080fd5b919050565b600060a082840312156200048157600080fd5b60405160a081016001600160401b0381118282101715620004b257634e487b7160e01b600052604160045260246000fd5b604052905080620004c38362000451565b8152620004d36020840162000451565b6020820152620004e66040840162000451565b6040820152620004f96060840162000451565b60608201526200050c6080840162000451565b60808201525092915050565b600061024082840312156200052c57600080fd5b6200053662000419565b82518152620005486020840162000451565b60208201526200055b6040840162000451565b60408201526200056f84606085016200046e565b60608201526101006200058481850162000451565b60808301526101206200059981860162000451565b60a0840152610140620005ae81870162000451565b60c08501526101608087015160e086015261018080880151858701526101a0945084880151848701526101c0880151838701526101e088015182870152610200880151818701525050505061022084015181830152508091505092915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156200041357620004136200060e565b600181815b808511156200067b5781600019048211156200065f576200065f6200060e565b808516156200066d57918102915b93841c93908002906200063f565b509250929050565b600082620006945750600162000413565b81620006a35750600062000413565b8160018114620006bc5760028114620006c757620006e7565b600191505062000413565b60ff841115620006db57620006db6200060e565b50506001821b62000413565b5060208310610133831016604e8410600b84101617156200070c575081810a62000413565b6200071883836200063a565b80600019048211156200072f576200072f6200060e565b029392505050565b600062000745838362000683565b9392505050565b6000602082840312156200075f57600080fd5b815160ff811681146200074557600080fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161551062000a3960003960008181610ff0015281816112690152818161131a01528181613dba01528181613e230152613ed0015260008181610fc9015281816129c5015261311f015260008181610fa20152818161298e015261303d015260008181610f7b0152611936015260008181610f540152612ae4015260008181610f2d0152611906015260008181610f070152612ab4015260008181610edf01528181612cdc0152613823015260008181610856015281816108ba0152610eb60152600081816107970152610e8f01526000818161093d0152610e640152600081816105f50152610e39015260008181610e12015281816145330152818161463301526146c4015260008181610429015281816104e30152610d8f015260008181610a9401528181610c5e01528181610d63015281816127c2015281816128650152818161306701528181613149015281816132b50152613a2401526000818161076901528181611c5f0152818161249a015281816124ee0152818161254a015281816125a1015261335f01526000818161074301528181611c8001528181612479015281816124cd015281816125260152818161257d015261338001526000818161071d01528181611ba2015281816123ef01528181612446015281816125f50152818161264901526133b60152600081816106fa01528181611bc3015281816123cb01528181612422015281816125d40152818161262801526133d701526000505060008181610de301528181611b5601528181611c3b01526138bc015260008181610dbb01528181611b7e01528181611c1301526138940152600081816103d90152610d2b01526155106000f3fe6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201527f0000000000000000000000000000000000000000000000000000000000000000606082015290565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f0000000000000000000000000000000000000000000000000000000000000000866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166020808401919091527f000000000000000000000000000000000000000000000000000000000000000082166040808501919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08501527f0000000000000000000000000000000000000000000000000000000000000000831660c0850152606080850180517f00000000000000000000000000000000000000000000000000000000000000008616905280517f0000000000000000000000000000000000000000000000000000000000000000861694019390935282517f0000000000000000000000000000000000000000000000000000000000000000851692019190915281517f00000000000000000000000000000000000000000000000000000000000000008416910152517f000000000000000000000000000000000000000000000000000000000000000082166080918201527f0000000000000000000000000000000000000000000000000000000000000000909116908201527f000000000000000000000000000000000000000000000000000000000000000060e08201527f00000000000000000000000000000000000000000000000000000000000000006101008201527f00000000000000000000000000000000000000000000000000000000000000006101208201527f00000000000000000000000000000000000000000000000000000000000000006101408201527f00000000000000000000000000000000000000000000000000000000000000006101608201527f00000000000000000000000000000000000000000000000000000000000000006101808201527f00000000000000000000000000000000000000000000000000000000000000006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b9050600061195d7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000006124147f00000000000000000000000000000000000000000000000000000000000000008861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000061246b7f00000000000000000000000000000000000000000000000000000000000000008661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000061256f7f00000000000000000000000000000000000000000000000000000000000000008861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000006125c67f00000000000000000000000000000000000000000000000000000000000000008661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129e9565b6129e96103ff60ee8b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b90506000612b0b7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000000000000000000000000000000000000000000000826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526130ed907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015261318d907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000000000000000000000000000000000000000000000856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660448301527f00000000000000000000000000000000000000000000000000000000000000008116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000000006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000000000000000000000000000000000000000000000907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033000000000000000000000000000000000000000000000000000000000000000100000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49700000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c190850000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd00000000000000000000000020c86b8fc6ae133fe78560c1dedac286a1d83395000000000000000000000000417082c6099338c1a04081ff290e8c64cb08e8e9000000000000000000000000f3c087d5f40f97ba09b258732806aaa10304f168000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b80000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6131848091c3c7f98e5aef7805aa612f81b6052f1c3e3e495ef46d6dee38812ff16c9d6e6c0fe5bb46fd8db51fd239511adb0187726196eb00a2e011dceca114236696efd8534ce144b358082d303ba190cad0c8d37e9f4802b2a5198019379bd943cec1dfc617bf9515058376abfab0217f98cce018735f02efd4abd3453ad8f3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716fa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d70000000000000000000000000000000000000000000000000000000000004000","recompiledBytecode":"0x6103606040523480156200001257600080fd5b5060405162005f4938038062005f49833981016040819052620000359162000518565b3060e052805160805260208101516001600160a01b0390811661018052604082015181166101a05260a08083015182169081905260c080840151909216918290528291829110620000a2576040516317f71f0760e11b815261c76160048201526024015b60405180910390fd5b60a051620000b09062000313565b610120526101005260c051620000c69062000313565b61016052610140526060810151516001600160a01b031615620000fc576060810151516001600160a01b03166101c05262000102565b306101c0525b6060810151602001516001600160a01b03161562000136576060810151602001516001600160a01b03166101e0526200013c565b306101e0525b6060810151604001516001600160a01b03161562000170576060810151604001516001600160a01b03166102005262000176565b30610200525b60608082015101516001600160a01b031615620001a85760608082015101516001600160a01b031661022052620001ae565b30610220525b6060810151608001516001600160a01b031615620001e2576060810151608001516001600160a01b031661024052620001e8565b30610240525b60808101516001600160a01b03166102605260e0810151610280526101008101516102a0526101208101516102c0526101408101516102e05261016081015161030052610180810151610320526101a081015161ffff101562000263576040516317f71f0760e11b815261c762600482015260240162000099565b6101a0015161034052506060810151516001600160a01b031615806200029857506060810151602001516001600160a01b0316155b80620002b357506060810151604001516001600160a01b0316155b80620002cd575060608082015101516001600160a01b0316155b80620002e857506060810151608001516001600160a01b0316155b156200030c576040516317f71f0760e11b815261c772600482015260240162000099565b5062000771565b6000808062000322846200037b565b9050600c8111156200035457600192506200033f600c8262000624565b6200034c90600a62000737565b915062000375565b6200036181600c62000624565b6200036e90600a62000737565b9250600191505b50915091565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146200041057816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040791906200074c565b60ff1662000413565b60125b92915050565b6040516101c081016001600160401b03811182821017156200044b57634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b03811681146200046957600080fd5b919050565b600060a082840312156200048157600080fd5b60405160a081016001600160401b0381118282101715620004b257634e487b7160e01b600052604160045260246000fd5b604052905080620004c38362000451565b8152620004d36020840162000451565b6020820152620004e66040840162000451565b6040820152620004f96060840162000451565b60608201526200050c6080840162000451565b60808201525092915050565b600061024082840312156200052c57600080fd5b6200053662000419565b82518152620005486020840162000451565b60208201526200055b6040840162000451565b60408201526200056f84606085016200046e565b60608201526101006200058481850162000451565b60808301526101206200059981860162000451565b60a0840152610140620005ae81870162000451565b60c08501526101608087015160e086015261018080880151858701526101a0945084880151848701526101c0880151838701526101e088015182870152610200880151818701525050505061022084015181830152508091505092915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156200041357620004136200060e565b600181815b808511156200067b5781600019048211156200065f576200065f6200060e565b808516156200066d57918102915b93841c93908002906200063f565b509250929050565b600082620006945750600162000413565b81620006a35750600062000413565b8160018114620006bc5760028114620006c757620006e7565b600191505062000413565b60ff841115620006db57620006db6200060e565b50506001821b62000413565b5060208310610133831016604e8410600b84101617156200070c575081810a62000413565b6200071883836200063a565b80600019048211156200072f576200072f6200060e565b029392505050565b600062000745838362000683565b9392505050565b6000602082840312156200075f57600080fd5b815160ff811681146200074557600080fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161551062000a3960003960008181610ff0015281816112690152818161131a01528181613dba01528181613e230152613ed0015260008181610fc9015281816129c5015261311f015260008181610fa20152818161298e015261303d015260008181610f7b0152611936015260008181610f540152612ae4015260008181610f2d0152611906015260008181610f070152612ab4015260008181610edf01528181612cdc0152613823015260008181610856015281816108ba0152610eb60152600081816107970152610e8f01526000818161093d0152610e640152600081816105f50152610e39015260008181610e12015281816145330152818161463301526146c4015260008181610429015281816104e30152610d8f015260008181610a9401528181610c5e01528181610d63015281816127c2015281816128650152818161306701528181613149015281816132b50152613a2401526000818161076901528181611c5f0152818161249a015281816124ee0152818161254a015281816125a1015261335f01526000818161074301528181611c8001528181612479015281816124cd015281816125260152818161257d015261338001526000818161071d01528181611ba2015281816123ef01528181612446015281816125f50152818161264901526133b60152600081816106fa01528181611bc3015281816123cb01528181612422015281816125d40152818161262801526133d701526000505060008181610de301528181611b5601528181611c3b01526138bc015260008181610dbb01528181611b7e01528181611c1301526138940152600081816103d90152610d2b01526155106000f3fe6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201527f0000000000000000000000000000000000000000000000000000000000000000606082015290565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f0000000000000000000000000000000000000000000000000000000000000000866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166020808401919091527f000000000000000000000000000000000000000000000000000000000000000082166040808501919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08501527f0000000000000000000000000000000000000000000000000000000000000000831660c0850152606080850180517f00000000000000000000000000000000000000000000000000000000000000008616905280517f0000000000000000000000000000000000000000000000000000000000000000861694019390935282517f0000000000000000000000000000000000000000000000000000000000000000851692019190915281517f00000000000000000000000000000000000000000000000000000000000000008416910152517f000000000000000000000000000000000000000000000000000000000000000082166080918201527f0000000000000000000000000000000000000000000000000000000000000000909116908201527f000000000000000000000000000000000000000000000000000000000000000060e08201527f00000000000000000000000000000000000000000000000000000000000000006101008201527f00000000000000000000000000000000000000000000000000000000000000006101208201527f00000000000000000000000000000000000000000000000000000000000000006101408201527f00000000000000000000000000000000000000000000000000000000000000006101608201527f00000000000000000000000000000000000000000000000000000000000000006101808201527f00000000000000000000000000000000000000000000000000000000000000006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b9050600061195d7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000006124147f00000000000000000000000000000000000000000000000000000000000000008861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000061246b7f00000000000000000000000000000000000000000000000000000000000000008661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000061256f7f00000000000000000000000000000000000000000000000000000000000000008861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000006125c67f00000000000000000000000000000000000000000000000000000000000000008661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129e9565b6129e96103ff60ee8b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b90506000612b0b7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000000000000000000000000000000000000000000000826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526130ed907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015261318d907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000000000000000000000000000000000000000000000856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660448301527f00000000000000000000000000000000000000000000000000000000000000008116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000000006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000000000000000000000000000000000000000000000907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","sourceMap":"797:42753:18:-:0;;;878:610;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3051:4:21;3027:29;;3076:16;;3067:25;;3130:20;;;;-1:-1:-1;;;;;3102:49:21;;;;;3192:18;;;;3161:50;;;;3232:17;;;;;3222:27;;;;;;3269:17;;;;;3259:27;;;;;;;939:14:18;;;;3301:18:21;3297:95;;3328:64;;-1:-1:-1;;;3328:64:21;;3722:5:13;3328:64:21;;;2930:25:25;2903:18;;3328:64:21;;;;;;;;3297:95;3495:7;;3466:37;;:28;:37::i;:::-;3403:100;;;;3605:7;;3576:37;;:28;:37::i;:::-;3513:100;;;;3628:26;;;;:32;-1:-1:-1;;;;;3628:46:21;;3624:199;;3713:26;;;;:32;-1:-1:-1;;;;;3690:55:21;;;3624:199;;;3807:4;3776:36;;3624:199;3836:26;;;;:32;;;-1:-1:-1;;;;;3836:46:21;;3832:199;;3921:26;;;;:32;;;-1:-1:-1;;;;;3898:55:21;;;3832:199;;;4015:4;3984:36;;3832:199;4044:26;;;;:40;;;-1:-1:-1;;;;;4044:54:21;;4040:233;;4146:26;;;;:40;;;-1:-1:-1;;;;;4114:72:21;;;4040:233;;;4257:4;4217:45;;4040:233;4286:26;;;;;:41;;-1:-1:-1;;;;;4286:55:21;;4282:237;;4390:26;;;;;:41;;-1:-1:-1;;;;;4357:74:21;;;4282:237;;;4503:4;4462:46;;4282:237;4532:26;;;;:54;;;-1:-1:-1;;;;;4532:68:21;;4528:295;;4665:26;;;;:54;;;-1:-1:-1;;;;;4616:103:21;;;4528:295;;;4807:4;4750:62;;4528:295;4853:27;;;;-1:-1:-1;;;;;4833:47:21;;;4913:27;;;;4891:49;;4972:27;;;;4950:49;;5031:27;;;;5009:49;;5090:27;;;;5068:49;;5157:34;;;;5127:64;;5231:34;;;;5201:64;;5280:24;;;;1551:6:16;-1:-1:-1;5276:97:21;;;5319:54;;-1:-1:-1;;;5319:54:21;;3791:5:13;5319:54:21;;;2930:25:25;2903:18;;5319:54:21;2784:177:25;5276:97:21;5407:24;;;5384:47;;-1:-1:-1;1032:30:18::1;::::0;::::1;::::0;:36;-1:-1:-1;;;;;1032:50:18::1;::::0;;:116:::1;;-1:-1:-1::0;1098:30:18::1;::::0;::::1;::::0;:36:::1;;::::0;-1:-1:-1;;;;;1098:50:18::1;::::0;1032:116:::1;:190;;;-1:-1:-1::0;1164:30:18::1;::::0;::::1;::::0;:44:::1;;::::0;-1:-1:-1;;;;;1164:58:18::1;::::0;1032:190:::1;:265;;;-1:-1:-1::0;1238:30:18::1;::::0;;::::1;::::0;:45:::1;::::0;-1:-1:-1;;;;;1238:59:18::1;::::0;1032:265:::1;:353;;;-1:-1:-1::0;1313:30:18::1;::::0;::::1;::::0;:58:::1;;::::0;-1:-1:-1;;;;;1313:72:18::1;::::0;1032:353:::1;1015:467;;;1417:54;::::0;-1:-1:-1;;;1417:54:18;;5162:5:13::1;1417:54:18;::::0;::::1;2930:25:25::0;2903:18;;1417:54:18::1;2784:177:25::0;1015:467:18::1;878:610:::0;797:42753;;2496:470:21;2586:18;;;2658:17;2668:6;2658:9;:17::i;:::-;2638:37;;843:2:16;2689:9:21;:37;2685:275;;;2755:1;;-1:-1:-1;2792:37:21;843:2:16;2792:9:21;:37;:::i;:::-;2785:45;;:2;:45;:::i;:::-;2770:60;;2685:275;;;2881:37;2909:9;843:2:16;2881:37:21;:::i;:::-;2874:45;;:2;:45;:::i;:::-;2861:58;;2948:1;2933:16;;2685:275;2628:338;2496:470;;;:::o;3655:175:16:-;3713:7;-1:-1:-1;;;;;3740:22:16;;594:42;3740:22;3739:84;;3805:6;-1:-1:-1;;;;;3790:31:16;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3739:84;;;;;692:2;3739:84;3732:91;3655:175;-1:-1:-1;;3655:175:16:o;14:347:25:-;81:2;75:9;123:6;111:19;;-1:-1:-1;;;;;145:34:25;;181:22;;;142:62;139:185;;;246:10;241:3;237:20;234:1;227:31;281:4;278:1;271:15;309:4;306:1;299:15;139:185;340:2;333:22;14:347;:::o;366:177::-;445:13;;-1:-1:-1;;;;;487:31:25;;477:42;;467:70;;533:1;530;523:12;467:70;366:177;;;:::o;548:873::-;621:5;669:4;657:9;652:3;648:19;644:30;641:50;;;687:1;684;677:12;641:50;720:2;714:9;762:4;750:17;;-1:-1:-1;;;;;782:34:25;;818:22;;;779:62;776:185;;;883:10;878:3;874:20;871:1;864:31;918:4;915:1;908:15;946:4;943:1;936:15;776:185;977:2;970:22;1010:6;-1:-1:-1;1010:6:25;1040:40;1070:9;1040:40;:::i;:::-;1032:6;1025:56;1114:49;1159:2;1148:9;1144:18;1114:49;:::i;:::-;1109:2;1101:6;1097:15;1090:74;1197:49;1242:2;1231:9;1227:18;1197:49;:::i;:::-;1192:2;1184:6;1180:15;1173:74;1280:49;1325:2;1314:9;1310:18;1280:49;:::i;:::-;1275:2;1267:6;1263:15;1256:74;1364:50;1409:3;1398:9;1394:19;1364:50;:::i;:::-;1358:3;1350:6;1346:16;1339:76;;548:873;;;;:::o;1426:1353::-;1527:6;1580:3;1568:9;1559:7;1555:23;1551:33;1548:53;;;1597:1;1594;1587:12;1548:53;1623:17;;:::i;:::-;1669:9;1663:16;1656:5;1649:31;1712:49;1757:2;1746:9;1742:18;1712:49;:::i;:::-;1707:2;1700:5;1696:14;1689:73;1794:49;1839:2;1828:9;1824:18;1794:49;:::i;:::-;1789:2;1782:5;1778:14;1771:73;1876;1941:7;1936:2;1925:9;1921:18;1876:73;:::i;:::-;1871:2;1864:5;1860:14;1853:97;1969:3;2006:49;2051:2;2040:9;2036:18;2006:49;:::i;:::-;1999:4;1992:5;1988:16;1981:75;2075:3;2112:49;2157:2;2146:9;2142:18;2112:49;:::i;:::-;2105:4;2098:5;2094:16;2087:75;2181:3;2218:49;2263:2;2252:9;2248:18;2218:49;:::i;:::-;2211:4;2204:5;2200:16;2193:75;2287:3;2345:2;2334:9;2330:18;2324:25;2317:4;2310:5;2306:16;2299:51;2369:3;2425:2;2414:9;2410:18;2404:25;2399:2;2392:5;2388:14;2381:49;2449:3;2439:13;;2505:2;2494:9;2490:18;2484:25;2479:2;2472:5;2468:14;2461:49;2563:6;2552:9;2548:22;2542:29;2537:2;2530:5;2526:14;2519:53;2625:3;2614:9;2610:19;2604:26;2599:2;2592:5;2588:14;2581:50;2684:3;2673:9;2669:19;2663:26;2658:2;2651:5;2647:14;2640:50;;;;;2743:3;2732:9;2728:19;2722:26;2717:2;2710:5;2706:14;2699:50;;2768:5;2758:15;;;1426:1353;;;;:::o;2966:127::-;3027:10;3022:3;3018:20;3015:1;3008:31;3058:4;3055:1;3048:15;3082:4;3079:1;3072:15;3098:128;3165:9;;;3186:11;;;3183:37;;;3200:18;;:::i;3231:422::-;3320:1;3363:5;3320:1;3377:270;3398:7;3388:8;3385:21;3377:270;;;3457:4;3453:1;3449:6;3445:17;3439:4;3436:27;3433:53;;;3466:18;;:::i;:::-;3516:7;3506:8;3502:22;3499:55;;;3536:16;;;;3499:55;3615:22;;;;3575:15;;;;3377:270;;;3381:3;3231:422;;;;;:::o;3658:806::-;3707:5;3737:8;3727:80;;-1:-1:-1;3778:1:25;3792:5;;3727:80;3826:4;3816:76;;-1:-1:-1;3863:1:25;3877:5;;3816:76;3908:4;3926:1;3921:59;;;;3994:1;3989:130;;;;3901:218;;3921:59;3951:1;3942:10;;3965:5;;;3989:130;4026:3;4016:8;4013:17;4010:43;;;4033:18;;:::i;:::-;-1:-1:-1;;4089:1:25;4075:16;;4104:5;;3901:218;;4203:2;4193:8;4190:16;4184:3;4178:4;4175:13;4171:36;4165:2;4155:8;4152:16;4147:2;4141:4;4138:12;4134:35;4131:77;4128:159;;;-1:-1:-1;4240:19:25;;;4272:5;;4128:159;4319:34;4344:8;4338:4;4319:34;:::i;:::-;4389:6;4385:1;4381:6;4377:19;4368:7;4365:32;4362:58;;;4400:18;;:::i;:::-;4438:20;;3658:806;-1:-1:-1;;;3658:806:25:o;4469:131::-;4529:5;4558:36;4585:8;4579:4;4558:36;:::i;:::-;4549:45;4469:131;-1:-1:-1;;;4469:131:25:o;4605:273::-;4673:6;4726:2;4714:9;4705:7;4701:23;4697:32;4694:52;;;4742:1;4739;4732:12;4694:52;4774:9;4768:16;4824:4;4817:5;4813:16;4806:5;4803:27;4793:55;;4844:1;4841;4834:12;4605:273;797:42753:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","offset":24340}},"transformations":[{"type":"insert","offset":24393,"reason":"constructorArguments"}],"transformationValues":{"constructorArguments":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49700000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c190850000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd00000000000000000000000020c86b8fc6ae133fe78560c1dedac286a1d83395000000000000000000000000417082c6099338c1a04081ff290e8c64cb08e8e9000000000000000000000000f3c087d5f40f97ba09b258732806aaa10304f168000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b80000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6131848091c3c7f98e5aef7805aa612f81b6052f1c3e3e495ef46d6dee38812ff16c9d6e6c0fe5bb46fd8db51fd239511adb0187726196eb00a2e011dceca114236696efd8534ce144b358082d303ba190cad0c8d37e9f4802b2a5198019379bd943cec1dfc617bf9515058376abfab0217f98cce018735f02efd4abd3453ad8f3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716fa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d70000000000000000000000000000000000000000000000000000000000004000"}},"runtimeBytecode":{"onchainBytecode":"0x6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000181565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c1908573ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f00000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c1908573ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000020c86b8fc6ae133fe78560c1dedac286a1d833956000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000181527f00000000000000000000000000000000000000000000000000000000000f424060208201527f000000000000000000000000000000000000000000000000000000000000000160408201527f00000000000000000000000000000000000000000000000000000000000f4240606082015290565b60006107f37f000000000000000000000000f3c087d5f40f97ba09b258732806aaa10304f1686000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b86000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b86000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f000000000000000000000000417082c6099338c1a04081ff290e8c64cb08e8e96000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e4971614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000001815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49781166020808401919091527f00000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c1908582166040808501919091527f0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529831660a08501527f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee831660c0850152606080850180517f0000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd8616905280517f00000000000000000000000020c86b8fc6ae133fe78560c1dedac286a1d83395861694019390935282517f000000000000000000000000417082c6099338c1a04081ff290e8c64cb08e8e9851692019190915281517f000000000000000000000000f3c087d5f40f97ba09b258732806aaa10304f1688416910152517f000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b882166080918201527f0000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be909116908201527f6131848091c3c7f98e5aef7805aa612f81b6052f1c3e3e495ef46d6dee38812f60e08201527ff16c9d6e6c0fe5bb46fd8db51fd239511adb0187726196eb00a2e011dceca1146101008201527f236696efd8534ce144b358082d303ba190cad0c8d37e9f4802b2a5198019379b6101208201527fd943cec1dfc617bf9515058376abfab0217f98cce018735f02efd4abd3453ad86101408201527ff3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716f6101608201527fa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d76101808201527f00000000000000000000000000000000000000000000000000000000000040006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000400060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000400060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7ff16c9d6e6c0fe5bb46fd8db51fd239511adb0187726196eb00a2e011dceca11485600161326c565b9050600061195d7fd943cec1dfc617bf9515058376abfab0217f98cce018735f02efd4abd3453ad885600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811660208301527f0000000000000000000000005979d7b546e38e414f7e9822514be443a48005291681527f00000000000000000000000000000000000000000000000000000000000f42407f0000000000000000000000000000000000000000000000000000000000000001870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529811660208301527f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1681527f00000000000000000000000000000000000000000000000000000000000f42407f0000000000000000000000000000000000000000000000000000000000000001870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000016124147f00000000000000000000000000000000000000000000000000000000000f42408861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000161246b7f00000000000000000000000000000000000000000000000000000000000f42408661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000000000000000000000000000000000000000f42408602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000000000000000000000000000000000000000f424084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000161256f7f00000000000000000000000000000000000000000000000000000000000f42408861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000016125c67f00000000000000000000000000000000000000000000000000000000000f42408661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000000000000000000000000000000000000000f424086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000000000000000000000000000000000000000f424084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167ff3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716f6139c5565b6129e9565b6129e96103ff60ee8b901c167fa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d76139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f6131848091c3c7f98e5aef7805aa612f81b6052f1c3e3e495ef46d6dee38812f85600161326c565b90506000612b0b7f236696efd8534ce144b358082d303ba190cad0c8d37e9f4802b2a5198019379b85600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527ff3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716f60048201526130ed907f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527fa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d7600482015261318d907f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e49773ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000f42407f00000000000000000000000000000000000000000000000000000000000000018302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000f42407f000000000000000000000000000000000000000000000000000000000000000183028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529811660448301527f000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000040008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000040006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000040008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","recompiledBytecode":"0x6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201527f0000000000000000000000000000000000000000000000000000000000000000606082015290565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f0000000000000000000000000000000000000000000000000000000000000000866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166020808401919091527f000000000000000000000000000000000000000000000000000000000000000082166040808501919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08501527f0000000000000000000000000000000000000000000000000000000000000000831660c0850152606080850180517f00000000000000000000000000000000000000000000000000000000000000008616905280517f0000000000000000000000000000000000000000000000000000000000000000861694019390935282517f0000000000000000000000000000000000000000000000000000000000000000851692019190915281517f00000000000000000000000000000000000000000000000000000000000000008416910152517f000000000000000000000000000000000000000000000000000000000000000082166080918201527f0000000000000000000000000000000000000000000000000000000000000000909116908201527f000000000000000000000000000000000000000000000000000000000000000060e08201527f00000000000000000000000000000000000000000000000000000000000000006101008201527f00000000000000000000000000000000000000000000000000000000000000006101208201527f00000000000000000000000000000000000000000000000000000000000000006101408201527f00000000000000000000000000000000000000000000000000000000000000006101608201527f00000000000000000000000000000000000000000000000000000000000000006101808201527f00000000000000000000000000000000000000000000000000000000000000006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b9050600061195d7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000006124147f00000000000000000000000000000000000000000000000000000000000000008861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000061246b7f00000000000000000000000000000000000000000000000000000000000000008661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000061256f7f00000000000000000000000000000000000000000000000000000000000000008861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000006125c67f00000000000000000000000000000000000000000000000000000000000000008661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129e9565b6129e96103ff60ee8b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b90506000612b0b7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000000000000000000000000000000000000000000000826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526130ed907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015261318d907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000000000000000000000000000000000000000000000856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660448301527f00000000000000000000000000000000000000000000000000000000000000008116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000000006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000000000000000000000000000000000000000000000907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","sourceMap":"797:42753:18:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38672:7;;;;:21;38668:63;;38709:11;:9;:11::i;:::-;797:42753;;38607:11;:9;:11::i;43065:483::-;;;;;;;;;;-1:-1:-1;43065:483:18;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40119:423;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;25047:246::-;;;;;;;;;;-1:-1:-1;25047:246:18;;;;;:::i;:::-;;:::i;:::-;;;2429:25:25;;;2417:2;2402:18;25047:246:18;2283:177:25;16567:263:18;;;;;;:::i;:::-;;:::i;18250:280::-;;;;;;:::i;:::-;;:::i;27572:273::-;;;;;;:::i;20865:310::-;;;;;;;;;;-1:-1:-1;20865:310:18;;;;;:::i;:::-;;:::i;:::-;;;;3737:25:25;;;3793:2;3778:18;;3771:34;;;;3710:18;20865:310:18;3563:248:25;26706:263:18;;;;;;;;;;-1:-1:-1;26706:263:18;;;;;:::i;:::-;;:::i;19897:318::-;;;;;;:::i;41597:501::-;;;;;;;;;;-1:-1:-1;41597:501:18;;;;;:::i;:::-;;:::i;36902:346::-;;;;;;;;;;;;;:::i;27998:826::-;;;;;;;;;;-1:-1:-1;27998:826:18;;;;;:::i;:::-;;:::i;186:186:9:-;;;;;;;;;;-1:-1:-1;186:186:9;;;;;:::i;:::-;308:12;;186:186;38787:1282:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;17422:274::-;;;;;;:::i;:::-;;:::i;29694:7202::-;;;;;;;;;;-1:-1:-1;29694:7202:18;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;23419:257::-;;;;;;:::i;685:31:21:-;;;;;;;;;;;;;;;37849:714:18;37894:36;;;;;37919:10;37894:36;;;9567:74:25;37894:11:18;:24;;;;;9540:18:25;;37894:36:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:88;;;-1:-1:-1;37934:48:18;;;;;37964:4;37934:48;;;10137:34:25;37971:10:18;10187:18:25;;;10180:43;37934:11:18;:21;;;;;10049:18:25;;37934:48:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37888:171;;38006:42;;;;;359:5:13;38006:42:18;;;2429:25:25;2402:18;;38006:42:18;;;;;;;;37888:171;38069:18;38090:12;38132:1;38116:17;;;:22;;38112:82;;38147:47;;;;;302:5:13;38147:47:18;;;2429:25:25;2402:18;;38147:47:18;2283:177:25;38112:82:18;38251:13;38267:1;38251:17;38236:12;:32;;;;38343:38;38350:20;38372:8;;38343:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38343:6:18;;-1:-1:-1;;;38343:38:18:i;:::-;-1:-1:-1;;38533:12:18;;;38548:8;38533:23;38518:38;;37849:714::o;43065:483::-;43280:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43280:22:18;43333:208;43367:14;43399:11;43428;43457:26;43501;43333:16;:208::i;:::-;43314:227;43065:483;-1:-1:-1;;;;;;43065:483:18:o;40119:423::-;40168:37;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40168:37:18;40260:27;40217:70;;40342:29;40297:42;;;:74;40424:27;40381:40;;;:70;40506:29;40461:42;;;:74;40217:15;40119:423::o;25047:246::-;25184:12;25226:48;25233:30;25265:8;;25226:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25226:6:18;;-1:-1:-1;;;25226:48:18:i;:::-;25215:71;;;;;;;;;;;;:::i;:::-;25208:78;25047:246;-1:-1:-1;;;;;25047:246:18:o;16567:263::-;16716:18;16753:70;16761:9;16772;16783:39;;;;;;;;16796:3;16783:39;;;;;;16801:13;16783:39;;;;16816:5;16783:39;;;;;16753:7;:70::i;18250:280::-;18400:17;18447:64;18454:46;18502:8;;18447:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18447:6:18;;-1:-1:-1;;;18447:64:18:i;20865:310::-;21021:15;21038;21083:64;21090:46;21138:8;;21083:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21083:6:18;;-1:-1:-1;;;21083:64:18:i;:::-;21072:96;;;;;;;;;;;;:::i;:::-;21065:103;;;;20865:310;;;;;;;:::o;26706:263::-;26856:17;26903:47;26910:29;26941:8;;26903:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26903:6:18;;-1:-1:-1;;;26903:47:18:i;41597:501::-;41818:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41818:28:18;41877:214;41917:14;41949:11;41978;42007:26;42051;41877:22;:214::i;36902:346::-;36957:18;36978:12;37022:13;;37046:37;36978:12;37022:13;37046:6;:37::i;:::-;37094:34;37131:56;37159:12;;37173:13;;37131:27;:56::i;:::-;37205:36;;;;;;10918:13:25;;37205:36:18;;;10900:32:25;10988:4;10976:17;;10970:24;10948:20;;;10941:54;11039:17;;;11033:24;11011:20;;;11004:54;11114:4;11102:17;;11096:24;11074:20;;;11067:54;11177:4;11165:17;;11159:24;11137:20;;;11130:54;11240:4;11228:17;;11222:24;11200:20;;;11193:54;11303:4;11291:17;;11285:24;11263:20;;;11256:54;11366:4;11354:17;;11348:24;11326:20;;;11319:54;11392:6;11440:15;;11434:22;11414:18;;;11407:50;37094:93:18;;-1:-1:-1;10872:19:25;;37205:36:18;10673:790:25;27998:826:18;28100:10;:32;28122:9;28100:32;;28096:99;;28141:54;;;;;3185:5:13;28141:54:18;;;2429:25:25;2402:18;;28141:54:18;2283:177:25;28096:99:18;28209:12;;28224:1;28209:16;28229:1;28209:21;28205:90;;28239:56;;;;;3313:5:13;28239:56:18;;;2429:25:25;2402:18;;28239:56:18;2283:177:25;28205:90:18;28325:2;28309:18;;28305:83;;28336:52;;;;;5300:5:13;28336:52:18;;;2429:25:25;2402:18;;28336:52:18;2283:177:25;28305:83:18;28400:18;;;28455:40;;;;28466:5;28455:40;:::i;:::-;28399:96;;;;;;28526:7;28510:13;:23;28506:95;;;28542:59;;;;;5374:5:13;28542:59:18;;;2429:25:25;2402:18;;28542:59:18;2283:177:25;28506:95:18;28616:11;28612:206;;;28643:54;;;;;:31;12123:55:25;;;28643:54:18;;;12105:74:25;12195:18;;;12188:34;;;28643:31:18;;;;;12078:18:25;;28643:54:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28612:206;;;28728:79;28758:6;28766:5;28781:9;28793:13;28728:29;:79::i;:::-;28086:738;;;27998:826;;;;:::o;38787:1282::-;38835:35;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38835:35:18;38905:6;38882:29;;38921:45;38956:9;38921:45;;:24;;;;:45;;;;39009:11;38976:45;;:22;;;;:45;;;;39055:7;39031:31;;:21;;;:31;39096:7;39072:31;;:21;;;:31;39113:30;;;;;;39152:20;39113:59;;;;39182:30;;39221:20;39182:59;;:36;;:59;;;;39251:30;;39298:29;39251:76;;:44;;:76;;;;39337:30;;39385;39337:78;;:45;;:78;39425:30;39486:46;39425:107;;:58;;;;:107;39576:17;39542:51;;;:31;;;:51;39637:19;39603:31;;;:53;39700:19;39666:31;;;:53;39763:19;39729:31;;;:53;39826:19;39792:31;;;:53;39896:27;39855:38;;;:68;39974:27;39933:38;;;:68;40042:20;40011:28;;;:51;38882:14;38787:1282::o;17422:274::-;17583:18;17620:69;17628:9;17639;17650:38;;;;;;;;17663:3;17650:38;;;;;;17668:13;17650:38;;;;17683:4;17650:38;;;;;17620:7;:69::i;29694:7202::-;29780:22;29804:18;29834:27;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29834:27:18;29872:18;29893:12;;;29945:1;29938:3;29921:20;;;29920:26;:31;;29916:117;;29974:48;;;;;5713:5:13;29974:48:18;;;2429:25:25;2402:18;;29974:48:18;2283:177:25;29916:117:18;30065:12;:19;30052:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30052:33:18;;;;;;;;;;;;;;;;;30043:42;;30096:15;30121:10;30142:6;30158:16;30177:12;30190:1;30177:15;;;;;;;;:::i;:::-;;;;;;;;;;;;30273:38;;;;;;30237:2;30220:19;;;1133:4:16;30317:37:18;30272:83;30402:34;;;30446:19;;;:35;;;1215:3:16;30592::18;30575:20;;;30574:27;;30558:13;;;:43;;;1551:6:16;30644:3:18;30627:20;;;30626:28;30611:12;;;:43;30272:83;;-1:-1:-1;30177:15:18;;-1:-1:-1;30272:83:18;;-1:-1:-1;;;;;;;30767:45:18;;30811:1;30767:45;;;30795:12;;;;30787:21;;;;:7;:21;;;;;;30767:45;30755:9;;;:57;30823:14;;30912:15;30898:3;30881:20;;;2011:11:16;30880:28:18;30879:48;30875:427;;;31085:48;31122:3;31105:20;;;2011:11:16;31104:28:18;31085:15;:48;:::i;:::-;31077:56;;30875:427;;;31288:3;;;:::i;:::-;;;30875:427;31343:1;31348;31343:6;31339:2481;;31375:2;:13;;31373:15;;;;;:::i;:::-;;;;;31392:1;31373:20;31369:269;;31433:1;31417:13;;;:17;;;31460:12;;;;:17;;31456:107;;31520:20;31505:12;;;:35;31456:107;31596:7;:23;31606:2;:12;;31604:14;;;;;:::i;:::-;;;;;31596:23;;;;;;;;;;;-1:-1:-1;31596:23:18;;31584:9;;;:35;31369:269;1963:10:16;31683:2:18;:13;;;31699:2;31683:18;;;;:::i;:::-;31669:9;;;;:33;;31668:41;;-1:-1:-1;31731:13:18;;31727:1723;;1378:5:16;31776:9:18;:14;31768:22;;31816:5;31825:1;31816:10;31812:801;;31935:1;31922:9;:14;;31914:22;;32062:2;:13;;;32079:1;32062:18;32058:533;;32128:1;32112:13;;;:17;;;32163:12;;;;:17;;32159:123;;32231:20;32216:12;;;:35;32159:123;32323:7;:23;32333:2;:12;;32331:14;;;;;:::i;:::-;;;;;32323:23;;;;;;;;;;;-1:-1:-1;32323:23:18;;32311:9;;;:35;;;1963:10:16;32388:15:18;;-1:-1:-1;32058:533:18;;;32468:2;:13;;32466:15;;;;;:::i;:::-;;;32538:13;;;;1963:10:16;;32538:18:18;;32554:2;32538:18;:::i;:::-;32524:2;:9;;;:33;;32523:41;32511:53;;32058:533;-1:-1:-1;32662:2:18;32649:15;;;1730:8:16;32702:27:18;32649:15;2789:8:16;32702:27:18;:::i;:::-;32701:35;;;;:::i;:::-;32686:50;;32777:1;32764:9;:14;;32782:1;32763:20;32787:1;32763:25;32758:443;;2730:4:16;32931:21:18;32940:12;32931:6;:21;:::i;:::-;32930:42;;;;:::i;:::-;32921:51;;:6;:51;:::i;:::-;32912:60;;31339:2481;;32758:443;2730:4:16;33137:21:18;33146:12;33137:6;:21;:::i;:::-;33136:42;;;;:::i;:::-;33127:51;;:6;:51;:::i;31727:1723::-;33376:55;;;;;4578:5:13;33376:55:18;;;2429:25:25;2402:18;;33376:55:18;2283:177:25;31339:2481:18;33474:1;33479;33474:6;33470:350;;33720:3;33703:20;;;1730:8:16;33702:28:18;;-1:-1:-1;33608:31:18;;;;;;1133:4:16;33572:1:18;33555:18;;;33645:30;33607:69;;-1:-1:-1;33748:3:18;;;:::i;:::-;;;33470:350;;;33776:1;33781;33776:6;33772:48;;33802:3;;;:::i;:::-;;;33772:48;33834:19;33848:5;33834:19;;:::i;:::-;;;33892:6;33871:2;:18;;;:27;33867:60;;;33900:27;;;33867:60;33967:6;33945:2;:19;;;:28;33941:62;;;33975:19;;;:28;;;33941:62;34034:11;34021:10;:24;34017:2863;;;34078:14;34087:5;34078:6;:14;:::i;:::-;34065:27;;;;:::i;:::-;;-1:-1:-1;34141:5:18;34124:13;34131:6;34124:4;:13;:::i;:::-;34123:23;;;;:::i;:::-;34110:36;;;;:::i;:::-;;;31312:5578;;34017:2863;34215:10;34193:19;34201:11;34193:5;:19;:::i;:::-;:32;;;;:::i;:::-;34185:40;-1:-1:-1;34256:14:18;34185:40;34256:6;:14;:::i;:::-;34243:27;;;;:::i;:::-;;-1:-1:-1;34319:5:18;34302:13;34309:6;34302:4;:13;:::i;:::-;34301:23;;;;:::i;:::-;34288:36;;;;:::i;:::-;;-1:-1:-1;34427:23:18;34439:11;34427:9;:23;:::i;:::-;34415:35;-1:-1:-1;34480:23:18;34492:11;34480:9;:23;:::i;:::-;34468:35;;34534:266;;;;;;;;34562:9;34534:266;;;;34593:2;:18;;;34534:266;;;;34633:2;:19;;;34534:266;;;;34674:9;34534:266;;;;34713:2;:19;;;34706:4;:26;;;;:::i;:::-;34534:266;;;;34763:2;:18;;;34756:4;:25;;;;:::i;:::-;34534:266;;;34522:6;34529:1;34522:9;;;;;;;;:::i;:::-;;;;;;;;;;;:278;;;;34886:27;;;34931:19;;:28;;;34978:1789;34991:19;;34985:3;;;:::i;:::-;;;;:25;34978:1789;;;35091:24;35104:11;35091:10;:24;:::i;:::-;35083:32;-1:-1:-1;35083:32:18;;-1:-1:-1;35362:12:18;35375:5;35379:1;35375;:5;:::i;:::-;35362:19;;;;;;;;:::i;:::-;;;;;;;35344:12;35357:1;35344:15;;;;;;;;:::i;:::-;;;;;;;:37;;;;:::i;:::-;35330:51;;35420:11;35407:10;:24;35403:1346;;;35471:14;35480:5;35471:6;:14;:::i;:::-;35459:26;-1:-1:-1;35541:5:18;35524:13;35531:6;35524:4;:13;:::i;:::-;35523:23;;;;:::i;:::-;35511:35;;35734:5;35743:1;35734:10;35730:161;;35797:14;35776:35;;:18;35841:19;;;:23;35730:161;35916:5;;35403:1346;36006:10;35984:19;35992:11;35984:5;:19;:::i;:::-;:32;;;;:::i;:::-;35976:40;-1:-1:-1;36105:14:18;35976:40;36105:6;:14;:::i;:::-;36093:26;-1:-1:-1;36239:5:18;36222:13;36229:6;36222:4;:13;:::i;:::-;36221:23;;;;:::i;:::-;36209:35;-1:-1:-1;36282:23:18;36294:11;36282:9;:23;:::i;:::-;36270:35;-1:-1:-1;36343:23:18;36355:11;36343:9;:23;:::i;:::-;36331:35;;36404:322;;;;;;;;36440:9;36404:322;;;;36479:2;:18;;;36404:322;;;;36527:2;:19;;;36404:322;;;;36576:9;36404:322;;;;36623:2;:19;;;36616:4;:26;;;;:::i;:::-;36404:322;;;;36681:2;:18;;;36674:4;:25;;;;:::i;:::-;36404:322;;;36392:6;36399:1;36392:9;;;;;;;;:::i;:::-;;;;;;:334;;;;34978:1789;;;36793:12;:19;36788:1;:24;36784:60;;36814:30;;;;;;;;;;;;29694:7202;;;:::o;36784:60::-;31312:5578;;2660:667:20;2731:22;2869:1;2866;2858:5;2852:12;2845:4;2838:5;2834:16;2825:7;2818:5;2805:66;2896:16;2945:4;2939:11;2926:24;;3027:4;3023:9;3016:4;3009;3003;2999:15;2995:26;2991:42;2980:9;2976:58;2970:4;2963:72;3066:4;3055:9;3048:23;3124:4;3121:1;3114:4;3103:9;3099:20;3084:45;3153:9;3143:168;;3257:4;3251;3245;3230:32;3292:4;3286;3279:18;3143:168;;;2660:667;;;;:::o;36559:1446::-;36777:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36777:22:20;36811:16;36830:72;36848:19;36869:26;36897:4;36830:17;:72::i;:::-;36811:91;;36912:16;36931:73;36949:19;36970:26;36998:5;36931:17;:73::i;:::-;37015:27;;;37052:13;;;:27;;;36912:92;-1:-1:-1;37111:4:20;37094:21;;37090:909;;;37314:77;37337:14;37353:11;37366;37379;37314:22;:77::i;:::-;37271:26;;;37131:260;37227:26;;;37131:260;37188:21;;;37131:260;37149:21;;;37131:260;37090:909;;;37893:95;37917:21;37924:14;37917:4;:21;:::i;:::-;37942:18;37949:11;37942:4;:18;:::i;:::-;37963:11;37976;37893:22;:95::i;:::-;37850:26;;;37710:278;37806:26;;;37710:278;37767:21;;;37710:278;37728:21;;;37710:278;37090:909;36801:1204;;36559:1446;;;;;;;:::o;2381:13621:18:-;2510:18;2561:12;;2605:13;;;;2652:3;2634:21;;;2633:28;;2629:96;;2670:55;;;;;3971:5:13;2670:55:18;;;2429:25:25;2402:18;;2670:55:18;2283:177:25;2629:96:18;2736:37;2743:13;2758:14;2736:6;:37::i;:::-;2788:10;;:24;;2784:53;;2827:10;2814:23;;2784:53;2848:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2848:22:18;2885:9;2881:459;;;2910:46;2948:7;2910:46;;2923:11;;;2910:46;2939:7;2910:46;;;3061:29;3030:27;3018:39;;3061:29;3017:73;;;;:::i;:::-;;2998:16;;;:92;2881:459;;;3135:46;3173:7;3135:46;;3148:11;;;3135:46;3164:7;3135:46;;;3286:29;3255:27;3243:39;;3286:29;3242:73;;;;:::i;:::-;;3223:16;;;:92;2881:459;3350:60;3382:2;:16;;;3400:9;3350:31;:60::i;:::-;3421:34;3458:58;3486:13;3501:14;3458:27;:58::i;:::-;3421:95;-1:-1:-1;3531:9:18;:13;3527:243;;3577:9;3564;:22;3560:90;;3595:55;;;;;695:5:13;3595:55:18;;;2429:25:25;2402:18;;3595:55:18;2283:177:25;3560:90:18;3668:10;;:26;;594:42:16;3668:26:18;3664:95;;3703:56;;;;;766:5:13;3703:56:18;;;2429:25:25;2402:18;;3703:56:18;2283:177:25;3664:95:18;1595:7:16;4051:1:18;4033:19;;;4032:27;1296:4:16;4312:2:18;4294:20;;;4293:27;4292:38;;2569:3:16;4273:59:18;4257:13;;;:75;2517:3:16;4501:21:18;;;4492:6;;;:30;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3854:1:18;3837:18;;;;3918:19;;;3917:25;;;;4032:27;;4586;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4586:27:18;4627:5;4636:1;4627:10;4623:1431;;4714:28;4745:258;4789:4;:18;;;4829:4;:15;;;4866:4;:15;;;4903:4;:30;;;4955:4;:30;;;4745:22;:258::i;:::-;4714:289;;5025:9;5021:1009;;;5317:21;;5364;;;;;5411:26;;;;;5463;;;;;5237:29;;;5058:453;5183:28;;;5058:453;5133:24;;;5058:453;;;5021:1009;;;5817:21;;;;;5864;;5911:26;;;;;5963;;;;;5737:29;;;5558:453;;;;5683:28;;;5558:453;5633:24;;;5558:453;;;;;;5021:1009;4696:1348;4623:1431;6068:6;6078:1;6068:11;6064:1736;;6150:22;6175:252;6213:4;:18;;;6253:4;:15;;;6290:4;:15;;;6327:4;:30;;;6379:4;:30;;;6175:16;:252::i;:::-;6150:277;;6449:9;6445:1331;;;6824:13;;6863;;;;;6902:21;;;;;6949;;;;;6996:26;;;;;7048;;;;;6744:29;;;6482:614;6690:28;;;6482:614;6640:24;;;6482:614;6591:23;;;6482:614;6549:16;;;6482:614;;;6445:1331;;;7485:13;;;;;7524;;7563:21;;;;;7610;;;;;7657:26;;;;;7709;;;;;7405:29;;;7143:614;;;;7351:28;;;7143:614;7301:24;;;7143:614;;;;7252:23;;;7143:614;7210:16;;;7143:614;;;;;;6445:1331;6132:1658;6064:1736;8578:1;8546:3;:28;;;8515:3;:28;;;:59;8514:65;;;;;:::i;:::-;;8494:2;:16;;;:86;8490:169;;;8605:54;;;;;4165:5:13;8605:54:18;;;2429:25:25;2402:18;;8605:54:18;2283:177:25;8490:169:18;8684:5;8693:1;8684:10;:25;;;;;8698:6;8708:1;8698:11;8684:25;8680:397;;;8818:248;8850:2;:16;;;8884:3;:29;;;8931:3;:28;;;8977:3;:29;;;9024:3;:28;;;8818:14;:248::i;:::-;8798:17;;;:268;8680:397;9295:2;:17;;;9275:2;:16;;;9271:41;:66;;;;;9336:1;9316:2;:17;;;:21;9271:66;9267:1495;;;9453:17;;;;9564:16;;;;9755:10;;9739:26;;;;:13;;;:26;9793:10;;9779:24;:11;;;:24;9453:17;;-1:-1:-1;9637:1:18;;-1:-1:-1;9564:24:18;;;;-1:-1:-1;9637:1:18;;-1:-1:-1;9267:1495:18;;;9825:5;9834:1;9825:10;:25;;;;-1:-1:-1;9839:11:18;;9825:25;9824:75;;;;9881:2;:16;;;9856:2;:17;;;:42;;9824:75;9820:942;;;10012:16;;;;10197:10;;10181:26;;:13;;;:26;10012:16;-1:-1:-1;10030:1:18;;-1:-1:-1;10030:1:18;;-1:-1:-1;10030:1:18;;-1:-1:-1;9820:942:18;;;10229:10;;:25;;;;;10243:6;10253:1;10243:11;10229:25;10228:55;;;;10281:1;10260:2;:17;;;:22;;10228:55;10224:538;;;10396:16;;;;10579:10;;10565:24;;:11;;;:24;10390:1;;-1:-1:-1;10390:1:18;;-1:-1:-1;10396:16:18;-1:-1:-1;10390:1:18;;-1:-1:-1;10224:538:18;;;10707:44;;;;;825:5:13;10707:44:18;;;2429:25:25;2402:18;;10707:44:18;2283:177:25;10224:538:18;10776:9;;10772:785;;10848:171;2517:3:16;10889:2:18;:6;;;10881:5;:14;;;;:::i;:::-;10880:31;;;;:::i;:::-;10930:3;:28;;;10976:3;:29;;;10848:13;:171::i;:::-;10839:180;;11033:9;:513;;11313:233;11384:6;11357:3;:24;;;:33;;;;:::i;:::-;11414:23;;:31;;11440:5;;11414:31;:::i;:::-;11468:4;:16;;;3059:3:16;11313:21:18;:233::i;:::-;11033:513;;;11105:23;;11061:233;;11105:31;;11131:5;;11105:31;:::i;:::-;11187:6;11160:3;:24;;;:33;;;;:::i;:::-;11216:4;:16;;;3059:3:16;11061:21:18;:233::i;:::-;11570:10;;11566:790;;11644:172;2517:3:16;11686:2:18;:6;;;11677;:15;;;;:::i;:::-;11676:32;;;;:::i;:::-;11727:3;:28;;;11773:3;:29;;;11644:13;:172::i;:::-;11635:181;;11830:9;:515;;12111:234;12182:6;12155:3;:24;;;:33;;;;:::i;:::-;12238:6;12212:3;:23;;;:32;;;;:::i;12111:234::-;11830:515;;;11858:234;11928:6;11902:3;:23;;;:32;;;;:::i;:::-;11985:6;11958:3;:24;;;:33;;;;:::i;11858:234::-;2569:3:16;12513:2:18;:13;;;12505:5;:21;;;;:::i;:::-;12504:40;;;;:::i;:::-;12496:48;;2569:3:16;12573:2:18;:13;;;12564:6;:22;;;;:::i;:::-;12563:41;;;;:::i;:::-;12554:50;;12792:6;12784:5;:14;12780:643;;;12869:9;:227;;13089:6;13057:3;:29;;;:38;;;;:::i;:::-;13039:5;13008:3;:28;;;:36;;;;:::i;:::-;13007:45;;13048:4;13007:45;:::i;:::-;13006:90;;;;:::i;:::-;12869:227;;;12981:5;12950:3;:28;;;:36;;;;:::i;:::-;12931:6;12899:3;:29;;;:38;;;;:::i;:::-;12898:47;;12941:4;12898:47;:::i;:::-;12897:90;;;;:::i;:::-;12858:8;;;:238;12780:643;;;13183:9;:229;;13405:6;13373:3;:29;;;:38;;;;:::i;:::-;13354:6;13323:3;:28;;;:37;;;;:::i;:::-;13322:46;;13364:4;13322:46;:::i;:::-;13321:91;;;;:::i;:::-;13183:229;;;13295:6;13264:3;:28;;;:37;;;;:::i;:::-;13245:6;13213:3;:29;;;:38;;;;:::i;:::-;13212:47;;13255:4;13212:47;:::i;:::-;13211:91;;;;:::i;:::-;13172:8;;;:240;12780:643;13485:9;13481:989;;;13561:27;13520:37;13528:29;13520:5;:37;:::i;:::-;13519:69;;;;:::i;:::-;13510:79;-1:-1:-1;13656:27:18;13614:38;13623:29;13614:6;:38;:::i;:::-;13613:70;;;;:::i;:::-;13603:81;;13828:27;13795:29;13786:6;:38;13785:70;;;;;:::i;:::-;;13775:81;;13927:27;13894:29;13885:6;:38;13884:70;;;;;:::i;:::-;;13874:81;;13481:989;;;14051:27;14010:37;14018:29;14010:5;:37;:::i;:::-;14009:69;;;;:::i;:::-;14000:79;-1:-1:-1;14146:27:18;14104:38;14113:29;14104:6;:38;:::i;:::-;14103:70;;;;:::i;:::-;14093:81;;14318:27;14285:29;14276:6;:38;14275:70;;;;;:::i;:::-;;14265:81;;14417:27;14384:29;14375:6;:38;14374:70;;;;;:::i;:::-;;14364:81;;13481:989;14614:10;;14517:15;;;;-1:-1:-1;14614:26:18;;;;14610:69;;14649:30;;;;;;;;2429:25:25;;;2402:18;;14649:30:18;2283:177:25;14610:69:18;14707:7;:20;;;14694:10;:33;14690:97;;;14736:51;;;;;891:5:13;14736:51:18;;;2429:25:25;2402:18;;14736:51:18;2283:177:25;14690:97:18;14959:9;14970:7;:18;;;14990:10;14948:53;;;;;;;;;13958:25:25;;;14026:14;;14019:22;14014:2;13999:18;;13992:50;14090:42;14078:55;14073:2;14058:18;;14051:83;13946:2;13931:18;;13762:378;14948:53:18;;;;;;;;;;;;;;14938:7;;;:63;15184:10;;15146:17;:9;:17;;;;15172:9;;15200:5;15208:12;15213:6;15208:12;:::i;:::-;15230:1;15242;15246:2;:7;;;15146:108;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;15316:9;:17;;;15334:2;:11;;;15352:6;15347:12;;;:::i;:::-;15374:13;;;;15389:11;;;;15402:12;;;15412:1;15402:12;;;;;;;;;15316:99;;;;;;;;;;;;;15365:6;;15374:13;;15316:99;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;15497:3:18;15479:21;;;1915:10:16;15478:29:18;;-1:-1:-1;15521:9:18;;15517:121;;15546:23;;;:11;;;:23;;;15618:8;;;;15583:44;;15595:5;;15602:1;;15546:23;15583:11;:44::i;:::-;15648:9;:199;;15767:80;1421:5:16;15806:3:18;15788:14;:21;;15787:29;15819:27;15767:18;:80::i;:::-;15648:199;;;15672:80;1421:5:16;15711:3:18;15693:14;:21;;15692:29;15724:27;15672:18;:80::i;:::-;15873:56;15887:2;:8;;;15897:4;:16;;;15915:13;15873;:56::i;:::-;15858:12;:71;;;;15945:50;15950:9;15961;15972:10;15984:7;:10;;;15945:50;;;;;;;;15647:14:25;;15640:22;15622:41;;15694:2;15679:18;;15672:34;;;;15737:2;15722:18;;15715:34;15797:42;15785:55;15780:2;15765:18;;15758:83;15609:3;15594:19;;15397:450;15945:50:18;;;;;;;;2530:13472;;;;;;;;;;2381:13621;;;;;:::o;28430:1570:20:-;28654:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28654:28:20;28694:18;28715:78;28739:19;28760:26;28788:4;28715:23;:78::i;:::-;28694:99;;28803:18;28824:79;28848:19;28869:26;28897:5;28824:23;:79::i;:::-;28803:100;;28935:4;28918:14;:21;28914:841;;;29014:167;29062:14;29094:11;29123:13;29154;29014:30;:167::i;:::-;28984:26;;;28955:226;28956:26;;;28955:226;28914:841;;;29559:185;29608:21;29615:14;29608:4;:21;:::i;:::-;29649:18;29656:11;29649:4;:18;:::i;:::-;29686:13;29717;29559:30;:185::i;:::-;29529:26;;;29500:244;29501:26;;;29500:244;28914:841;29765:37;;;29812:21;;;:37;;;29883:26;;;:43;;;;;;;;29940:26;;;:43;;;;;;;29765:2;28430:1570;-1:-1:-1;;;;;28430:1570:20:o;8773:336::-;8853:13;8869:1;8853:17;8874:1;8853:22;8849:82;;8884:47;;;;;302:5:13;8884:47:20;;;2429:25:25;2402:18;;8884:47:20;2283:177:25;8849:82:20;8945:14;8962:1;8945:18;8967:1;8945:23;8941:87;;8977:51;;;;;558:5:13;8977:51:20;;;2429:25:25;2402:18;;8977:51:20;2283:177:25;8941:87:20;-1:-1:-1;9101:1:20;9085:17;9070:12;:32;8773:336::o;16348:7349::-;16466:34;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16466:34:20;16512:17;16564:3;16546:14;:21;;16571:1;16545:27;16577:1;16544:34;16540:883;;1915:10:16;16677:3:20;16659:14;:21;;16658:29;16643:44;;16705:12;16721:1;16705:17;16701:563;;-1:-1:-1;16818:37:20;;;;;;1133:4:16;16775:2:20;16758:19;;;16861:36;16817:81;16540:883;;16701:563;17177:57;17202:17;17221:12;17177:24;:57::i;:::-;17164:83;;;:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17149:100;;16540:883;;;17365:47;17382:13;17397:14;17365:16;:47::i;:::-;17350:62;;16540:883;17514:41;;;;;;1133:4:16;17475:2:20;17458:19;;;17561:40;17513:89;17652:2;17634:20;;;1685:7:16;17633:28:20;;;;17711:2;17693:20;;;17692:28;17761:1;17755:2;17737:20;;;17736:26;;17735:33;;17731:218;;17878:60;17897:11;17910;17923:14;17878:18;:60::i;:::-;17833:105;-1:-1:-1;17833:105:20;;-1:-1:-1;17833:105:20;-1:-1:-1;17731:218:20;18185:11;2517:3:16;18170:26:20;2517:3:16;18138:12:20;:27;18137:60;;;;;:::i;:::-;;;-1:-1:-1;2517:3:16;18278:26:20;;;18262:43;;18261:60;18342:13;1685:7:16;18587:2:20;18569:20;;;18568:28;18567:34;18563:2384;;18663:2;18645:20;;;1421:5:16;18644:28:20;;;;18732:2;18714:20;;;18713:28;18799:2;18781:20;;;1822:8:16;18780:28:20;18856:1;18850:2;18832:20;;;18831:26;;18830:33;;18826:397;;19039:165;19087:15;19128;19169:13;19039:22;:165::i;:::-;18987:217;;-1:-1:-1;18987:217:20;-1:-1:-1;18987:217:20;-1:-1:-1;18826:397:20;2365:3:16;19391:26:20;;;19422:32;;;19390:65;19389:112;19346:12;:155;19302:16;:200;19273:1642;;;19608:3;19591:20;;;2011:11:16;19590:28:20;19571:15;:48;19711:28;;;19707:321;;;19849:13;19833:12;19817;19803:11;:26;19802:43;19801:61;;;;;:::i;:::-;;19786:12;:76;19771:91;;19707:321;;;19990:11;19975:26;;19707:321;20064:4;20053:15;;19525:566;19273:1642;;;2365:3:16;20215:26:20;;;20246:32;;;20214:65;20213:112;20170:12;:155;20126:16;:200;20097:818;;;20432:3;20415:20;;;2011:11:16;20414:28:20;20395:15;:48;20535:28;;;20531:321;;;20673:13;20657:12;20642:11;20627:12;:26;20626:43;20625:61;;;;;:::i;:::-;;20610:12;:76;20595:91;;20531:321;;;20814:11;20799:26;;20531:321;20888:4;20877:15;;20349:566;20097:818;18603:2344;;;18563:2384;21065:30;;;;;;1133:4:16;21036:3:20;21018:21;;;21101:29;21064:67;21145:20;;;21141:554;;;21260:5;21245:20;;21290:4;21279:15;;21141:554;;;-1:-1:-1;21493:30:20;;;;;;1133:4:16;21460:3:20;21442:21;;;21529:29;21492:67;21577:20;;;21573:112;;;21632:5;21617:20;;21666:4;21655:15;;21573:112;21792:8;21788:820;;;1685:7:16;21850:2:20;21832:14;:20;;21831:28;21816:44;;1685:7:16;21908:2:20;21890:14;:20;;21889:28;21874:44;;21956:2;21938:14;:20;;21962:1;21937:26;21968:1;21936:33;21932:255;;22034:138;22074:11;22107;22140:14;22034:18;:138::i;:::-;21989:183;-1:-1:-1;21989:183:20;;-1:-1:-1;21989:183:20;-1:-1:-1;21932:255:20;22439:11;2517:3:16;22424:26:20;2517:3:16;22392:12:20;:27;22391:60;;;;;:::i;:::-;;;-1:-1:-1;2517:3:16;22540:26:20;;;22524:43;;22523:60;22509:74;;21788:820;22618:39;;;22667:16;;;:31;;;22708:15;;;:29;;;22747:15;;;:29;;;22829:4;22815:18;;22811:430;;;22946:49;22983:11;22969;:25;22946:22;:49::i;:::-;22925:18;;;:70;22811:430;;;23152:67;23213:4;23199:11;:18;23190:4;23176:11;:18;23175:43;23152:22;:67::i;:::-;23222:4;23152:74;23131:18;;;:95;22811:430;23437:54;;;;;23463:27;23437:54;;;2429:25:25;23390:111:20;;23437:9;:25;;;;;2402:18:25;;23437:54:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23390:33;:111::i;:::-;23356:30;;;23323:178;23324:30;;;23323:178;23626:54;;;;;23652:27;23626:54;;;2429:25:25;23579:111:20;;23626:9;:25;;;;;2402:18:25;;23626:54:20;2283:177:25;23579:111:20;23545:30;;;23512:178;23513:30;;;23512:178;-1:-1:-1;23513:4:20;;16348:7349;-1:-1:-1;;;;;;;16348:7349:20:o;873:1832:8:-;979:13;1150:4;1144:11;1292:66;1273:17;1266:93;1417:42;1410:5;1406:54;1402:1;1383:17;1379:25;1372:89;1559:42;1554:3;1550:52;1545:2;1526:17;1522:26;1515:88;1690:7;1685:2;1666:17;1662:26;1655:43;2548:2;2545:1;2540:3;2521:17;2518:1;2510:6;2503:5;2498:53;2066:16;2059:24;2053:2;2035:16;2032:24;2028:1;2024;2018:8;2015:15;2011:46;2008:76;1808:757;1796:769;;;2590:8;2585:114;;2621:67;;;;;995:5:5;2621:67:8;;;2429:25:25;2402:18;;2621:67:8;2283:177:25;2585:114:8;969:1736;873:1832;;;;:::o;34691:901:20:-;34890:43;;;;;;;;2429:25:25;;;34839:15:20;;;;34890:25;:9;:25;;;;2402:18:25;;34890:43:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34866:67;;2110:18:16;4646:1:7;34958:16:20;:62;;34957:70;34944:83;;1337:4:16;35072:10:20;:15;35065:1;35051:10;:15;;35050:38;;35037:51;;35103:16;35122:1;35103:20;35127:1;35103:25;35099:230;;762:4:6;35228:32:20;;;35227:77;35214:90;;35099:230;35376:9;:199;;35545:29;35514:27;35501:10;:40;35500:74;;;;;:::i;:::-;;35376:199;;;35450:29;35419:27;35406:10;:40;35405:74;;;;;:::i;:::-;;35363:212;34691:901;-1:-1:-1;;;;;34691:901:20:o;30723:3569::-;30856:8;;;;;33006;32990:10;:3;32996:4;32990:10;:::i;:::-;32973:9;32979:3;32973;:9;:::i;:::-;32969:32;;;;:::i;:::-;32968:47;;;;:::i;:::-;32958:57;-1:-1:-1;33025:8:20;33037:9;33043:3;33037;:9;:::i;:::-;33025:22;;33069:4;33063:3;:10;:52;;33112:3;33098:10;33104:4;33098:3;:10;:::i;:::-;33097:18;;;;:::i;:::-;33063:52;;;33090:4;33077:9;33083:3;33077;:9;:::i;:::-;33076:18;;;;:::i;:::-;33057:58;-1:-1:-1;33146:47:20;33181:9;33187:3;;33181:9;:::i;:::-;33170:21;;:3;:21;:::i;:::-;33146:22;:47::i;:::-;33136:58;;:3;:58;:::i;:::-;33125:70;-1:-1:-1;33522:9:20;33528:3;33522;:9;:::i;:::-;33507:10;:3;33513:4;33507:10;:::i;:::-;33506:26;;;;:::i;:::-;33498:35;;2517:3:16;33547:4:20;:19;33543:168;;;33649:51;;;;;4785:5:13;33649:51:20;;;2429:25:25;2402:18;;33649:51:20;2283:177:25;33543:168:20;33730:4;33724:3;:10;33720:234;;;33778:4;33758:9;33764:3;;33758:9;:::i;:::-;:16;;33770:4;33758:16;:::i;:::-;33757:25;;;;:::i;:::-;33750:32;;33720:234;;;33931:11;33938:4;33931;:11;:::i;:::-;33917:9;33923:3;;33917:9;:::i;:::-;33916:27;;;;:::i;:::-;33909:34;;33720:234;34145:3;34138;34124:10;34145:3;34124:4;:10;:::i;:::-;34123:18;;;;:::i;:::-;34122:26;;;;:::i;:::-;34115:33;-1:-1:-1;34274:10:20;34281:3;34274:4;:10;:::i;:::-;34259;34266:3;34259:4;:10;:::i;:::-;34258:27;;;;:::i;:::-;34252:33;;30898:3394;;30723:3569;;;;;;;;;:::o;10183:475::-;2517:3:16;10459:15:20;:30;:55;;;;2166:26:16;10493:15:20;:21;10459:55;:81;;;;2313:3:16;10518:7:20;:22;10459:81;:99;;;;2231:34:16;10544:7:20;:14;10459:99;10455:196;;;10579:72;;;;;4508:5:13;10579:72:20;;;2429:25:25;2402:18;;10579:72:20;2283:177:25;10455:196:20;10183:475;;:::o;5631:664::-;5720:6;;6090:36;6113:5;6117:1;6113;:5;:::i;:::-;:12;;6121:4;6113:12;:::i;6090:36::-;6075:51;-1:-1:-1;6136:14:20;6153:38;6176:7;6181:2;6176;:7;:::i;6153:38::-;6136:55;-1:-1:-1;6268:19:20;6136:55;6268:7;:19;:::i;:::-;6246:13;6250:9;6246:1;:13;:::i;:::-;6227:11;6231:7;6227:1;:11;:::i;:::-;6212:12;6217:7;6212:2;:12;:::i;:::-;:26;;;;:::i;:::-;6208:52;;;;:::i;:::-;6207:81;;;;:::i;:::-;6202:86;5631:664;-1:-1:-1;;;;;;;;5631:664:20:o;3641:538::-;3773:18;3938:24;;;3999:23;;;;3938:24;3999:23;4137:25;;;;:::i;:::-;;;3641:538;-1:-1:-1;;;;;;3641:538:20:o;9290:353::-;9520:28;9535:13;9520:12;:28;:::i;:::-;9493:22;:15;9511:4;9493:22;:::i;:::-;9492:57;;;;:::i;:::-;9472:15;9471:79;9466:171;;;9574:52;;;;;625:5:13;9574:52:20;;;2429:25:25;2402:18;;9574:52:20;2283:177:25;9466:171:20;9290:353;;;;:::o;9824:::-;10062:20;10069:13;10062:4;:20;:::i;:::-;10027:30;10045:12;10027:15;:30;:::i;:::-;10026:57;;;;:::i;:::-;10006:15;10005:79;10000:171;;;10108:52;;;;;625:5:13;10108:52:20;;;2429:25:25;2402:18;;10108:52:20;2283:177:25;45968:549:20;46090:57;46115:17;46134:12;46090:24;:57::i;:::-;46084:211;;;;;;;;17323:25:25;;;17391:14;;17384:22;17364:18;;;17357:50;46084:73:20;46225:7;17504:15:25;;17484:18;;;17477:43;46250:7:20;17556:15:25;;17536:18;;;17529:43;17588:19;;;17581:35;;;46084:73:20;;;;;;;17295:19:25;;46084:211:20;;;;;;;;;;;;;;;;;;;-1:-1:-1;46084:211:20;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;46068:443;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46420:91;46068:443;;;46344:5;46339:69;;46358:50;;;;;1044:5:13;46358:50:20;;;2429:25:25;2402:18;;46358:50:20;2283:177:25;7672:1095:20;2365:3:16;7780:17:20;:34;7776:985;;;7850:22;:17;7870:2;7850:22;:::i;:::-;7988:45;;;;;;;;2429:25:25;;;7830:42:20;;-1:-1:-1;7954:31:20;;7988:25;:9;:25;;;;2402:18:25;;7988:45:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2197:2:7;8093:81:20;1507:6:16;8092:105:20;;-1:-1:-1;8606:46:20;;;8602:148;;;8677:73;;;;;979:5:13;8677:73:20;;;2429:25:25;2402:18;;8677:73:20;2283:177:25;8602:148:20;7816:945;7672:1095;;:::o;38845:7117::-;38941:4;;39029:48;39066:3;39049:20;;;2011:11:16;39048:28:20;39029:15;:48;:::i;:::-;39012:65;;39087:10;39107:11;39128;39154:9;39167:1;39154:14;39150:1349;;39375:30;;;;;;1133:4:16;39343:2:20;39326:19;;;39411:29;39374:67;;-1:-1:-1;2569:3:16;39672:18:20;39671:28;;39670:47;39654:12;:64;39653:156;;;-1:-1:-1;2569:3:16;39762:18:20;39761:28;;39760:47;39744:12;:64;39653:156;39628:302;;;39857:54;;;;;4719:5:13;39857:54:20;;;2429:25:25;2402:18;;39857:54:20;2283:177:25;39628:302:20;40051:30;;;;;;1133:4:16;40020:1:20;40003:18;;;40087:29;40050:67;;-1:-1:-1;40132:33:20;40050:67;40155:9;40132:15;:33::i;:::-;-1:-1:-1;40484:2:20;40424:56;:9;40446:2;40450:1;998:5:2;40424:21:20;:56::i;:::-;:62;;40321:13;40337:66;40321:82;40320:167;40312:176;;;;;;;;39150:1349;40532:3;40515:13;:20;;40539:1;40514:26;40545:1;40513:33;40509:5447;;40702:30;;;;;;1133:4:16;40669:2:20;40652:19;;;40738:29;40701:67;;-1:-1:-1;40783:33:20;40701:67;40806:9;40783:15;:33::i;:::-;-1:-1:-1;41179:15:20;41198:3;41179:22;41156:2;41093:59;:12;41118:2;41122:1;998:5:2;41093:24:20;:59::i;:::-;:65;;41070:2;41010:56;:9;41032:2;41036:1;998:5:2;41010:21:20;:56::i;:::-;40868:66;40852:82;;40955:34;;;;;;40851:139;41010:62;;40851:222;:308;:351;;-1:-1:-1;40843:360:20;;-1:-1:-1;;;;40843:360:20;40509:5447;41380:30;;;;;;;1133:4:16;41349:1:20;41332:18;;;41416:29;;41379:67;;;;;-1:-1:-1;41556:31:20;;;;;;;41523:2;41506:19;;;41593:30;;;41555:69;;-1:-1:-1;41639:14:20;41656:34;41555:69;41680:9;41656:15;:34::i;:::-;41639:51;;41850:6;2730:4:16;41822:5:20;:24;41821:35;;;;;:::i;:::-;;2730:4:16;41793:64:20;41780:77;;42067:1;42054:10;:14;42050:300;;;42147:1;2789:8:16;1730;42109:10:20;42108:11;;42103:23;42102:40;;;;;:::i;:::-;;42101:47;;42092:56;;42050:300;;;42325:1;2789:8:16;1730;42282:22:20;;42281:39;42280:46;;42330:1;42279:52;42270:61;;42050:300;1730:8:16;42382:9:20;:15;42378:237;;;1730:8:16;42585:15:20;;42378:237;42693:3;42676:20;;;1730:8:16;42675:28:20;;-1:-1:-1;42759:3:20;42742:20;;;1215:3:16;42741:27:20;42819:3;42802:20;;;1551:6:16;42801:28:20;1378:5:16;42847:10:20;;42843:2404;;;42881:19;;42877:1628;;43102:2;43092:12;;;;43118:1;43109:10;;;43091:29;;43198:17;;;:::i;:::-;;-1:-1:-1;43198:22:20;:17;43218:2;43198:22;:::i;:::-;43164:19;;;;:7;:19;;;;;;;43187:34;;;;43164:58;;;43142:80;;43248:19;;43244:466;;43295:17;;;:::i;:::-;;;42843:2404;;43244:466;43493:1;43475:19;;43592:20;43574:10;43587:1;43574:14;43573:39;;;;;:::i;:::-;;43686:1;43664:19;;;:7;:19;;;;;:23;43573:39;-1:-1:-1;42843:2404:20;;42877:1628;44076:19;;;;:7;:19;;;;;;;;;;44031:1;44021:11;;;;44076:28;;;44054:50;;44076:7;-1:-1:-1;44289:20:20;-1:-1:-1;44271:14:20;;44289:20;44270:39;;;;:::i;:::-;;44441:19;;;;:7;:19;;;;;44473:12;44463:23;;;44441:45;;44270:39;-1:-1:-1;42843:2404:20;;;44568:5;44563:1;44553:6;:11;;44552:21;44543:30;;44645:1;44627:15;:19;44623:249;;;44696:19;;;;:7;44748:2;44696:19;;;;;;;;;44730:20;;;44719:32;;;44696:56;;;44674:78;;44623:249;;;44807:19;;;;:7;:19;;;;;44841:6;44829:20;;;44807:42;;44623:249;44911:19;;44907:326;;44954:17;;;:::i;44907:326::-;45036:1;45018:19;;45127:20;45109:10;45122:1;45109:14;45108:39;;;;;:::i;:::-;;45213:1;45191:19;;;:7;:19;;;;;:23;45108:39;-1:-1:-1;44907:326:20;45358:9;;-1:-1:-1;45390:12:20;;-1:-1:-1;45425:13:20;;-1:-1:-1;45940:3:20;45926:17;;;45902:3;45883:22;;;45859:3;45846:16;;;45803:15;45822:3;45803:22;45780:2;45723:53;45390:12;45742:2;45746:1;998:5:2;45723:18:20;:53::i;:::-;:59;;45700:2;45644:52;:5;45662:2;45666:1;998:5:2;45644:17:20;:52::i;:::-;:58;;45622:1;2060:12:16;45608:2:20;45598:6;:12;;45597:20;45596:27;;45500:6;45509:66;45500:75;45499:125;:204;:284;:327;:364;:407;:445;45491:454;;;;;;;;;38845:7117;;;;;;:::o;23991:2027::-;24132:8;;;25625:9;25631:3;25625;:9;:::i;:::-;25614:20;-1:-1:-1;25644:8:20;25687:7;25614:20;25687:1;:7;:::i;:::-;25671:10;:3;25677:4;25671:10;:::i;:::-;25657:9;25663:3;25657;:9;:::i;:::-;25656:26;;;;:::i;:::-;25655:40;;;;:::i;:::-;25644:51;-1:-1:-1;25705:8:20;25716:9;25722:3;25716;:9;:::i;:::-;25705:20;;25780:4;25774:3;:10;25773:56;;25812:9;25818:3;25812;:9;:::i;:::-;25811:18;;25825:4;25811:18;:::i;:::-;25773:56;;;25804:3;25790:10;:3;25796:4;25790:10;:::i;:::-;25789:18;;;;:::i;:::-;25767:62;-1:-1:-1;25934:43:20;25965:9;25971:3;;25965:9;:::i;25934:43::-;25928:49;;:3;:49;:::i;:::-;25922:55;-1:-1:-1;26007:4:20;25994:9;26000:3;25922:55;25994:9;:::i;:::-;25993:18;;;;:::i;:::-;25987:24;;24152:1866;;;23991:2027;;;;;;;:::o;548:1201:1:-;628:17;889;920:6;930:4;920:14;916:767;;965:1;950:17;;;;;916:767;998:4;988:6;:14;984:699;;1025:74;;1042:12;1025:74;;;17917:28:25;1056:12:1;17961:11:25;;;17954:36;18040:66;18027:2;18023:15;;;18019:88;18006:11;;;17999:109;18146:3;18142:16;;;17842:66;18138:25;18124:12;;;18117:47;18180:12;;1025:74:1;;;;;;;;;;;;;1018:81;;984:699;;;1130:4;1120:6;:14;1116:567;;1157:88;;1174:12;1157:88;;;18519:28:25;1188:12:1;18563:11:25;;;18556:36;18642:66;18629:2;18625:15;;;18621:88;18608:11;;;18601:109;1217:12:1;18726::25;;;18719:37;18794:3;18790:16;;;18444:66;18786:25;18772:12;;;18765:47;18828:12;;1157:88:1;18203:643:25;1116:567:1;1276:6;1266;:16;1262:421;;1305:89;;1322:12;1305:89;;;19169:28:25;1336:12:1;19213:11:25;;;19206:36;19292:66;19279:2;19275:15;;;19271:88;19258:11;;;19251:109;1365:12:1;19376::25;;;19369:37;19458:66;19444:3;19440:16;;;19436:89;19422:12;;;19415:111;19542:12;;1305:89:1;18851:709:25;1262:421:1;1425:8;1415:6;:18;1411:272;;1456:89;;1473:12;1456:89;;;19883:28:25;1487:12:1;19927:11:25;;;19920:36;20006:66;19993:2;19989:15;;;19985:88;19972:11;;;19965:109;1516:12:1;20090::25;;;20083:37;20172:66;20158:3;20154:16;;;20150:89;20136:12;;;20129:111;20256:12;;1456:89:1;19565:709:25;1411:272:1;1583:89;;1600:12;1583:89;;;20597:28:25;1614:12:1;20641:11:25;;;20634:36;20720:66;20707:2;20703:15;;;20699:88;20686:11;;;20679:109;1643:12:1;20804::25;;;20797:37;20886:66;20872:3;20868:16;;;20864:89;20850:12;;;20843:111;20970:12;;1583:89:1;;;;;;;;;;;;1576:96;;1411:272;1724:15;;;;;;;;-1:-1:-1;548:1201:1;;;;;:::o;14087:387:20:-;14321:90;;;;;3737:25:25;;;3778:18;;;3771:34;;;14172:20:20;;14251:178;;14279:20;;14344:35;;3710:18:25;;14321:90:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14251:6;:178::i;:::-;14223:244;;;;;;;;;;;;:::i;11208:574::-;11486:221;;;;;21195:25:25;;;21236:18;;;21229:34;;;21279:18;;;21272:34;;;11341:4:20;;;;;;11416:309;;11444:20;;11534:37;;21168:18:25;;11486:221:20;20993:319:25;11416:309:20;11388:387;;;;;;;;;;;;:::i;:::-;11369:406;;;;;;11208:574;;;;;;;:::o;12342:598::-;12632:233;;;;;21195:25:25;;;21236:18;;;21229:34;;;21279:18;;;21272:34;;;12487:4:20;;;;;;12562:321;;12590:20;;12680:41;;21168:18:25;;12632:233:20;20993:319:25;5746:3396:24;5976:3;5890:1;6425:37;6419:44;;6409:136;;6525:2;6521:10;;;;;6492:3;6488:11;6409:136;6574:21;6571:1;6568:28;6558:119;;6657:2;6653:10;;;;;6625:2;6621:10;6558:119;6706:13;6703:1;6700:20;6690:111;;6781:2;6777:10;;;;;6749:2;6745:10;6690:111;6830:9;6827:1;6824:16;6814:106;;6901:1;6897:9;;;;;6869:2;6865:10;6814:106;8137:5;8130:13;8123:21;8119:2;8115:30;8325:9;;;8318:17;8315:1;8311:25;;;8368:9;;;8361:17;8354:25;;8411:9;;;8404:17;8397:25;;8454:9;;;8447:17;8440:25;;8497:9;;;8490:17;8483:25;;8540:9;;;8533:17;8526:25;;8583:9;;;8576:17;8569:25;;9112:9;;;;9109:16;-1:-1:-1;9102:24:24;;;5746:3396::o;2065:10605:6:-;1457:18;2422:2:7;2308:89:6;;;2307:109;;;2501:3:7;2462:89:6;;;2461:109;2585:25;;;:54;;-1:-1:-1;2614:25:6;;2585:54;2581:162;;;2662:70;;;;;395:5:5;2662:70:6;;;2429:25:25;2402:18;;2662:70:6;2283:177:25;2581:162:6;1273:6;2769:30;;2343:2:7;2987:82:6;;;1408:11;2986:90;2951:15;:126;;;;2643:3:7;3116:80:6;;;1229:6;3115:104;;3237:28;;:42;;-1:-1:-1;3269:10:6;;3237:42;:63;;;;3283:12;3299:1;3283:17;3237:63;3233:377;;;3544:51;;;2065:10605;;;:::o;3233:377::-;3990:32;3915:28;;;:54;;3914:109;3874:149;;;;1229:6;2572:3:7;6250:24:6;:80;;6249:88;6241:96;;6356:5;6365:1;6356:10;6352:283;;6569:51;;;2065:10605;;;:::o;6352:283::-;6780:5;6788:1;6780:9;6793:1;6780:14;6776:2287;;6930:1;6921:10;;;;;;7586:20;6921:10;7585:30;;;;:::i;:::-;;;-1:-1:-1;1090:3:6;2197:2:7;7851:79:6;;;1185:6;7850:87;7966:4;:12;;7849:130;7848:244;7755:337;;6776:2287;;;8341:1;8332:10;;;;;8936:29;2197:2:7;8700:79:6;;;1185:6;8699:87;1090:3;8889:21;;8667:244;:4;:244;8666:300;8566:400;;6776:2287;9303:12;9318:1;9303:16;9323:1;9303:21;9299:1880;;9474:1;9458:17;1090:3;10238:28;;10229:4;10214:19;;10238:28;10213:54;;;;:::i;:::-;;10198:69;;9299:1880;;;10552:1;10536:17;1090:3;10830:28;;10821:4;10806:19;;10830:28;10805:54;;;;:::i;:::-;;10797:4;:63;10781:80;;9299:1880;11439:4;11399:36;;;1090:3;11399:36;1273:6;11979:30;;11398:45;;;11978:71;2128:2:7;12107:71:6;;;1185:6;12106:79;1090:3;12089:97;11978:209;;-1:-1:-1;12470:64:6;12395:28;;;:54;;12394:141;12369:167;;;;2832:9832;;2224:10446;2065:10605;;;:::o;38011:828:20:-;38091:14;38305:9;38273:28;2730:4:16;38273:9:20;:28;:::i;:::-;38272:42;;;;:::i;:::-;38244:71;;2730:4:16;38244:71:20;:::i;:::-;38231:84;;2789:8:16;38355:10:20;:30;38354:69;;;-1:-1:-1;38404:18:20;38391:31;;38354:69;38350:473;;;38751:57;;;;;3643:5:13;38751:57:20;;;2429:25:25;2402:18;;38751:57:20;2283:177:25;2369:2808:2;2528:17;2580:12;2620:6;2654:34;2645:7;2642:47;2639:145;;;2723:4;;-1:-1:-1;2719:18:2;;2639:145;2812:18;2803:7;2800:31;2797:144;;;2865:4;2908:19;;;;2861:18;2797:144;2969:10;2960:7;2957:23;2954:136;;;3014:4;3057:19;;;;3010:18;2954:136;3118:6;3109:7;3106:19;3103:132;;;3159:4;3202:19;;;;3155:18;3103:132;3263:4;3254:7;3251:17;3248:128;;;3302:3;3344:18;;;;3298:17;3248:128;3404:3;3395:7;3392:16;3389:127;;;3442:3;3484:18;;;;3438:17;3389:127;3544:3;3535:7;3532:16;3529:127;;;3582:3;3624:18;;;;3578:17;3529:127;3684:3;3675:7;3672:16;3669:80;;;3733:1;3723:8;3719:16;3707:28;;3669:80;3765:14;;3762:78;;3824:1;3814:8;3810:16;3798:28;;3762:78;;3869:15;3859:8;3856:29;3853:131;;;-1:-1:-1;3955:15:2;3853:131;4027:15;4017:8;4013:30;3997:46;;4089:6;4079:8;4075:21;4138:1;4128:8;4125:15;4116:7;4112:29;4109:670;;;4319:1;4306:11;4302:19;4287:34;;4369:11;4365:1;4348:15;4344:23;4341:40;4338:427;;-1:-1:-1;4696:1:2;4731:16;;;;4671:23;;;4667:31;4338:427;4833:1;4819:12;4815:20;4805:8;4802:34;4792:263;;5039:1;5036;5029:12;4792:263;5081:30;;;5137:24;;;;;-1:-1:-1;;;;2369:2808:2:o;14:454:25:-;109:6;117;125;133;141;194:3;182:9;173:7;169:23;165:33;162:53;;;211:1;208;201:12;162:53;-1:-1:-1;;234:23:25;;;304:2;289:18;;276:32;;-1:-1:-1;355:2:25;340:18;;327:32;;406:2;391:18;;378:32;;-1:-1:-1;457:3:25;442:19;429:33;;-1:-1:-1;14:454:25;-1:-1:-1;14:454:25:o;855:262::-;1049:3;1034:19;;1062:49;1038:9;1093:6;557:5;551:12;546:3;539:25;613:4;606:5;602:16;596:23;589:4;584:3;580:14;573:47;669:4;662:5;658:16;652:23;645:4;640:3;636:14;629:47;725:4;718:5;714:16;708:23;701:4;696:3;692:14;685:47;781:4;774:5;770:16;764:23;757:4;752:3;748:14;741:47;837:4;830:5;826:16;820:23;813:4;808:3;804:14;797:47;;;473:377;1394:268;1202:12;;1190:25;;1264:4;1253:16;;;1247:23;1231:14;;;1224:47;1320:4;1309:16;;;1303:23;1287:14;;;1280:47;1376:4;1365:16;;;1359:23;1343:14;;;1336:47;1592:3;1577:19;;1605:51;1122:267;1667:154;1753:42;1746:5;1742:54;1735:5;1732:65;1722:93;;1811:1;1808;1801:12;1722:93;1667:154;:::o;1826:452::-;1912:6;1920;1928;1936;1989:3;1977:9;1968:7;1964:23;1960:33;1957:53;;;2006:1;2003;1996:12;1957:53;2042:9;2029:23;2019:33;;2099:2;2088:9;2084:18;2071:32;2061:42;;2150:2;2139:9;2135:18;2122:32;2112:42;;2204:2;2193:9;2189:18;2176:32;2217:31;2242:5;2217:31;:::i;:::-;1826:452;;;;-1:-1:-1;1826:452:25;;-1:-1:-1;;1826:452:25:o;2465:118::-;2551:5;2544:13;2537:21;2530:5;2527:32;2517:60;;2573:1;2570;2563:12;2588:519;2671:6;2679;2687;2695;2748:3;2736:9;2727:7;2723:23;2719:33;2716:53;;;2765:1;2762;2755:12;2716:53;2804:9;2791:23;2823:28;2845:5;2823:28;:::i;:::-;2870:5;-1:-1:-1;2922:2:25;2907:18;;2894:32;;-1:-1:-1;2973:2:25;2958:18;;2945:32;;-1:-1:-1;3029:2:25;3014:18;;3001:32;3042:33;3001:32;3042:33;:::i;3112:446::-;3195:6;3203;3211;3219;3272:3;3260:9;3251:7;3247:23;3243:33;3240:53;;;3289:1;3286;3279:12;3240:53;3325:9;3312:23;3302:33;;3382:2;3371:9;3367:18;3354:32;3344:42;;3433:2;3422:9;3418:18;3405:32;3395:42;;3487:2;3476:9;3472:18;3459:32;3500:28;3522:5;3500:28;:::i;4097:794::-;4185:6;4193;4201;4209;4262:2;4250:9;4241:7;4237:23;4233:32;4230:52;;;4278:1;4275;4268:12;4230:52;4317:9;4304:23;4336:31;4361:5;4336:31;:::i;:::-;4386:5;-1:-1:-1;4438:2:25;4423:18;;4410:32;;-1:-1:-1;4493:2:25;4478:18;;4465:32;4516:18;4546:14;;;4543:34;;;4573:1;4570;4563:12;4543:34;4611:6;4600:9;4596:22;4586:32;;4656:7;4649:4;4645:2;4641:13;4637:27;4627:55;;4678:1;4675;4668:12;4627:55;4718:2;4705:16;4744:2;4736:6;4733:14;4730:34;;;4760:1;4757;4750:12;4730:34;4805:7;4800:2;4791:6;4787:2;4783:15;4779:24;4776:37;4773:57;;;4826:1;4823;4816:12;4773:57;4097:794;;;;-1:-1:-1;;4857:2:25;4849:11;;-1:-1:-1;;;4097:794:25:o;4896:180::-;4955:6;5008:2;4996:9;4987:7;4983:23;4979:32;4976:52;;;5024:1;5021;5014:12;4976:52;-1:-1:-1;5047:23:25;;4896:180;-1:-1:-1;4896:180:25:o;5648:1616::-;5875:13;;5857:32;;5936:4;5924:17;;;5918:24;5844:3;5829:19;;;5951:54;;5984:20;;5918:24;5158:42;5147:54;5135:67;;5081:127;5951:54;;6054:4;6046:6;6042:17;6036:24;6069:56;6119:4;6108:9;6104:20;6088:14;5158:42;5147:54;5135:67;;5081:127;6069:56;;6174:4;6166:6;6162:17;6156:24;6189:71;6254:4;6243:9;6239:20;6223:14;5292:42;5373:2;5365:5;5359:12;5355:21;5350:3;5343:34;5438:2;5430:4;5423:5;5419:16;5413:23;5409:32;5402:4;5397:3;5393:14;5386:56;5503:2;5495:4;5488:5;5484:16;5478:23;5474:32;5467:4;5462:3;5458:14;5451:56;5568:2;5560:4;5553:5;5549:16;5543:23;5539:32;5532:4;5527:3;5523:14;5516:56;5633:2;5625:4;5618:5;5614:16;5608:23;5604:32;5597:4;5592:3;5588:14;5581:56;;5213:430;;;6189:71;;6309:4;6301:6;6297:17;6291:24;6334:6;6349:54;6399:2;6388:9;6384:18;6368:14;5158:42;5147:54;5135:67;;5081:127;6349:54;6452:4;6444:6;6440:17;6434:24;6412:46;;6477:6;6492:54;6542:2;6531:9;6527:18;6511:14;5158:42;5147:54;5135:67;;5081:127;6492:54;6595:4;6587:6;6583:17;6577:24;6555:46;;6620:6;6635:54;6685:2;6674:9;6670:18;6654:14;5158:42;5147:54;5135:67;;5081:127;6635:54;6726:4;6714:17;;6708:24;6751:6;6773:18;;;6766:30;;;;6821:15;;;6815:22;6856:6;6878:18;;;6871:30;;;;6926:15;;;6920:22;6961:6;6983:18;;;6976:30;;;;7052:15;;;7046:22;7037:6;7022:22;;7015:54;7115:15;;;7109:22;7100:6;7085:22;;7078:54;7178:15;;7172:22;7163:6;7148:22;;7141:54;7241:15;;;7235:22;7226:6;7211:22;;;7204:54;;;;5648:1616;;-1:-1:-1;5648:1616:25:o;7269:184::-;7321:77;7318:1;7311:88;7418:4;7415:1;7408:15;7442:4;7439:1;7432:15;7458:1174;7542:6;7573:2;7616;7604:9;7595:7;7591:23;7587:32;7584:52;;;7632:1;7629;7622:12;7584:52;7672:9;7659:23;7701:18;7742:2;7734:6;7731:14;7728:34;;;7758:1;7755;7748:12;7728:34;7796:6;7785:9;7781:22;7771:32;;7841:7;7834:4;7830:2;7826:13;7822:27;7812:55;;7863:1;7860;7853:12;7812:55;7899:2;7886:16;7921:2;7917;7914:10;7911:36;;;7927:18;;:::i;:::-;7973:2;7970:1;7966:10;8005:2;7999:9;8064:66;8059:2;8055;8051:11;8047:84;8039:6;8035:97;8182:6;8170:10;8167:22;8162:2;8150:10;8147:18;8144:46;8141:72;;;8193:18;;:::i;:::-;8229:2;8222:22;8279:18;;;8313:15;;;;-1:-1:-1;8355:11:25;;;8351:20;;;8383:19;;;8380:39;;;8415:1;8412;8405:12;8380:39;8439:11;;;;8459:142;8475:6;8470:3;8467:15;8459:142;;;8541:17;;8529:30;;8492:12;;;;8579;;;;8459:142;;8637:779;8903:2;8915:21;;;8985:13;;8888:18;;;9007:22;;;8855:4;;9082;;9060:2;9045:18;;;9109:15;;;8855:4;9152:195;9166:6;9163:1;9160:13;9152:195;;;9215:50;9261:3;9252:6;9246:13;557:5;551:12;546:3;539:25;613:4;606:5;602:16;596:23;589:4;584:3;580:14;573:47;669:4;662:5;658:16;652:23;645:4;640:3;636:14;629:47;725:4;718:5;714:16;708:23;701:4;696:3;692:14;685:47;781:4;774:5;770:16;764:23;757:4;752:3;748:14;741:47;837:4;830:5;826:16;820:23;813:4;808:3;804:14;797:47;;;473:377;9215:50;9294:4;9285:14;;;;;9322:15;;;;9188:1;9181:9;9152:195;;;-1:-1:-1;;;9383:18:25;;9376:34;;;;9364:3;8637:779;-1:-1:-1;;8637:779:25:o;9652:245::-;9719:6;9772:2;9760:9;9751:7;9747:23;9743:32;9740:52;;;9788:1;9785;9778:12;9740:52;9820:9;9814:16;9839:28;9861:5;9839:28;:::i;10234:184::-;10304:6;10357:2;10345:9;10336:7;10332:23;10328:32;10325:52;;;10373:1;10370;10363:12;10325:52;-1:-1:-1;10396:16:25;;10234:184;-1:-1:-1;10234:184:25:o;10423:245::-;10502:6;10510;10563:2;10551:9;10542:7;10538:23;10534:32;10531:52;;;10579:1;10576;10569:12;10531:52;-1:-1:-1;;10602:16:25;;10658:2;10643:18;;;10637:25;10602:16;;10637:25;;-1:-1:-1;10423:245:25:o;11468:458::-;11550:6;11558;11566;11619:2;11607:9;11598:7;11594:23;11590:32;11587:52;;;11635:1;11632;11625:12;11587:52;11671:9;11658:23;11648:33;;11731:2;11720:9;11716:18;11703:32;11744:28;11766:5;11744:28;:::i;:::-;11791:5;-1:-1:-1;11848:2:25;11833:18;;11820:32;11861:33;11820:32;11861:33;:::i;:::-;11913:7;11903:17;;;11468:458;;;;;:::o;12233:184::-;12285:77;12282:1;12275:88;12382:4;12379:1;12372:15;12406:4;12403:1;12396:15;12422:184;12474:77;12471:1;12464:88;12571:4;12568:1;12561:15;12595:4;12592:1;12585:15;12611:128;12678:9;;;12699:11;;;12696:37;;;12713:18;;:::i;12744:195::-;12783:3;12814:66;12807:5;12804:77;12801:103;;12884:18;;:::i;:::-;-1:-1:-1;12931:1:25;12920:13;;12744:195::o;12944:196::-;12983:3;13011:5;13001:39;;13020:18;;:::i;:::-;-1:-1:-1;13067:66:25;13056:78;;12944:196::o;13145:168::-;13218:9;;;13249;;13266:15;;;13260:22;;13246:37;13236:71;;13287:18;;:::i;13318:184::-;13370:77;13367:1;13360:88;13467:4;13464:1;13457:15;13491:4;13488:1;13481:15;13507:120;13547:1;13573;13563:35;;13578:18;;:::i;:::-;-1:-1:-1;13612:9:25;;13507:120::o;13632:125::-;13697:9;;;13718:10;;;13715:36;;;13731:18;;:::i;14145:191::-;14180:3;14211:66;14204:5;14201:77;14198:103;;14281:18;;:::i;:::-;-1:-1:-1;14321:1:25;14317:13;;14145:191::o;14341:1051::-;14587:4;14616:42;14697:2;14689:6;14685:15;14674:9;14667:34;14720:2;14758:6;14753:2;14742:9;14738:18;14731:34;14801:6;14796:2;14785:9;14781:18;14774:34;14856:2;14848:6;14844:15;14839:2;14828:9;14824:18;14817:43;14909:2;14901:6;14897:15;14891:3;14880:9;14876:19;14869:44;14950:3;14944;14933:9;14929:19;14922:32;14983:6;14977:13;14963:27;;15027:6;15021:3;15010:9;15006:19;14999:35;15052:1;15062:141;15076:6;15073:1;15070:13;15062:141;;;15172:14;;;15168:23;;15162:30;15137:17;;;15156:3;15133:27;15126:67;15091:10;;15062:141;;;15066:3;;15253:1;15247:3;15238:6;15227:9;15223:22;15219:32;15212:43;15382:3;15312:66;15307:2;15299:6;15295:15;15291:88;15280:9;15276:104;15272:114;15264:122;;;14341:1051;;;;;;;;;:::o;16034:200::-;16100:9;;;16073:4;16128:9;;16156:10;;16168:12;;;16152:29;16191:12;;;16183:21;;16149:56;16146:82;;;16208:18;;:::i;:::-;16146:82;16034:200;;;;:::o;16239:308::-;16278:1;16304;16294:35;;16309:18;;:::i;:::-;16426:66;16423:1;16420:73;16351:66;16348:1;16345:73;16341:153;16338:179;;;16497:18;;:::i;:::-;-1:-1:-1;16531:10:25;;16239:308::o;16552:292::-;16624:9;;;16591:7;16649:9;;16666:66;16660:73;;16645:89;16642:115;;;16737:18;;:::i;:::-;16810:1;16801:7;16796:16;16793:1;16790:23;16786:1;16779:9;16776:38;16766:72;;16818:18;;:::i;16849:216::-;16913:9;;;16941:11;;;16888:3;16971:9;;16999:10;;16995:19;;17024:10;;17016:19;;16992:44;16989:70;;;17039:18;;:::i;21317:306::-;21405:6;21413;21421;21474:2;21462:9;21453:7;21449:23;21445:32;21442:52;;;21490:1;21487;21480:12;21442:52;21519:9;21513:16;21503:26;;21569:2;21558:9;21554:18;21548:25;21538:35;;21613:2;21602:9;21598:18;21592:25;21582:35;;21317:306;;;;;:::o","linkReferences":{},"cborAuxdata":{"1":{"value":"0xa2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","offset":21723}},"immutableReferences":{"9244":[{"start":985,"length":32},{"start":3371,"length":32}],"9247":[{"start":3515,"length":32},{"start":7038,"length":32},{"start":7187,"length":32},{"start":14484,"length":32}],"9250":[{"start":3555,"length":32},{"start":6998,"length":32},{"start":7227,"length":32},{"start":14524,"length":32}],"9254":[{"start":1786,"length":32},{"start":7107,"length":32},{"start":9163,"length":32},{"start":9250,"length":32},{"start":9684,"length":32},{"start":9768,"length":32},{"start":13271,"length":32}],"9256":[{"start":1821,"length":32},{"start":7074,"length":32},{"start":9199,"length":32},{"start":9286,"length":32},{"start":9717,"length":32},{"start":9801,"length":32},{"start":13238,"length":32}],"9258":[{"start":1859,"length":32},{"start":7296,"length":32},{"start":9337,"length":32},{"start":9421,"length":32},{"start":9510,"length":32},{"start":9597,"length":32},{"start":13184,"length":32}],"9260":[{"start":1897,"length":32},{"start":7263,"length":32},{"start":9370,"length":32},{"start":9454,"length":32},{"start":9546,"length":32},{"start":9633,"length":32},{"start":13151,"length":32}],"9264":[{"start":2708,"length":32},{"start":3166,"length":32},{"start":3427,"length":32},{"start":10178,"length":32},{"start":10341,"length":32},{"start":12391,"length":32},{"start":12617,"length":32},{"start":12981,"length":32},{"start":14884,"length":32}],"9268":[{"start":1065,"length":32},{"start":1251,"length":32},{"start":3471,"length":32}],"9271":[{"start":3602,"length":32},{"start":17715,"length":32},{"start":17971,"length":32},{"start":18116,"length":32}],"9274":[{"start":1525,"length":32},{"start":3641,"length":32}],"9277":[{"start":2365,"length":32},{"start":3684,"length":32}],"9280":[{"start":1943,"length":32},{"start":3727,"length":32}],"9283":[{"start":2134,"length":32},{"start":2234,"length":32},{"start":3766,"length":32}],"9286":[{"start":3807,"length":32},{"start":11484,"length":32},{"start":14371,"length":32}],"9289":[{"start":3847,"length":32},{"start":10932,"length":32}],"9291":[{"start":3885,"length":32},{"start":6406,"length":32}],"9293":[{"start":3924,"length":32},{"start":10980,"length":32}],"9295":[{"start":3963,"length":32},{"start":6454,"length":32}],"9297":[{"start":4002,"length":32},{"start":10638,"length":32},{"start":12349,"length":32}],"9299":[{"start":4041,"length":32},{"start":10693,"length":32},{"start":12575,"length":32}],"9301":[{"start":4080,"length":32},{"start":4713,"length":32},{"start":4890,"length":32},{"start":15802,"length":32},{"start":15907,"length":32},{"start":16080,"length":32}]},"transformations":[{"id":"9244","type":"replace","offset":985,"reason":"immutable"},{"id":"9244","type":"replace","offset":3371,"reason":"immutable"},{"id":"9247","type":"replace","offset":3515,"reason":"immutable"},{"id":"9247","type":"replace","offset":7038,"reason":"immutable"},{"id":"9247","type":"replace","offset":7187,"reason":"immutable"},{"id":"9247","type":"replace","offset":14484,"reason":"immutable"},{"id":"9250","type":"replace","offset":3555,"reason":"immutable"},{"id":"9250","type":"replace","offset":6998,"reason":"immutable"},{"id":"9250","type":"replace","offset":7227,"reason":"immutable"},{"id":"9250","type":"replace","offset":14524,"reason":"immutable"},{"id":"9254","type":"replace","offset":1786,"reason":"immutable"},{"id":"9254","type":"replace","offset":7107,"reason":"immutable"},{"id":"9254","type":"replace","offset":9163,"reason":"immutable"},{"id":"9254","type":"replace","offset":9250,"reason":"immutable"},{"id":"9254","type":"replace","offset":9684,"reason":"immutable"},{"id":"9254","type":"replace","offset":9768,"reason":"immutable"},{"id":"9254","type":"replace","offset":13271,"reason":"immutable"},{"id":"9256","type":"replace","offset":1821,"reason":"immutable"},{"id":"9256","type":"replace","offset":7074,"reason":"immutable"},{"id":"9256","type":"replace","offset":9199,"reason":"immutable"},{"id":"9256","type":"replace","offset":9286,"reason":"immutable"},{"id":"9256","type":"replace","offset":9717,"reason":"immutable"},{"id":"9256","type":"replace","offset":9801,"reason":"immutable"},{"id":"9256","type":"replace","offset":13238,"reason":"immutable"},{"id":"9258","type":"replace","offset":1859,"reason":"immutable"},{"id":"9258","type":"replace","offset":7296,"reason":"immutable"},{"id":"9258","type":"replace","offset":9337,"reason":"immutable"},{"id":"9258","type":"replace","offset":9421,"reason":"immutable"},{"id":"9258","type":"replace","offset":9510,"reason":"immutable"},{"id":"9258","type":"replace","offset":9597,"reason":"immutable"},{"id":"9258","type":"replace","offset":13184,"reason":"immutable"},{"id":"9260","type":"replace","offset":1897,"reason":"immutable"},{"id":"9260","type":"replace","offset":7263,"reason":"immutable"},{"id":"9260","type":"replace","offset":9370,"reason":"immutable"},{"id":"9260","type":"replace","offset":9454,"reason":"immutable"},{"id":"9260","type":"replace","offset":9546,"reason":"immutable"},{"id":"9260","type":"replace","offset":9633,"reason":"immutable"},{"id":"9260","type":"replace","offset":13151,"reason":"immutable"},{"id":"9264","type":"replace","offset":2708,"reason":"immutable"},{"id":"9264","type":"replace","offset":3166,"reason":"immutable"},{"id":"9264","type":"replace","offset":3427,"reason":"immutable"},{"id":"9264","type":"replace","offset":10178,"reason":"immutable"},{"id":"9264","type":"replace","offset":10341,"reason":"immutable"},{"id":"9264","type":"replace","offset":12391,"reason":"immutable"},{"id":"9264","type":"replace","offset":12617,"reason":"immutable"},{"id":"9264","type":"replace","offset":12981,"reason":"immutable"},{"id":"9264","type":"replace","offset":14884,"reason":"immutable"},{"id":"9268","type":"replace","offset":1065,"reason":"immutable"},{"id":"9268","type":"replace","offset":1251,"reason":"immutable"},{"id":"9268","type":"replace","offset":3471,"reason":"immutable"},{"id":"9271","type":"replace","offset":3602,"reason":"immutable"},{"id":"9271","type":"replace","offset":17715,"reason":"immutable"},{"id":"9271","type":"replace","offset":17971,"reason":"immutable"},{"id":"9271","type":"replace","offset":18116,"reason":"immutable"},{"id":"9274","type":"replace","offset":1525,"reason":"immutable"},{"id":"9274","type":"replace","offset":3641,"reason":"immutable"},{"id":"9277","type":"replace","offset":2365,"reason":"immutable"},{"id":"9277","type":"replace","offset":3684,"reason":"immutable"},{"id":"9280","type":"replace","offset":1943,"reason":"immutable"},{"id":"9280","type":"replace","offset":3727,"reason":"immutable"},{"id":"9283","type":"replace","offset":2134,"reason":"immutable"},{"id":"9283","type":"replace","offset":2234,"reason":"immutable"},{"id":"9283","type":"replace","offset":3766,"reason":"immutable"},{"id":"9286","type":"replace","offset":3807,"reason":"immutable"},{"id":"9286","type":"replace","offset":11484,"reason":"immutable"},{"id":"9286","type":"replace","offset":14371,"reason":"immutable"},{"id":"9289","type":"replace","offset":3847,"reason":"immutable"},{"id":"9289","type":"replace","offset":10932,"reason":"immutable"},{"id":"9291","type":"replace","offset":3885,"reason":"immutable"},{"id":"9291","type":"replace","offset":6406,"reason":"immutable"},{"id":"9293","type":"replace","offset":3924,"reason":"immutable"},{"id":"9293","type":"replace","offset":10980,"reason":"immutable"},{"id":"9295","type":"replace","offset":3963,"reason":"immutable"},{"id":"9295","type":"replace","offset":6454,"reason":"immutable"},{"id":"9297","type":"replace","offset":4002,"reason":"immutable"},{"id":"9297","type":"replace","offset":10638,"reason":"immutable"},{"id":"9297","type":"replace","offset":12349,"reason":"immutable"},{"id":"9299","type":"replace","offset":4041,"reason":"immutable"},{"id":"9299","type":"replace","offset":10693,"reason":"immutable"},{"id":"9299","type":"replace","offset":12575,"reason":"immutable"},{"id":"9301","type":"replace","offset":4080,"reason":"immutable"},{"id":"9301","type":"replace","offset":4713,"reason":"immutable"},{"id":"9301","type":"replace","offset":4890,"reason":"immutable"},{"id":"9301","type":"replace","offset":15802,"reason":"immutable"},{"id":"9301","type":"replace","offset":15907,"reason":"immutable"},{"id":"9301","type":"replace","offset":16080,"reason":"immutable"}],"transformationValues":{"immutables":{"9244":"0x0000000000000000000000000000000000000000000000000000000000000001","9247":"0x0000000000000000000000005979d7b546e38e414f7e9822514be443a4800529","9250":"0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee","9254":"0x0000000000000000000000000000000000000000000000000000000000000001","9256":"0x00000000000000000000000000000000000000000000000000000000000f4240","9258":"0x0000000000000000000000000000000000000000000000000000000000000001","9260":"0x00000000000000000000000000000000000000000000000000000000000f4240","9264":"0x00000000000000000000000052aa899454998be5b000ad077a46bbe360f4e497","9268":"0x00000000000000000000000091716c4eda1fb55e84bf8b4c7085f84285c19085","9271":"0x0000000000000000000000001dab06729718f96c3478d2aacc49e117b6fdd7fd","9274":"0x00000000000000000000000020c86b8fc6ae133fe78560c1dedac286a1d83395","9277":"0x000000000000000000000000417082c6099338c1a04081ff290e8c64cb08e8e9","9280":"0x000000000000000000000000f3c087d5f40f97ba09b258732806aaa10304f168","9283":"0x000000000000000000000000f06bd1905b30ded5db229655ed3dd583705635b8","9286":"0x0000000000000000000000004ec7b668baf70d4a4b0fc7941a7708a07b6d45be","9289":"0x6131848091c3c7f98e5aef7805aa612f81b6052f1c3e3e495ef46d6dee38812f","9291":"0xf16c9d6e6c0fe5bb46fd8db51fd239511adb0187726196eb00a2e011dceca114","9293":"0x236696efd8534ce144b358082d303ba190cad0c8d37e9f4802b2a5198019379b","9295":"0xd943cec1dfc617bf9515058376abfab0217f98cce018735f02efd4abd3453ad8","9297":"0xf3dad1157554688b243cfc80212ae06c4bd92450ccab99da3bca5425bc6b716f","9299":"0xa1829a9003092132f585b6ccdd167c19fe9774dbdea4260287e8a8e8ca8185d7","9301":"0x0000000000000000000000000000000000000000000000000000000000004000"}}},"deployment":{"transactionHash":"0x7d7198b9af07566444ba8a13e655cf79a4052388de881e48203570f567648739","blockNumber":"285775309","transactionIndex":"2","deployer":"0x6da6b8F5c219BeEbF77A2B38dDB18B271F0d7a83"},"sources":{"contracts/infiniteProxy/interfaces/iProxy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IProxy {\n    function setAdmin(address newAdmin_) external;\n\n    function setDummyImplementation(address newDummyImplementation_) external;\n\n    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\n\n    function removeImplementation(address implementation_) external;\n\n    function getAdmin() external view returns (address);\n\n    function getDummyImplementation() external view returns (address);\n\n    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\n\n    function getSigsImplementation(bytes4 sig_) external view returns (address);\n\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"},"contracts/libraries/addressCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements calculation of address for contracts deployed through CREATE.\n/// Accepts contract deployed from which address & nonce\nlibrary AddressCalcs {\n\n    /// @notice                         Computes the address of a contract based\n    /// @param deployedFrom_            Address from which the contract was deployed\n    /// @param nonce_                   Nonce at which the contract was deployed\n    /// @return contract_               Address of deployed contract\n    function addressCalc(address deployedFrom_, uint nonce_) internal pure returns (address contract_) {\n        // @dev based on https://ethereum.stackexchange.com/a/61413\n\n        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment\n        // hence, nonce of vault deployment starts with 1.\n        bytes memory data;\n        if (nonce_ == 0x00) {\n            return address(0);\n        } else if (nonce_ <= 0x7f) {\n            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployedFrom_, uint8(nonce_));\n        } else if (nonce_ <= 0xff) {\n            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployedFrom_, bytes1(0x81), uint8(nonce_));\n        } else if (nonce_ <= 0xffff) {\n            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployedFrom_, bytes1(0x82), uint16(nonce_));\n        } else if (nonce_ <= 0xffffff) {\n            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployedFrom_, bytes1(0x83), uint24(nonce_));\n        } else {\n            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), deployedFrom_, bytes1(0x84), uint32(nonce_));\n        }\n\n        return address(uint160(uint256(keccak256(data))));\n    }\n\n}"},"contracts/libraries/bigMathMinified.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\n/// result in significant gas cost reduction due to storage space reduction.\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\nlibrary BigMathMinified {\n    /// @dev constants to use for `roundUp` input param to increase readability\n    bool internal constant ROUND_DOWN = false;\n    bool internal constant ROUND_UP = true;\n\n    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\n    /// e.g.:\n    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\n    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\n    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\n    ///                                                                        ^-------------------- 51(exponent) -------------- ^\n    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)\n    /// exponent =                                            0011,0011     (51)\n    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)\n    ///\n    /// @param normal number which needs to be converted into Big Number\n    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\n    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\n    /// @param roundUp signals if result should be rounded down or up\n    /// @return bigNumber converted bigNumber (coefficient << exponent)\n    function toBigNumber(\n        uint256 normal,\n        uint256 coefficientSize,\n        uint256 exponentSize,\n        bool roundUp\n    ) internal pure returns (uint256 bigNumber) {\n        assembly {\n            let lastBit_\n            let number_ := normal\n            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit_ := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit_ := add(lastBit_, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit_ := add(lastBit_, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit_ := add(lastBit_, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit_ := add(lastBit_, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit_ := add(lastBit_, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit_ := add(lastBit_, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if gt(number_, 0) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if lt(lastBit_, coefficientSize) {\n                // for throw exception\n                lastBit_ := coefficientSize\n            }\n            let exponent := sub(lastBit_, coefficientSize)\n            let coefficient := shr(exponent, normal)\n            if and(roundUp, gt(exponent, 0)) {\n                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\n                coefficient := add(coefficient, 1)\n                if eq(shl(coefficientSize, 1), coefficient) {\n                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\n                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\n                    coefficient := shl(sub(coefficientSize, 1), 1)\n                    exponent := add(exponent, 1)\n                }\n            }\n            if iszero(lt(exponent, shl(exponentSize, 1))) {\n                // if exponent is >= exponentSize, the normal number is too big to fit within\n                // BigNumber with too small sizes for coefficient and exponent\n                revert(0, 0)\n            }\n            bigNumber := shl(exponentSize, coefficient)\n            bigNumber := add(bigNumber, exponent)\n        }\n    }\n\n    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\n    function fromBigNumber(\n        uint256 bigNumber,\n        uint256 exponentSize,\n        uint256 exponentMask\n    ) internal pure returns (uint256 normal) {\n        assembly {\n            let coefficient := shr(exponentSize, bigNumber)\n            let exponent := and(bigNumber, exponentMask)\n            normal := shl(exponent, coefficient)\n        }\n    }\n\n    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\n    /// e.g.\n    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\n    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^\n    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\n        assembly {\n            let number_ := normal\n            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit := add(lastBit, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit := add(lastBit, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit := add(lastBit, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit := add(lastBit, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit := add(lastBit, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit := add(lastBit, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit := add(lastBit, 1)\n            }\n            if gt(number_, 0) {\n                lastBit := add(lastBit, 1)\n            }\n        }\n    }\n}\n"},"contracts/libraries/dexCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\nimport { DexSlotsLink } from \"./dexSlotsLink.sol\";\n\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n// @DEV ATTENTION: ON ANY CHANGES HERE, MAKE SURE THAT LOGIC IN VAULTS WILL STILL BE VALID.\n// SOME CODE THERE ASSUMES DEXCALCS == LIQUIDITYCALCS.\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n/// @notice implements calculation methods used for Fluid Dex such as updated withdrawal / borrow limits.\nlibrary DexCalcs {\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) &\n            X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ = block.timestamp - ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ = block.timestamp - ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n}\n"},"contracts/libraries/dexSlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Dex.\n/// @dev as all data for Fluid Dex is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidDexResolver.\nlibrary DexSlotsLink {\n    /// @dev storage slot for variables at Dex\n    uint256 internal constant DEX_VARIABLES_SLOT = 0;\n    /// @dev storage slot for variables2 at Dex\n    uint256 internal constant DEX_VARIABLES2_SLOT = 1;\n    /// @dev storage slot for total supply shares at Dex\n    uint256 internal constant DEX_TOTAL_SUPPLY_SHARES_SLOT = 2;\n    /// @dev storage slot for user supply mapping at Dex\n    uint256 internal constant DEX_USER_SUPPLY_MAPPING_SLOT = 3;\n    /// @dev storage slot for total borrow shares at Dex\n    uint256 internal constant DEX_TOTAL_BORROW_SHARES_SLOT = 4;\n    /// @dev storage slot for user borrow mapping at Dex\n    uint256 internal constant DEX_USER_BORROW_MAPPING_SLOT = 5;\n    /// @dev storage slot for oracle mapping at Dex\n    uint256 internal constant DEX_ORACLE_MAPPING_SLOT = 6;\n    /// @dev storage slot for range and threshold shifts at Dex\n    uint256 internal constant DEX_RANGE_THRESHOLD_SHIFTS_SLOT = 7;\n    /// @dev storage slot for center price shift at Dex\n    uint256 internal constant DEX_CENTER_PRICE_SHIFT_SLOT = 8;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_ALLOWED = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_ALLOWED = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Dex contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Dex contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n"},"contracts/libraries/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary LibsErrorTypes {\n    /***********************************|\n    |         LiquidityCalcs            | \n    |__________________________________*/\n\n    /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet)\n    uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001;\n\n    /// @notice thrown when rate data is set to a version that is not implemented\n    uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002;\n\n    /// @notice thrown when the calculated borrow rate turns negative. This should never happen.\n    uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003;\n\n    /***********************************|\n    |           SafeTransfer            | \n    |__________________________________*/\n\n    /// @notice thrown when safe transfer from for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFromFailed = 71001;\n\n    /// @notice thrown when safe transfer for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFailed = 71002;\n\n    /***********************************|\n    |           SafeApprove             | \n    |__________________________________*/\n\n    /// @notice thrown when safe approve from for an ERC20 fails\n    uint256 internal constant SafeApprove__ApproveFailed = 81001;\n}\n"},"contracts/libraries/liquidityCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\nimport { LiquiditySlotsLink } from \"./liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\n\n/// @notice implements calculation methods used for Fluid liquidity such as updated exchange prices,\n/// borrow rate, withdrawal / borrow limits, revenue amount.\nlibrary LiquidityCalcs {\n    error FluidLiquidityCalcsError(uint256 errorId_);\n\n    /// @notice emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\n    event BorrowRateMaxCap();\n\n    /// @dev constants as from Liquidity variables.sol\n    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n    /// @dev Ignoring leap years\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant TWELVE_DECIMALS = 1e12;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X15 = 0x7fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                  CALC EXCHANGE PRICES                  /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @return supplyExchangePrice_ updated supplyExchangePrice\n    /// @return borrowExchangePrice_ updated borrowExchangePrice\n    function calcExchangePrices(\n        uint256 exchangePricesAndConfig_\n    ) internal view returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\n        // Extracting exchange prices\n        supplyExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\n            X64;\n        borrowExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\n            X64;\n\n        if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\n        }\n\n        uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\n\n        unchecked {\n            // last timestamp can not be > current timestamp\n            uint256 secondsSinceLastUpdate_ = block.timestamp -\n                ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\n\n            uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\n                X15;\n            if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\n                // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\n                // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // calculate new borrow exchange price.\n            // formula borrowExchangePriceIncrease: previous price * borrow rate * secondsSinceLastUpdate_.\n            // nominator is max uint112 (uint64 * uint16 * uint32). Divisor can not be 0.\n            borrowExchangePrice_ +=\n                (borrowExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS);\n\n            // FOR SUPPLY EXCHANGE PRICE:\n            // all yield paid by borrowers (in mode with interest) goes to suppliers in mode with interest.\n            // formula: previous price * supply rate * secondsSinceLastUpdate_.\n            // where supply rate = (borrow rate  - revenueFee%) * ratioSupplyYield. And\n            // ratioSupplyYield = utilization * supplyRatio * borrowRatio\n            //\n            // Example:\n            // supplyRawInterest is 80, supplyInterestFree is 20. totalSupply is 100. BorrowedRawInterest is 50.\n            // BorrowInterestFree is 10. TotalBorrow is 60. borrow rate 40%, revenueFee 10%.\n            // yield is 10 (so half a year must have passed).\n            // supplyRawInterest must become worth 89. totalSupply must become 109. BorrowedRawInterest must become 60.\n            // borrowInterestFree must still be 10. supplyInterestFree still 20. totalBorrow 70.\n            // supplyExchangePrice would have to go from 1 to 1,125 (+ 0.125). borrowExchangePrice from 1 to 1,2 (+0.2).\n            // utilization is 60%. supplyRatio = 20 / 80 = 25% (only 80% of lenders receiving yield).\n            // borrowRatio = 10 / 50 = 20% (only 83,333% of borrowers paying yield):\n            // x of borrowers paying yield = 100% - (20 / (100 + 20)) = 100% - 16.6666666% = 83,333%.\n            // ratioSupplyYield = 60% * 83,33333% * (100% + 20%) = 62,5%\n            // supplyRate = (40% * (100% - 10%)) * = 36% * 62,5% = 22.5%\n            // increase in supplyExchangePrice, assuming 100 as previous price.\n            // 100 * 22,5% * 1/2 (half a year) = 0,1125.\n            // cross-check supplyRawInterest worth = 80 * 1.1125 = 89. totalSupply worth = 89 + 20.\n\n            // -------------- 1. calculate ratioSupplyYield --------------------------------\n            // step1: utilization * supplyRatio (or actually part of lenders receiving yield)\n\n            // temp_ => supplyRatio (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n            // if first bit 0 then ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n            // else ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n            temp_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) & X15;\n\n            if (temp_ == 1) {\n                // if no raw supply: no exchange price update needed\n                // (if supplyRatio_ == 1 means there is only supplyInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // ratioSupplyYield precision is 1e27 as 100% for increased precision when supplyInterestFree > supplyWithInterest\n            if (temp_ & 1 == 1) {\n                // ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n                temp_ = temp_ >> 1;\n\n                // Note: case where temp_ == 0 (only supplyInterestFree, no yield) already covered by early return\n                // in the if statement a little above.\n\n                // based on above example but supplyRawInterest is 20, supplyInterestFree is 80. no fee.\n                // supplyRawInterest must become worth 30. totalSupply must become 110.\n                // supplyExchangePrice would have to go from 1 to 1,5. borrowExchangePrice from 1 to 1,2.\n                // so ratioSupplyYield must come out as 2.5 (250%).\n                // supplyRatio would be (20 * 10_000 / 80) = 2500. but must be inverted.\n                temp_ = (1e27 * FOUR_DECIMALS) / temp_; // e.g. 1e31 / 2500 = 4e27. (* 1e27 for precision)\n                // e.g. 5_000 * (1e27 + 4e27) / 1e27 = 25_000 (=250%).\n                temp_ =\n                    // utilization * (100% + 100% / supplyRatio)\n                    (((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) *\n                        (1e27 + temp_)) / // extract utilization (max 16_383 so there is no way this can overflow).\n                    (FOUR_DECIMALS);\n                // max possible value of temp_ here is 16383 * (1e27 + 1e31) / 1e4 = ~1.64e31\n            } else {\n                // ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n                temp_ = temp_ >> 1;\n                // if temp_ == 0 then only supplyWithInterest => full yield. temp_ is already 0\n\n                // e.g. 5_000 * 10_000 + (20 * 10_000 / 80) / 10_000 = 5000 * 12500 / 10000 = 6250 (=62.5%).\n                temp_ =\n                    // 1e27 * utilization * (100% + supplyRatio) / 100%\n                    (1e27 *\n                        ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) * // extract utilization (max 16_383 so there is no way this can overflow).\n                        (FOUR_DECIMALS + temp_)) /\n                    (FOUR_DECIMALS * FOUR_DECIMALS);\n                // max possible temp_ value: 1e27 * 16383 * 2e4 / 1e8 = 3.2766e27\n            }\n            // from here temp_ => ratioSupplyYield (utilization * supplyRatio part) scaled by 1e27. max possible value ~1.64e31\n\n            // step2 of ratioSupplyYield: add borrowRatio (only x% of borrowers paying yield)\n            if (borrowRatio_ & 1 == 1) {\n                // ratio is borrowWithInterest / borrowInterestFree (borrowInterestFree is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n\n                // Note: case where borrowRatio_ == 0 (only borrowInterestFree, no yield) already covered\n                // at the beginning of the method by early return if `borrowRatio_ == 1`.\n\n                // based on above example but borrowRawInterest is 10, borrowInterestFree is 50. no fee. borrowRatio = 20%.\n                // so only 16.66% of borrowers are paying yield. so the 100% - part of the formula is not needed.\n                // x of borrowers paying yield = (borrowRatio / (100 + borrowRatio)) = 16.6666666%\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                borrowRatio_ = (borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_);\n                // max value here for borrowRatio_ is (1e31 / (1e4 + 1e4))= 5e26 (= 50% of borrowers paying yield).\n            } else {\n                // ratio is borrowInterestFree / borrowWithInterest (borrowWithInterest is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                // x of borrowers paying yield = 100% - (borrowRatio / (100 + borrowRatio)) = 100% - 16.6666666% = 83,333%.\n                borrowRatio_ = (1e27 - ((borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_)));\n                // borrowRatio can never be > 100%. so max subtraction can be 100% - 100% / 200%.\n                // or if borrowRatio_ is 0 -> 100% - 0. or if borrowRatio_ is 1 -> 100% - 1 / 101.\n                // max value here for borrowRatio_ is 1e27 - 0 = 1e27 (= 100% of borrowers paying yield).\n            }\n\n            // temp_ => ratioSupplyYield. scaled down from 1e25 = 1% each to normal percent precision 1e2 = 1%.\n            // max nominator value is ~1.64e31 * 1e27 = 1.64e58. max result = 1.64e8\n            temp_ = (FOUR_DECIMALS * temp_ * borrowRatio_) / 1e54;\n\n            // 2. calculate supply rate\n            // temp_ => supply rate (borrow rate  - revenueFee%) * ratioSupplyYield.\n            // division part is done in next step to increase precision. (divided by 2x FOUR_DECIMALS, fee + borrowRate)\n            // Note that all calculation divisions for supplyExchangePrice are rounded down.\n            // Note supply rate can be bigger than the borrowRate, e.g. if there are only few lenders with interest\n            // but more suppliers not earning interest.\n            temp_ = ((exchangePricesAndConfig_ & X16) * // borrow rate\n                temp_ * // ratioSupplyYield\n                (FOUR_DECIMALS - ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14))); // revenueFee\n            // fee can not be > 100%. max possible = 65535 * ~1.64e8 * 1e4 =~1.074774e17.\n\n            // 3. calculate increase in supply exchange price\n            supplyExchangePrice_ += ((supplyExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS * FOUR_DECIMALS * FOUR_DECIMALS));\n            // max possible nominator = max uint 64 * 1.074774e17 * max uint32 = ~8.52e45. Denominator can not be 0.\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                     CALC REVENUE                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from storage\n    /// and the current balance of the Fluid liquidity contract for the token.\n    /// @param totalAmounts_ total amounts packed uint256 read from storage\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @param liquidityTokenBalance_   current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\n    /// @return revenueAmount_ collectable revenue amount\n    function calcRevenue(\n        uint256 totalAmounts_,\n        uint256 exchangePricesAndConfig_,\n        uint256 liquidityTokenBalance_\n    ) internal view returns (uint256 revenueAmount_) {\n        // @dev no need to super-optimize this method as it is only used by admin\n\n        // calculate the new exchange prices based on earned interest\n        (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = calcExchangePrices(exchangePricesAndConfig_);\n\n        // total supply = interest free + with interest converted from raw\n        uint256 totalSupply_ = getTotalSupply(totalAmounts_, supplyExchangePrice_);\n\n        if (totalSupply_ > 0) {\n            // available revenue: balanceOf(token) + totalBorrowings - totalLendings.\n            revenueAmount_ = liquidityTokenBalance_ + getTotalBorrow(totalAmounts_, borrowExchangePrice_);\n            // ensure there is no possible case because of rounding etc. where this would revert,\n            // explicitly check if >\n            revenueAmount_ = revenueAmount_ > totalSupply_ ? revenueAmount_ - totalSupply_ : 0;\n            // Note: if utilization > 100% (totalSupply < totalBorrow), then all the amount above 100% utilization\n            // can only be revenue.\n        } else {\n            // if supply is 0, then rest of balance can be withdrawn as revenue so that no amounts get stuck\n            revenueAmount_ = liquidityTokenBalance_;\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >>\n            LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) & X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ =\n                block.timestamp -\n                ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ =\n                block.timestamp -\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC RATES                        /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev Calculates new borrow rate from utilization for a token\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_ totalBorrow / totalSupply. 1e4 = 100% utilization\n    /// @return rate_ rate for that particular token in 1e2 precision (e.g. 5% rate = 500)\n    function calcBorrowRateFromUtilization(uint256 rateData_, uint256 utilization_) internal returns (uint256 rate_) {\n        // extract rate version: 4 bits (0xF) starting from bit 0\n        uint256 rateVersion_ = (rateData_ & 0xF);\n\n        if (rateVersion_ == 1) {\n            rate_ = calcRateV1(rateData_, utilization_);\n        } else if (rateVersion_ == 2) {\n            rate_ = calcRateV2(rateData_, utilization_);\n        } else {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__UnsupportedRateVersion);\n        }\n\n        if (rate_ > X16) {\n            // hard cap for borrow rate at maximum value 16 bits (65535) to make sure it does not overflow storage space.\n            // this is unlikely to ever happen if configs stay within expected levels.\n            rate_ = X16;\n            // emit event to more easily become aware\n            emit BorrowRateMaxCap();\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 1 (with one kink) in 1e2 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e2 precision\n    function calcRateV1(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v1 (one kink) ------------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 188 bits =>  68-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // else utilization is greater than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;\n            x1_ = kink1_;\n            x2_ = FOUR_DECIMALS; // 100%\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 2 (with two kinks) in 1e4 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e4 precision\n    function calcRateV2(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v2 (two kinks) -----------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 156 bits => 100-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink1\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // extract kink2: 16 bits (0xFFFF) starting from bit 52\n            uint256 kink2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;\n            if (utilization_ < kink2_) {\n                // if utilization is less than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                x1_ = kink1_;\n                x2_ = kink2_;\n            } else {\n                // else utilization is greater than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;\n                x1_ = kink2_;\n                x2_ = FOUR_DECIMALS;\n            }\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev reads the total supply out of Liquidity packed storage `totalAmounts_` for `supplyExchangePrice_`\n    function getTotalSupply(\n        uint256 totalAmounts_,\n        uint256 supplyExchangePrice_\n    ) internal pure returns (uint256 totalSupply_) {\n        // totalSupply_ => supplyInterestFree\n        totalSupply_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\n        totalSupply_ = (totalSupply_ >> DEFAULT_EXPONENT_SIZE) << (totalSupply_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalSupplyRaw_ = totalAmounts_ & X64; // no shifting as supplyRaw is first 64 bits\n        totalSupplyRaw_ = (totalSupplyRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalSupplyRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalSupply = supplyInterestFree + supplyRawInterest normalized from raw\n        totalSupply_ += ((totalSupplyRaw_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n\n    /// @dev reads the total borrow out of Liquidity packed storage `totalAmounts_` for `borrowExchangePrice_`\n    function getTotalBorrow(\n        uint256 totalAmounts_,\n        uint256 borrowExchangePrice_\n    ) internal pure returns (uint256 totalBorrow_) {\n        // totalBorrow_ => borrowInterestFree\n        // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\n        totalBorrow_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\n        totalBorrow_ = (totalBorrow_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrow_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalBorrowRaw_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\n        totalBorrowRaw_ = (totalBorrowRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrowRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalBorrow = borrowInterestFree + borrowRawInterest normalized from raw\n        totalBorrow_ += ((totalBorrowRaw_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n}\n"},"contracts/libraries/liquiditySlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\nlibrary LiquiditySlotsLink {\n    /// @dev storage slot for status at Liquidity\n    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\n    /// @dev storage slot for auths mapping at Liquidity\n    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\n    /// @dev storage slot for guardians mapping at Liquidity\n    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\n    /// @dev storage slot for user class mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\n    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\n    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\n    /// @dev storage slot for rateData mapping at Liquidity\n    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\n    /// @dev storage slot for totalAmounts mapping at Liquidity\n    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\n    /// @dev storage slot for user supply double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\n    /// @dev storage slot for user borrow double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // ExchangePricesAndConfig\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\n    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\n    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\n    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\n\n    // RateData:\n    uint256 internal constant BITS_RATE_DATA_VERSION = 0;\n    // RateData: V1\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\n    // RateData: V2\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\n\n    // TotalAmounts\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_MODE = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\n\n    // Configs2\n    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n"},"contracts/libraries/safeTransfer.sol":{"content":"// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\n\n/// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom\nlibrary SafeTransfer {\n    uint256 internal constant MAX_NATIVE_TRANSFER_GAS = 20000; // pass max. 20k gas for native transfers\n\n    error FluidSafeTransferError(uint256 errorId_);\n\n    /// @dev Transfer `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    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63\n    function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from_\" argument.\n            mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 68), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of `token_` to `to_`.\n    /// If `token_` returns no value, non-reverting calls are assumed to be successful.\n    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95\n    function safeTransfer(address token_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 36), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of ` native token to `to_`.\n    /// Minimally modified from Solmate SafeTransferLib (Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L15-L25\n    function safeTransferNative(address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and store if it succeeded or not. Pass limited gas\n            success_ := call(MAX_NATIVE_TRANSFER_GAS, to_, amount_, 0, 0, 0, 0)\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n}\n"},"contracts/libraries/storageRead.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.\ncontract StorageRead {\n    function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {\n        assembly {\n            result_ := sload(slot_) // read value from the storage slot\n        }\n    }\n}\n"},"contracts/liquidity/adminModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct AddressBool {\n        address addr;\n        bool value;\n    }\n\n    struct AddressUint256 {\n        address addr;\n        uint256 value;\n    }\n\n    /// @notice struct to set borrow rate data for version 1\n    struct RateDataV1Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\n        uint256 kink;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink;\n        ///\n        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set borrow rate data for version 2\n    struct RateDataV2Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\n        uint256 kink1;\n        ///\n        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\n        uint256 kink2;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink1;\n        ///\n        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\n        uint256 rateAtUtilizationKink2;\n        ///\n        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set token config\n    struct TokenConfig {\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\n        uint256 fee;\n        ///\n        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\n        uint256 threshold;\n        ///\n        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\n        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).\n        uint256 maxUtilization;\n    }\n\n    /// @notice struct to set user supply & withdrawal config\n    struct UserSupplyConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which withdrawal limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration withdrawal limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseWithdrawalLimit;\n    }\n\n    /// @notice struct to set user borrow & payback config\n    struct UserBorrowConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which debt limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration debt limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\n        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseDebtCeiling;\n        ///\n        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 maxDebtCeiling;\n    }\n}\n"},"contracts/liquidity/interfaces/iLiquidity.sol":{"content":"//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IProxy } from \"../../infiniteProxy/interfaces/iProxy.sol\";\nimport { Structs as AdminModuleStructs } from \"../adminModule/structs.sol\";\n\ninterface IFluidLiquidityAdmin {\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\n    /// @param authsStatus_ array of structs setting allowed status for an address.\n    ///                     status true => add auth, false => remove auth\n    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\n\n    /// @notice adds/removes guardians. Only callable by Governance.\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\n    ///                         status true => add guardian, false => remove guardian\n    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\n\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n    /// @param revenueCollector_  new revenue collector address\n    function updateRevenueCollector(address revenueCollector_) external;\n\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n    /// @param newStatus_ new status\n    ///        status = 2 -> pause, status = 1 -> resume.\n    function changeStatus(uint256 newStatus_) external;\n\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\n    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\n\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\n    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\n\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n    ///         Only callable by Auths.\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\n    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\n\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n    ///         Only callable by Auths.\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\n    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\n\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\n\n    /// @notice sets a new withdrawal limit as the current limit for a certain user\n    /// @param user_ user address for which to update the withdrawal limit\n    /// @param token_ token address for which to update the withdrawal limit\n    /// @param newLimit_ new limit until which user supply can decrease to.\n    ///                  Important: input in raw. Must account for exchange price in input param calculation.\n    ///                  Note any limit that is < max expansion or > current user supply will set max expansion limit or\n    ///                  current user supply as limit respectively.\n    ///                  - set 0 to make maximum possible withdrawable: instant full expansion, and if that goes\n    ///                  below base limit then fully down to 0.\n    ///                  - set type(uint256).max to make current withdrawable 0 (sets current user supply as limit).\n    function updateUserWithdrawalLimit(address user_, address token_, uint256 newLimit_) external;\n\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\n\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to pause operations for\n    /// @param supplyTokens_  token addresses to pause withdrawals for\n    /// @param borrowTokens_  token addresses to pause borrowings for\n    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to unpause operations for\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\n    /// @param borrowTokens_  token addresses to unpause borrowings for\n    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\n    /// @param tokens_  array of tokens to collect revenue for\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\n    function collectRevenue(address[] calldata tokens_) external;\n\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\n    /// @param tokens_ tokens to update exchange prices for\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\n    function updateExchangePrices(\n        address[] calldata tokens_\n    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\n}\n\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\n    /// @notice Single function which handles supply, withdraw, borrow & payback\n    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\n    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\n    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\n    /// @param withdrawTo_ if withdrawal then to which address\n    /// @param borrowTo_ if borrow then to which address\n    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\n    /// @return memVar3_ updated supplyExchangePrice\n    /// @return memVar4_ updated borrowExchangePrice\n    /// @dev to trigger skipping in / out transfers (gas optimization):\n    /// -  ` callbackData_` MUST be encoded so that \"from\" address is the last 20 bytes in the last 32 bytes slot,\n    ///     also for native token operations where liquidityCallback is not triggered!\n    ///     from address must come at last position if there is more data. I.e. encode like:\n    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\n    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\n    /// -   this \"from\" address must match withdrawTo_ or borrowTo_ and must be == `msg.sender`\n    /// -   `callbackData_` must in addition to the from address as described above include bytes32 SKIP_TRANSFERS\n    ///     in the slot before (bytes 32 to 63)\n    /// -   `msg.value` must be 0.\n    /// -   Amounts must be either:\n    ///     -  supply(+) == borrow(+), withdraw(-) == payback(-).\n    ///     -  Liquidity must be on the winning side (deposit < borrow OR payback < withdraw).\n    function operate(\n        address token_,\n        int256 supplyAmount_,\n        int256 borrowAmount_,\n        address withdrawTo_,\n        address borrowTo_,\n        bytes calldata callbackData_\n    ) external payable returns (uint256 memVar3_, uint256 memVar4_);\n}\n\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\n"},"contracts/protocols/dex/error.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs } from \"./poolT1/coreModule/structs.sol\";\n\nabstract contract Error {\n    error FluidDexError(uint256 errorId_);\n\n    error FluidDexFactoryError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares_);\n\n    error FluidDexPricesAndExchangeRates(Structs.PricesAndExchangePrice pex_);\n}\n"},"contracts/protocols/dex/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n    /***********************************|\n    |             DexT1                 | \n    |__________________________________*/\n\n    /// @notice thrown at reentrancy\n    uint256 internal constant DexT1__AlreadyEntered = 51001;\n\n    uint256 internal constant DexT1__NotAnAuth = 51002;\n\n    uint256 internal constant DexT1__SmartColNotEnabled = 51003;\n\n    uint256 internal constant DexT1__SmartDebtNotEnabled = 51004;\n\n    uint256 internal constant DexT1__PoolNotInitialized = 51005;\n\n    uint256 internal constant DexT1__TokenReservesTooLow = 51006;\n\n    uint256 internal constant DexT1__EthAndAmountInMisMatch = 51007;\n\n    uint256 internal constant DexT1__EthSentForNonNativeSwap = 51008;\n\n    uint256 internal constant DexT1__NoSwapRoute = 51009;\n\n    uint256 internal constant DexT1__NotEnoughAmountOut = 51010;\n\n    uint256 internal constant DexT1__LiquidityLayerTokenUtilizationCapReached = 51011;\n\n    uint256 internal constant DexT1__HookReturnedFalse = 51012;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserSupplyInNotOn = 51013;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserDebtInNotOn = 51014;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants to give on deposit\n    uint256 internal constant DexT1__AboveDepositMax = 51015;\n\n    uint256 internal constant DexT1__MsgValueLowOnDepositOrPayback = 51016;\n\n    uint256 internal constant DexT1__WithdrawLimitReached = 51017;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on withdraw\n    uint256 internal constant DexT1__BelowWithdrawMin = 51018;\n\n    uint256 internal constant DexT1__DebtLimitReached = 51019;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on borrow\n    uint256 internal constant DexT1__BelowBorrowMin = 51020;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants on payback\n    uint256 internal constant DexT1__AbovePaybackMax = 51021;\n\n    uint256 internal constant DexT1__InvalidDepositAmts = 51022;\n\n    uint256 internal constant DexT1__DepositAmtsZero = 51023;\n\n    uint256 internal constant DexT1__SharesMintedLess = 51024;\n\n    uint256 internal constant DexT1__WithdrawalNotEnough = 51025;\n\n    uint256 internal constant DexT1__InvalidWithdrawAmts = 51026;\n\n    uint256 internal constant DexT1__WithdrawAmtsZero = 51027;\n\n    uint256 internal constant DexT1__WithdrawExcessSharesBurn = 51028;\n\n    uint256 internal constant DexT1__InvalidBorrowAmts = 51029;\n\n    uint256 internal constant DexT1__BorrowAmtsZero = 51030;\n\n    uint256 internal constant DexT1__BorrowExcessSharesMinted = 51031;\n\n    uint256 internal constant DexT1__PaybackAmtTooHigh = 51032;\n\n    uint256 internal constant DexT1__InvalidPaybackAmts = 51033;\n\n    uint256 internal constant DexT1__PaybackAmtsZero = 51034;\n\n    uint256 internal constant DexT1__PaybackSharedBurnedLess = 51035;\n\n    uint256 internal constant DexT1__NothingToArbitrage = 51036;\n\n    uint256 internal constant DexT1__MsgSenderNotLiquidity = 51037;\n\n    // On liquidity callback reentrancy bit should be on\n    uint256 internal constant DexT1__ReentrancyBitShouldBeOn = 51038;\n\n    // Thrown is reentrancy is already on and someone tries to fetch oracle price. Should not be possible to this\n    uint256 internal constant DexT1__OraclePriceFetchAlreadyEntered = 51039;\n\n    // Thrown when swap changes the current price by more than 5%\n    uint256 internal constant DexT1__OracleUpdateHugeSwapDiff = 51040;\n\n    uint256 internal constant DexT1__Token0ShouldBeSmallerThanToken1 = 51041;\n\n    uint256 internal constant DexT1__OracleMappingOverflow = 51042;\n\n    /// @notice thrown if governance has paused the swapping & arbitrage so only perfect functions are usable\n    uint256 internal constant DexT1__SwapAndArbitragePaused = 51043;\n\n    uint256 internal constant DexT1__ExceedsAmountInMax = 51044;\n\n    /// @notice thrown if amount in is too high or too low\n    uint256 internal constant DexT1__SwapInLimitingAmounts = 51045;\n\n    /// @notice thrown if amount out is too high or too low\n    uint256 internal constant DexT1__SwapOutLimitingAmounts = 51046;\n\n    uint256 internal constant DexT1__MintAmtOverflow = 51047;\n\n    uint256 internal constant DexT1__BurnAmtOverflow = 51048;\n\n    uint256 internal constant DexT1__LimitingAmountsSwapAndNonPerfectActions = 51049;\n\n    uint256 internal constant DexT1__InsufficientOracleData = 51050;\n\n    uint256 internal constant DexT1__SharesAmountInsufficient = 51051;\n\n    uint256 internal constant DexT1__CenterPriceOutOfRange = 51052;\n\n    uint256 internal constant DexT1__DebtReservesTooLow = 51053;\n\n    uint256 internal constant DexT1__SwapAndDepositTooLowOrTooHigh = 51054;\n\n    uint256 internal constant DexT1__WithdrawAndSwapTooLowOrTooHigh = 51055;\n\n    uint256 internal constant DexT1__BorrowAndSwapTooLowOrTooHigh = 51056;\n\n    uint256 internal constant DexT1__SwapAndPaybackTooLowOrTooHigh = 51057;\n\n    uint256 internal constant DexT1__InvalidImplementation = 51058;\n\n    uint256 internal constant DexT1__OnlyDelegateCallAllowed = 51059;\n\n    uint256 internal constant DexT1__IncorrectDataLength = 51060;\n\n    uint256 internal constant DexT1__AmountToSendLessThanAmount = 51061;\n\n    uint256 internal constant DexT1__InvalidCollateralReserves = 51062;\n\n    uint256 internal constant DexT1__InvalidDebtReserves = 51063;\n\n    uint256 internal constant DexT1__SupplySharesOverflow = 51064;\n\n    uint256 internal constant DexT1__BorrowSharesOverflow = 51065;\n\n    uint256 internal constant DexT1__OracleNotActive = 51066;\n\n    /***********************************|\n    |            DEX Admin              | \n    |__________________________________*/\n\n    /// @notice thrown when pool is not initialized\n    uint256 internal constant DexT1Admin__PoolNotInitialized = 52001;\n\n    uint256 internal constant DexT1Admin__SmartColIsAlreadyOn = 52002;\n\n    uint256 internal constant DexT1Admin__SmartDebtIsAlreadyOn = 52003;\n\n    /// @notice thrown when any of the configs value overflow the maximum limit\n    uint256 internal constant DexT1Admin__ConfigOverflow = 52004;\n\n    uint256 internal constant DexT1Admin__AddressNotAContract = 52005;\n\n    uint256 internal constant DexT1Admin__InvalidParams = 52006;\n\n    uint256 internal constant DexT1Admin__UserNotDefined = 52007;\n\n    uint256 internal constant DexT1Admin__OnlyDelegateCallAllowed = 52008;\n\n    uint256 internal constant DexT1Admin__UnexpectedPoolState = 52009;\n\n    /// @notice thrown when trying to pause or unpause but user is already in the target pause state\n    uint256 internal constant DexT1Admin__InvalidPauseToggle = 52009;\n\n    /***********************************|\n    |            DEX Factory            | \n    |__________________________________*/\n\n    uint256 internal constant DexFactory__InvalidOperation = 53001;\n    uint256 internal constant DexFactory__Unauthorized = 53002;\n    uint256 internal constant DexFactory__SameTokenNotAllowed = 53003;\n    uint256 internal constant DexFactory__TokenConfigNotProper = 53004;\n    uint256 internal constant DexFactory__InvalidParams = 53005;\n    uint256 internal constant DexFactory__OnlyDelegateCallAllowed = 53006;\n    uint256 internal constant DexFactory__InvalidDexAddress = 53007;\n}\n"},"contracts/protocols/dex/interfaces/iDexFactory.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexFactory {\n    /// @notice Global auth is auth for all dexes\n    function isGlobalAuth(address auth_) external view returns (bool);\n\n    /// @notice Dex auth is auth for a specific dex\n    function isDexAuth(address vault_, address auth_) external view returns (bool);\n\n    /// @notice Total dexes deployed.\n    function totalDexes() external view returns (uint256);\n\n    /// @notice Compute dexAddress\n    function getDexAddress(uint256 dexId_) external view returns (address);\n\n    /// @notice read uint256 `result_` for a storage `slot_` key\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"},"contracts/protocols/dex/interfaces/iDexT1.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexT1 {\n    error FluidDexError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares);\n\n    error FluidDexPricesAndExchangeRates(PricesAndExchangePrice pex_);\n\n    /// @notice returns the dex id\n    function DEX_ID() external view returns (uint256);\n\n    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndOracle;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) external view returns (CollateralReserves memory c_);\n\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) external view returns (DebtReserves memory d_);\n\n    // reverts with FluidDexPricesAndExchangeRates(pex_);\n    function getPricesAndExchangePrices() external;\n\n    function constantsView() external view returns (ConstantViews memory constantsView_);\n\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_);\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param amountOutMin_ The minimum amount of output tokens the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) external payable returns (uint256 amountOut_);\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) external payable returns (uint256 amountIn_);\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) external returns (\n        uint withdrawAmt_\n    );\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) external payable returns (\n        uint paybackAmt_\n    );\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (\n        Oracle[] memory twaps_,\n        uint currentPrice_\n    );\n}\n"},"contracts/protocols/dex/poolT1/common/constantVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { StorageRead } from \"../../../../libraries/storageRead.sol\";\n\ninterface ITokenDecimals {\n    function decimals() external view returns (uint8);\n}\n\nabstract contract ConstantVariables is StorageRead {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    address internal constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;\n\n    address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n    uint256 internal constant NATIVE_TOKEN_DECIMALS = 18;\n    address internal constant ADDRESS_DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint256 internal constant TOKENS_DECIMALS_PRECISION = 12;\n    uint256 internal constant TOKENS_DECIMALS = 1e12;\n\n    uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\n    uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant X2 = 0x3;\n    uint256 internal constant X3 = 0x7;\n    uint256 internal constant X5 = 0x1f;\n    uint256 internal constant X7 = 0x7f;\n    uint256 internal constant X8 = 0xff;\n    uint256 internal constant X9 = 0x1ff;\n    uint256 internal constant X10 = 0x3ff;\n    uint256 internal constant X11 = 0x7ff;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X17 = 0x1ffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X20 = 0xfffff;\n    uint256 internal constant X22 = 0x3fffff;\n    uint256 internal constant X23 = 0x7fffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X28 = 0xfffffff;\n    uint256 internal constant X30 = 0x3fffffff;\n    uint256 internal constant X32 = 0xffffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X40 = 0xffffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n    uint256 internal constant X96 = 0xffffffffffffffffffffffff;\n    uint256 internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n\n    uint256 internal constant TWO_DECIMALS = 1e2;\n    uint256 internal constant THREE_DECIMALS = 1e3;\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant FIVE_DECIMALS = 1e5;\n    uint256 internal constant SIX_DECIMALS = 1e6;\n    uint256 internal constant EIGHT_DECIMALS = 1e8;\n    uint256 internal constant NINE_DECIMALS = 1e9;\n\n    uint256 internal constant PRICE_PRECISION = 1e27;\n\n    uint256 internal constant ORACLE_PRECISION = 1e18; // 100%\n    uint256 internal constant ORACLE_LIMIT = 5 * 1e16; // 5%\n\n    /// after swap token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_SWAP\n    /// after swap token1 reserves should not be less than token0InToken1 / MINIMUM_LIQUIDITY_SWAP\n    uint256 internal constant MINIMUM_LIQUIDITY_SWAP = 1e4;\n\n    /// after user operations (deposit, withdraw, borrow, payback) token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    /// after user operations (deposit, withdraw, borrow, payback) token1 reserves should not be less than token0InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    uint256 internal constant MINIMUM_LIQUIDITY_USER_OPERATIONS = 1e6;\n\n    /// To skip transfers in liquidity layer if token in & out is same and liquidity layer is on the winning side\n    bytes32 internal constant SKIP_TRANSFERS = keccak256(bytes(\"SKIP_TRANSFERS\"));\n\n    function _decimals(address token_) internal view returns (uint256) {\n        return (token_ == NATIVE_TOKEN) ? NATIVE_TOKEN_DECIMALS : ITokenDecimals(token_).decimals();\n    }\n}\n"},"contracts/protocols/dex/poolT1/common/variables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Variables {\n    /*//////////////////////////////////////////////////////////////\n                          STORAGE VARIABLES\n    //////////////////////////////////////////////////////////////*/\n\n    /// First 1 bit  => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\n    /// Next 40 bits => 1-40 => last to last stored price. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 41-80 => last stored price of pool. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 81-120 => center price. Center price from where the ranges will be calculated. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 33 bits => 121-153 => last interaction time stamp\n    /// Next 22 bits => 154-175 => max 4194303 seconds (~1165 hrs, ~48.5 days), time difference between last to last and last price stored\n    /// Next 3 bits  => 176-178 => oracle checkpoint, if 0 then first slot, if 7 then last slot\n    /// Next 16 bits => 179-194 => current mapping or oracle, after every 8 transaction it will increase by 1. Max capacity is 65535 but it can be lower than that check dexVariables2\n    /// Next 1 bit  => 195 => is oracle active?\n    uint internal dexVariables;\n\n    /// Next  1 bit  => 0 => is smart collateral enabled?\n    /// Next  1 bit  => 1 => is smart debt enabled?\n    /// Next 17 bits => 2-18 => fee (1% = 10000, max value: 100000 = 10%, fee should not be more than 10%)\n    /// Next  7 bits => 19-25 => revenue cut from fee (1 = 1%, 100 = 100%). If fee is 1000 = 0.1% and revenue cut is 10 = 10% then governance get 0.01% of every swap\n    /// Next  1 bit  => 26 => percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 20 bits => 27-46 => upperPercent (1% = 10000, max value: 104.8575%) upperRange - upperRange * upperPercent = centerPrice. Hence, upperRange = centerPrice / (1 - upperPercent)\n    /// Next 20 bits => 47-66 => lowerPercent. lowerRange = centerPrice - centerPrice * lowerPercent.\n    /// Next  1 bit  => 67 => threshold percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 10 bits => 68-77 => upper shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice > (centerPrice + (upperRange - centerPrice) * (1000 - upperShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 10 bits => 78-87 => lower shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice < (centerPrice - (centerPrice - lowerRange) * (1000 - lowerShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 24 bits => 88-111 => Shifting time (~194 days) (rate = (% up + % down) / time ?)\n    /// Next 30 bits => 112-131 => Address of center price if center price should be fetched externally, for example, for wstETH <> ETH pool, fetch wstETH exchange rate into stETH from wstETH contract.\n    /// Why fetch it externally? Because let's say pool width is 0.1% and wstETH temporarily got depeg of 0.5% then pool will start to shift to newer pricing\n    /// but we don't want pool to shift to 0.5% because we know the depeg will recover so to avoid the loss for users.\n    /// Next 30 bits => 142-171 => Hooks bits, calculate hook address by storing deployment nonce from factory.\n    /// Next 28 bits => 172-199 => max center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 28 bits => 200-227 => min center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 10 bits => 228-237 => utilization limit of token0. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 10 bits => 238-247 => utilization limit of token1. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 1  bit  => 248     => is center price shift active\n    /// Last 1  bit  => 255     => Pause swap & arbitrage (only perfect functions will be usable), if we need to pause entire DEX then that can be done through pausing DEX on Liquidity Layer\n    uint internal dexVariables2;\n\n    /// first 128 bits => 0-127 => total supply shares\n    /// last 128 bits => 128-255 => max supply shares\n    uint internal _totalSupplyShares;\n\n    /// @dev user supply data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userSupplyData. Hence exact same supply & borrow limit library can be used\n    /// First  1 bit  =>       0 => is user allowed to supply? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user supply amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user withdrawal limit; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383).\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (aka shares can be burned); BigMath: 10 | 8\n    /// Next  38 bits => 218-255 => empty for future use\n    mapping(address => uint) internal _userSupplyData;\n\n    /// first 128 bits => 0-127 => total borrow shares\n    /// last 128 bits => 128-255 => max borrow shares\n    uint internal _totalBorrowShares;\n\n    /// @dev user borrow data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userBorrowData. Hence exact same supply & borrow limit library function can be used\n    /// First  1 bit  =>       0 => is user allowed to borrow? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user debt amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user debt ceiling; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand debt ceiling percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base debt ceiling: below this, there's no debt ceiling limits; BigMath: 10 | 8\n    /// Next  18 bits => 218-235 => max debt ceiling: absolute maximum debt ceiling can expand to; BigMath: 10 | 8\n    /// Next  20 bits => 236-255 => empty for future use\n    mapping(address => uint) internal _userBorrowData;\n\n    /// Price difference between last swap of last block & last swap of new block\n    /// If last swap happened at Block B - 4 and next swap happened after 4 blocks at Block B then it will store that difference\n    /// considering time difference between these 4 blocks is 48 seconds, hence time will be stored as 48\n    /// New oracle update:\n    /// time to 9 bits and precision to 22 bits\n    /// if time exceeds 9 bits which is 511 sec or ~8.5 min then we will use 2 oracle slot to store the data\n    /// we will leave the both time slot as 0 and on first sign + precision slot we will store time and\n    /// on second sign + precision slot we will store sign & precision\n    /// First 9 bits =>   0-  8 => time, 511 seconds\n    /// Next   1 bit  =>  9     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  10- 31 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  32- 40 => time, 511 seconds\n    /// Next   1 bit  =>  41     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  42- 63 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  64- 72 => time, 511 seconds\n    /// Next   1 bit  =>  73     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  74- 95 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  96-104 => time, 511 seconds\n    /// Next   1 bit  => 105     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 106-127 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 128-136 => time, 511 seconds\n    /// Next   1 bit  => 137     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 138-159 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 160-168 => time, 511 seconds\n    /// Next   1 bit  => 169     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 170-191 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 192-200 => time, 511 seconds\n    /// Next   1 bit  => 201     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 202-223 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 224-232 => time, 511 seconds\n    /// Next   1 bit  => 233     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 234-255 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    mapping(uint => uint) internal _oracle;\n\n    /// First 20 bits =>  0-19 => old upper shift\n    /// Next  20 bits => 20-39 => old lower shift\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    uint128 internal _rangeShift;\n\n    /// First 10 bits =>  0- 9 => old upper shift\n    /// Next  10 bits => 10-19 => empty so we can use same helper function\n    /// Next  10 bits => 20-29 => old lower shift\n    /// Next  10 bits => 30-39 => empty so we can use same helper function\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    /// Next  24 bits => 93-116 => old threshold time\n    uint128 internal _thresholdShift;\n\n    /// Shifting is fuzzy and with time it'll keep on getting closer and then eventually get over\n    /// First 33 bits => 0 -32 => starting timestamp\n    /// Next  20 bits => 33-52 => % shift\n    /// Next  20 bits => 53-72 => time to shift that percent\n    uint256 internal _centerPriceShift;\n}\n"},"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { CoreHelpers } from \"../helpers/coreHelpers.sol\";\nimport { SafeTransfer } from \"../../../../../libraries/safeTransfer.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IFluidDexT1 } from \"../../../interfaces/iDexT1.sol\";\n\ninterface IDexCallback {\n    function dexCallback(address token_, uint256 amount_) external;\n}\n\n/// @title FluidDexT1\n/// @notice Implements core logics for Fluid Dex protocol.\n/// Note Token transfers happen directly from user to Liquidity contract and vice-versa.\ncontract FluidDexT1 is CoreHelpers {\n    using BigMathMinified for uint256;\n\n    constructor(ConstantViews memory constantViews_) CoreHelpers(constantViews_) {\n        // any implementations should not be zero\n        if (\n            constantViews_.implementations.shift == address(0) ||\n            constantViews_.implementations.admin == address(0) ||\n            constantViews_.implementations.colOperations == address(0) ||\n            constantViews_.implementations.debtOperations == address(0) ||\n            constantViews_.implementations.perfectOperationsAndSwapOut == address(0)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__InvalidImplementation);\n        }\n    }\n\n    struct SwapInExtras {\n        address to;\n        uint amountOutMin;\n        bool isCallback;\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param extras_ Additional parameters for the swap:\n    ///   - to: Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    ///   - amountOutMin: The minimum amount of output tokens the user expects to receive\n    ///   - isCallback: If true, indicates that the input tokens should be transferred via a callback\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function _swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        SwapInExtras memory extras_\n    ) internal returns (uint256 amountOut_) {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);\n\n        _check(dexVariables_, dexVariables2_);\n\n        if (extras_.to == address(0)) extras_.to = msg.sender;\n\n        SwapInMemory memory s_;\n\n        if (swap0to1_) {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION;\n            }\n        } else {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION;\n            }\n        }\n\n        _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);\n\n        if (msg.value > 0) {\n            if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);\n            if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);\n        }\n\n        // is smart collateral pool enabled\n        uint temp_ = dexVariables2_ & 1;\n        // is smart debt pool enabled\n        uint temp2_ = (dexVariables2_ >> 1) & 1;\n\n        uint temp3_;\n        uint temp4_;\n\n        // extracting fee\n        temp3_ = ((dexVariables2_ >> 2) & X17);\n        unchecked {\n            // revenueCut in 6 decimals, to have proper precision\n            // if fee = 1% and revenue cut = 10% then revenueCut = 1e8 - (10000 * 10) = 99900000\n            s_.revenueCut = EIGHT_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_));\n            // fee in 4 decimals\n            // 1 - fee. If fee is 1% then withoutFee will be 1e6 - 1e4\n            // s_.fee => 1 - withdraw fee\n            s_.fee = SIX_DECIMALS - temp3_;\n        }\n\n        CollateralReservesSwap memory cs_;\n        DebtReservesSwap memory ds_;\n        if (temp_ == 1) {\n            // smart collateral is enabled\n            {\n                CollateralReserves memory c_ = _getCollateralReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.supplyToken0ExchangePrice,\n                    pex_.supplyToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token0RealReserves,\n                        c_.token1RealReserves,\n                        c_.token0ImaginaryReserves,\n                        c_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token1RealReserves,\n                        c_.token0RealReserves,\n                        c_.token1ImaginaryReserves,\n                        c_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        if (temp2_ == 1) {\n            // smart debt is enabled\n            {\n                DebtReserves memory d_ = _getDebtReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.borrowToken0ExchangePrice,\n                    pex_.borrowToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token0Debt,\n                        d_.token1Debt,\n                        d_.token0RealReserves,\n                        d_.token1RealReserves,\n                        d_.token0ImaginaryReserves,\n                        d_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token1Debt,\n                        d_.token0Debt,\n                        d_.token1RealReserves,\n                        d_.token0RealReserves,\n                        d_.token1ImaginaryReserves,\n                        d_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        // limiting amtInAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenIn reserves combined\n        // basically, if this throws that means user is trying to swap 0.5x tokenIn if current tokenIn imaginary reserves is x\n        // let's take x as token0 here, that means, initially the pool pricing might be:\n        // token1Reserve / x and new pool pricing will become token1Reserve / 1.5x (token1Reserve will decrease after swap but for simplicity ignoring that)\n        // So pool price is decreased by ~33.33% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand)\n        unchecked {\n            if (s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2))\n                revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);\n        }\n\n        if (temp_ == 1 && temp2_ == 1) {\n            // unless both pools are enabled s_.swapRoutingAmt will be 0\n            s_.swapRoutingAmt = _swapRoutingIn(\n                s_.amtInAdjusted,\n                cs_.tokenOutImaginaryReserves,\n                cs_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves,\n                ds_.tokenInImaginaryReserves\n            );\n        }\n\n        // In below if else statement temps are:\n        // temp_ => deposit amt\n        // temp2_ => withdraw amt\n        // temp3_ => payback amt\n        // temp4_ => borrow amt\n        if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {\n            // swap will route from the both pools\n            // temp_ = amountInCol_\n            temp_ = uint(s_.swapRoutingAmt);\n            unchecked {\n                // temp3_ = amountInDebt_\n                temp3_ = s_.amtInAdjusted - temp_;\n            }\n\n            (temp2_, temp4_) = (0, 0);\n\n            // debt pool price will be the same as collateral pool after the swap\n            s_.withdrawTo = extras_.to;\n            s_.borrowTo = extras_.to;\n        } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {\n            // entire swap will route through collateral pool\n            (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);\n            // price can slightly differ from debt pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.withdrawTo = extras_.to;\n        } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {\n            // entire swap will route through debt pool\n            (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);\n            // price can slightly differ from collateral pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.borrowTo = extras_.to;\n        } else {\n            // swap should never reach this point but if it does then reverting\n            revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);\n        }\n\n        if (temp_ > 0) {\n            // temp2_ = amountOutCol_\n            temp2_ = _getAmountOut(\n                ((temp_ * s_.fee) / SIX_DECIMALS),\n                cs_.tokenInImaginaryReserves,\n                cs_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (cs_.tokenInRealReserves + temp_),\n                    (cs_.tokenOutRealReserves - temp2_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (cs_.tokenOutRealReserves - temp2_),\n                    (cs_.tokenInRealReserves + temp_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n        if (temp3_ > 0) {\n            // temp4_ = amountOutDebt_\n            temp4_ = _getAmountOut(\n                ((temp3_ * s_.fee) / SIX_DECIMALS),\n                ds_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (ds_.tokenInRealReserves + temp3_),\n                    (ds_.tokenOutRealReserves - temp4_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (ds_.tokenOutRealReserves - temp4_),\n                    (ds_.tokenInRealReserves + temp3_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n\n        // (temp_ + temp3_) == amountIn_ == msg.value (for native token), if there is revenue cut then this statement is not true\n        temp_ = (temp_ * s_.revenueCut) / EIGHT_DECIMALS;\n        temp3_ = (temp3_ * s_.revenueCut) / EIGHT_DECIMALS;\n\n        // from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same\n        if (temp_ > temp3_) {\n            // new pool price from col pool\n            s_.price = swap0to1_\n                ? ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_)\n                : ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);\n        } else {\n            // new pool price from debt pool\n            s_.price = swap0to1_\n                ? ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_)\n                : ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);\n        }\n\n        // converting into normal token amounts\n        if (swap0to1_) {\n            temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            }\n        } else {\n            temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            }\n        }\n\n        unchecked {\n            amountOut_ = temp2_ + temp4_;\n        }\n\n        // if address dead then reverting with amountOut\n        if (extras_.to == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);\n\n        if (amountOut_ < extras_.amountOutMin) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);\n\n        // allocating to avoid stack-too-deep error\n        // not setting in the callbackData as last 2nd to avoid SKIP_TRANSFERS clashing\n        s_.data = abi.encode(amountIn_, extras_.isCallback, msg.sender); // true/false is to decide if dex should do callback or directly transfer from user\n        // deposit & payback token in at liquidity\n        LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);\n        // withdraw & borrow token out at liquidity\n        LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));\n\n        // if hook exists then calling hook\n        temp_ = (dexVariables2_ >> 142) & X30;\n        if (temp_ > 0) {\n            s_.swap0to1 = swap0to1_;\n            _hookVerify(temp_, 1, s_.swap0to1, s_.price);\n        }\n\n        swap0to1_\n            ? _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT)\n            : _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);\n\n        dexVariables = _updateOracle(s_.price, pex_.centerPrice, dexVariables_);\n\n        emit Swap(swap0to1_, amountIn_, amountOut_, extras_.to);\n    }\n\n    /// @dev Swap tokens with perfect amount in\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, false));\n    }\n\n    /// @dev Swap tokens with perfect amount in and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapInWithCallback(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, true));\n    }\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Swap tokens with perfect amount out and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOutWithCallback(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) public returns (uint withdrawAmt_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) public payable returns (uint paybackAmt_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev liquidity callback for cheaper token transfers in case of deposit or payback.\n    /// only callable by Liquidity during an operation.\n    function liquidityCallback(address token_, uint amount_, bytes calldata data_) external {\n        if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity);\n        if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn);\n        if (data_.length != 96) revert FluidDexError(ErrorTypes.DexT1__IncorrectDataLength);\n\n        (uint amountToSend_, bool isCallback_, address from_) = abi.decode(data_, (uint, bool, address));\n\n        if (amountToSend_ < amount_) revert FluidDexError(ErrorTypes.DexT1__AmountToSendLessThanAmount);\n\n        if (isCallback_) {\n            IDexCallback(from_).dexCallback(token_, amountToSend_);\n        } else {\n            SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountToSend_);\n        }\n    }\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (Oracle[] memory twaps_, uint currentPrice_) {\n        OraclePriceMemory memory o_;\n\n        uint dexVariables_ = dexVariables;\n\n        if ((dexVariables_ >> 195) & 1 == 0) {\n            revert FluidDexError(ErrorTypes.DexT1__OracleNotActive);\n        }\n\n        twaps_ = new Oracle[](secondsAgos_.length);\n\n        uint totalTime_;\n        uint time_;\n\n        uint i;\n        uint secondsAgo_ = secondsAgos_[0];\n\n        currentPrice_ = (dexVariables_ >> 41) & X40;\n        currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);\n        uint price_ = currentPrice_;\n        o_.lowestPrice1by0 = currentPrice_;\n        o_.highestPrice1by0 = currentPrice_;\n\n        uint twap1by0_;\n        uint twap0by1_;\n\n        uint j;\n\n        o_.oracleSlot = (dexVariables_ >> 176) & X3;\n        o_.oracleMap = (dexVariables_ >> 179) & X16;\n        // if o_.oracleSlot == 7 then it'll enter the if statement in the below while loop\n        o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;\n\n        uint slotData_;\n        uint percentDiff_;\n\n        if (((dexVariables_ >> 121) & X33) < block.timestamp) {\n            // last swap didn't occured in this block.\n            // hence last price is current price of pool & also the last price\n            time_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        } else {\n            // last swap occured in this block, that means current price is active for 0 secs. Hence TWAP for it will be 0.\n            ++j;\n        }\n\n        while (true) {\n            if (j == 2) {\n                if (++o_.oracleSlot == 8) {\n                    o_.oracleSlot = 0;\n                    if (o_.oracleMap == 0) {\n                        o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                    }\n                    o_.oracle = _oracle[--o_.oracleMap];\n                }\n\n                slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                if (slotData_ > 0) {\n                    time_ = slotData_ & X9;\n                    if (time_ == 0) {\n                        // time is in precision & sign bits\n                        time_ = slotData_ >> 9;\n                        // if o_.oracleSlot is 7 then precision & bits and stored in 1 less map\n                        if (o_.oracleSlot == 7) {\n                            o_.oracleSlot = 0;\n                            if (o_.oracleMap == 0) {\n                                o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                            }\n                            o_.oracle = _oracle[--o_.oracleMap];\n                            slotData_ = o_.oracle & X32;\n                        } else {\n                            ++o_.oracleSlot;\n                            slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                        }\n                    }\n                    percentDiff_ = slotData_ >> 10;\n                    percentDiff_ = (ORACLE_LIMIT * percentDiff_) / X22;\n                    if (((slotData_ >> 9) & 1 == 1)) {\n                        // if positive then old price was lower than current hence subtracting\n                        price_ = price_ - (price_ * percentDiff_) / ORACLE_PRECISION;\n                    } else {\n                        // if negative then old price was higher than current hence adding\n                        price_ = price_ + (price_ * percentDiff_) / ORACLE_PRECISION;\n                    }\n                } else {\n                    // oracle data does not exist. Probably due to pool recently got initialized and not have much swaps.\n                    revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);\n                }\n            } else if (j == 1) {\n                // last & last to last price\n                price_ = (dexVariables_ >> 1) & X40;\n                price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);\n                time_ = (dexVariables_ >> 154) & X22;\n                ++j;\n            } else if (j == 0) {\n                ++j;\n            }\n\n            totalTime_ += time_;\n            if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;\n            if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;\n            if (totalTime_ < secondsAgo_) {\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n            } else {\n                time_ = time_ + secondsAgo_ - totalTime_;\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n                // also auto checks that secondsAgos_ should not be == 0\n                twap1by0_ = twap1by0_ / secondsAgo_;\n                twap0by1_ = twap0by1_ / secondsAgo_;\n\n                twaps_[i] = Oracle(\n                    twap1by0_,\n                    o_.lowestPrice1by0,\n                    o_.highestPrice1by0,\n                    twap0by1_,\n                    (1e54 / o_.highestPrice1by0),\n                    (1e54 / o_.lowestPrice1by0)\n                );\n\n                // TWAP for next secondsAgo will start with price_\n                o_.lowestPrice1by0 = price_;\n                o_.highestPrice1by0 = price_;\n\n                while (++i < secondsAgos_.length) {\n                    // secondsAgo_ = [60, 15, 0]\n                    time_ = totalTime_ - secondsAgo_;\n                    // updating total time as new seconds ago started\n                    totalTime_ = time_;\n                    // also auto checks that secondsAgos_[i + 1] > secondsAgos_[i]\n                    secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];\n                    if (totalTime_ < secondsAgo_) {\n                        twap1by0_ = price_ * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        // if time_ comes out as 0 here then lowestPrice & highestPrice should not be price_, it should be next price_ that we will calculate\n                        if (time_ == 0) {\n                            o_.lowestPrice1by0 = type(uint).max;\n                            o_.highestPrice1by0 = 0;\n                        }\n                        break;\n                    } else {\n                        time_ = time_ + secondsAgo_ - totalTime_;\n                        // twap1by0_ = price_ here\n                        twap1by0_ = price_ * time_;\n                        // twap0by1_ = (1e54 / price_) * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        twap1by0_ = twap1by0_ / secondsAgo_;\n                        twap0by1_ = twap0by1_ / secondsAgo_;\n                        twaps_[i] = Oracle(\n                            twap1by0_,\n                            o_.lowestPrice1by0,\n                            o_.highestPrice1by0,\n                            twap0by1_,\n                            (1e54 / o_.highestPrice1by0),\n                            (1e54 / o_.lowestPrice1by0)\n                        );\n                    }\n                }\n                if (i == secondsAgos_.length) return (twaps_, currentPrice_); // oracle fetch over\n            }\n        }\n    }\n\n    function getPricesAndExchangePrices() public {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        _check(dexVariables_, dexVariables2_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables, dexVariables2);\n\n        revert FluidDexPricesAndExchangeRates(pex_);\n    }\n\n    /// @dev Internal fallback function to handle calls to non-existent functions\n    /// @notice This function is called when a transaction is sent to the contract without matching any other function\n    /// @notice It checks if the caller is authorized, enables re-entrancy protection, delegates the call to the admin implementation, and then disables re-entrancy protection\n    /// @notice Only authorized callers (global or dex auth) can trigger this function\n    /// @notice This function uses assembly to perform a delegatecall to the admin implementation to update configs related to DEX\n    function _fallback() private {\n        if (!(DEX_FACTORY.isGlobalAuth(msg.sender) || DEX_FACTORY.isDexAuth(address(this), msg.sender))) {\n            revert FluidDexError(ErrorTypes.DexT1__NotAnAuth);\n        }\n\n        uint dexVariables_ = dexVariables;\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n\n        // Delegate the current call to `ADMIN_IMPLEMENTATION`.\n        _spell(ADMIN_IMPLEMENTATION, msg.data);\n\n        // disabling re-entrancy\n        // directly fetching from storage so updates from Admin module will get auto covered\n        dexVariables = dexVariables & ~uint(1);\n    }\n\n    fallback() external payable {\n        _fallback();\n    }\n\n    receive() external payable {\n        if (msg.sig != 0x00000000) {\n            _fallback();\n        }\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView() external view returns (ConstantViews memory constantsView_) {\n        constantsView_.dexId = DEX_ID;\n        constantsView_.liquidity = address(LIQUIDITY);\n        constantsView_.factory = address(DEX_FACTORY);\n        constantsView_.token0 = TOKEN_0;\n        constantsView_.token1 = TOKEN_1;\n        constantsView_.implementations.shift = SHIFT_IMPLEMENTATION;\n        constantsView_.implementations.admin = ADMIN_IMPLEMENTATION;\n        constantsView_.implementations.colOperations = COL_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.debtOperations = DEBT_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.perfectOperationsAndSwapOut = PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n        constantsView_.deployerContract = DEPLOYER_CONTRACT;\n        constantsView_.supplyToken0Slot = SUPPLY_TOKEN_0_SLOT;\n        constantsView_.borrowToken0Slot = BORROW_TOKEN_0_SLOT;\n        constantsView_.supplyToken1Slot = SUPPLY_TOKEN_1_SLOT;\n        constantsView_.borrowToken1Slot = BORROW_TOKEN_1_SLOT;\n        constantsView_.exchangePriceToken0Slot = EXCHANGE_PRICE_TOKEN_0_SLOT;\n        constantsView_.exchangePriceToken1Slot = EXCHANGE_PRICE_TOKEN_1_SLOT;\n        constantsView_.oracleMapping = TOTAL_ORACLE_MAPPING;\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_) {\n        constantsView2_.token0NumeratorPrecision = TOKEN_0_NUMERATOR_PRECISION;\n        constantsView2_.token0DenominatorPrecision = TOKEN_0_DENOMINATOR_PRECISION;\n        constantsView2_.token1NumeratorPrecision = TOKEN_1_NUMERATOR_PRECISION;\n        constantsView2_.token1DenominatorPrecision = TOKEN_1_DENOMINATOR_PRECISION;\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) public view returns (CollateralReserves memory c_) {\n        return\n            _getCollateralReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0SupplyExchangePrice_,\n                token1SupplyExchangePrice_\n            );\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) public view returns (DebtReserves memory d_) {\n        return\n            _getDebtReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0BorrowExchangePrice_,\n                token1BorrowExchangePrice_\n            );\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/events.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n    /// @notice Emitted on token swaps\n    /// @param swap0to1 Indicates whether the swap is from token0 to token1 or vice-versa.\n    /// @param amountIn The amount of tokens to be sent to the vault to swap.\n    /// @param amountOut The amount of tokens user got from the swap.\n    /// @param to Recepient of swapped tokens.\n    event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to);\n\n    /// @notice Emitted when liquidity is added with shares specified.\n    /// @param shares Expected exact shares to be received.\n    /// @param token0Amt Amount of token0 deposited.\n    /// @param token0Amt Amount of token1 deposited.\n    event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is borrowed with shares specified.\n    /// @param shares shares minted\n    /// @param token0Amt Amount of token0 borrowed.\n    /// @param token1Amt Amount of token1 borrowed.\n    event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is deposited with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 deposited.\n    /// @param amount1 Amount of token1 deposited.\n    /// @param shares Amount of shares minted.\n    event LogDepositColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 withdrawn.\n    /// @param amount1 Amount of token1 withdrawn.\n    /// @param shares Amount of shares burned.\n    event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is borrowed with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 borrowed.\n    /// @param amount1 Amount of token1 borrowed.\n    /// @param shares Amount of shares minted.\n    event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is paid back with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 paid back.\n    /// @param amount1 Amount of token1 paid back.\n    /// @param shares Amount of shares burned.\n    event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified into one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified from one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when internal arbitrage between 2 pools happen\n    /// @param routing if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback\n    /// @param amtOut if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow\n    event LogArbitrage(int routing, uint amtOut);\n}\n"},"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\n\nimport { Variables } from \"../../common/variables.sol\";\nimport { ImmutableVariables } from \"../immutableVariables.sol\";\nimport { Events } from \"../events.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IHook, ICenterPrice } from \"../interfaces.sol\";\nimport { LiquiditySlotsLink } from \"../../../../../libraries/liquiditySlotsLink.sol\";\nimport { LiquidityCalcs } from \"../../../../../libraries/liquidityCalcs.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { AddressCalcs } from \"../../../../../libraries/addressCalcs.sol\";\n\ninterface IShifting {\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper threshold, lower threshold, and dexVariables2\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new center price during an active center price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return The updated center price\n    function _calcCenterPrice(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) external payable returns (uint);\n}\n\nabstract contract CoreHelpers is Variables, ImmutableVariables, Events {\n    using BigMathMinified for uint256;\n\n    /// @dev            do any arbitrary call\n    /// @param target_  Address to which the call needs to be delegated\n    /// @param data_    Data to execute at the delegated address\n    function _spell(address target_, bytes memory data_) internal returns (bytes memory response_) {\n        assembly {\n            let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)\n            let size := returndatasize()\n\n            response_ := mload(0x40)\n            mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n            mstore(response_, size)\n            returndatacopy(add(response_, 0x20), 0, size)\n\n            if iszero(succeeded) {\n                // throw if delegatecall failed\n                returndatacopy(0x00, 0x00, size)\n                revert(0x00, size)\n            }\n        }\n    }\n\n    /// @dev Given an input amount of asset and pair reserves, returns the maximum output amount of the other asset\n    /// @param amountIn_ The amount of input asset.\n    /// @param iReserveIn_ Imaginary token reserve with input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountOut(\n        uint256 amountIn_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountOut_) {\n        unchecked {\n            // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n            uint256 numerator_ = amountIn_ * iReserveOut_;\n            uint256 denominator_ = iReserveIn_ + amountIn_;\n\n            // Using the swap formula: (AmountIn * iReserveY) / (iReserveX + AmountIn)\n            amountOut_ = numerator_ / denominator_;\n        }\n    }\n\n    /// @dev Given an output amount of asset and pair reserves, returns the input amount of the other asset\n    /// @param amountOut_ Desired output amount of the asset.\n    /// @param iReserveIn_ Imaginary token reserve of input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountIn(\n        uint256 amountOut_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountIn_) {\n        // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n        uint256 numerator_ = amountOut_ * iReserveIn_;\n        uint256 denominator_ = iReserveOut_ - amountOut_;\n\n        // Using the swap formula: (AmountOut * iReserveX) / (iReserveY - AmountOut)\n        amountIn_ = numerator_ / denominator_;\n    }\n\n    /// @param t total amount in\n    /// @param x imaginary reserves of token out of collateral\n    /// @param y imaginary reserves of token in of collateral\n    /// @param x2 imaginary reserves of token out of debt\n    /// @param y2 imaginary reserves of token in of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingIn(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. out = x * a / (y + a)\n        // 2. out2 = x2 * (t - a) / (y2 + (t - a))\n        // final price should be same\n        // 3. (y + a) / (x - out) = (y2 + (t - a)) / (x2 - out2)\n        // derivation: https://chatgpt.com/share/dce6f381-ee5f-4d5f-b6ea-5996e84d5b57\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    /// @param t total amount out\n    /// @param x imaginary reserves of token in of collateral\n    /// @param y imaginary reserves of token out of collateral\n    /// @param x2 imaginary reserves of token in of debt\n    /// @param y2 imaginary reserves of token out of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingOut(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. in = (x * a) / (y - a)\n        // 2. in2 = (x2 * (t - a)) / (y2 - (t - a))\n        // final price should be same\n        // 3. (y - a) / (x + in) = (y2 - (t - a)) / (x2 + in2)\n        // derivation: https://chatgpt.com/share/6585bc28-841f-49ec-aea2-1e5c5b7f4fa9\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        // 1e18 precision gets cancelled out in division\n        a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view {\n        if (utilizationLimit_ < THREE_DECIMALS) {\n            utilizationLimit_ = utilizationLimit_ * 10;\n            // extracting utilization of token from liquidity layer\n            uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);\n            liquidityLayerUtilization_ =\n                (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) &\n                X14;\n            // Note: this can go slightly above the utilization limit if no update is written to storage at liquidity layer\n            // if swap was not big enough to go far enough above or any other storage update threshold write cause there\n            // so just to keep in mind when configuring the actual limit reachable can be utilizationLimit_ + storageUpdateThreshold at Liquidity\n            if (liquidityLayerUtilization_ > utilizationLimit_)\n                revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);\n        }\n    }\n\n    function _check(uint dexVariables_, uint dexVariables2_) internal {\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        if (dexVariables2_ & 3 == 0) revert FluidDexError(ErrorTypes.DexT1__PoolNotInitialized);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n    }\n\n    /// @dev if token0 reserves are too low w.r.t token1 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken0Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token0Reserves_) < ((token1Reserves_ * 1e27) / (centerPrice_ * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    /// @dev if token1 reserves are too low w.r.t token0 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken1Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token1Reserves_) < ((token0Reserves_ * centerPrice_) / (1e27 * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure {\n        // after shifting amount should not become 0\n        // limiting to six decimals which means in case of USDC, USDT it's 1 wei, for WBTC 100 wei, for ETH 1000 gwei\n        if (amountAdjusted_ < SIX_DECIMALS || amountAdjusted_ > X96 || amount_ < TWO_DECIMALS || amount_ > X128)\n            revert FluidDexError(ErrorTypes.DexT1__LimitingAmountsSwapAndNonPerfectActions);\n    }\n\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    /// @notice This function handles the gradual shifting of range values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcRangeShifting.selector,\n                        upperRange_,\n                        lowerRange_,\n                        dexVariables2_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new upper and lower threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param thresholdTime_ The time passed since shifting started\n    /// @return The updated upper threshold, lower threshold, and threshold time\n    /// @notice This function handles the gradual shifting of threshold values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint thresholdTime_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcThresholdShifting.selector,\n                        upperThreshold_,\n                        lowerThreshold_,\n                        thresholdTime_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new center price during an active price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return newCenterPrice_ The updated center price\n    /// @notice This function gradually shifts the center price towards a new target price over time\n    /// @notice It uses an external price source (via ICenterPrice) to determine the target price\n    /// @notice The shift continues until the current price reaches the target, or the shift duration ends\n    /// @notice Once the shift is complete, it updates the state and clears the shift data\n    /// @notice The shift rate is dynamic and depends on:\n    /// @notice - Time remaining in the shift duration\n    /// @notice - The new center price (fetched externally, which may change)\n    /// @notice - The current (old) center price\n    /// @notice This results in a fuzzy shifting mechanism where the rate can change as these parameters evolve\n    /// @notice The externally fetched new center price is expected to not differ significantly from the last externally fetched center price\n    function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(IShifting._calcCenterPrice.selector, dexVariables_, dexVariables2_)\n                ),\n                (uint)\n            );\n    }\n\n    /// @notice Calculates and returns the current prices and exchange prices for the pool\n    /// @param dexVariables_ The first set of DEX variables containing various pool parameters\n    /// @param dexVariables2_ The second set of DEX variables containing additional pool parameters\n    /// @return pex_ A struct containing the calculated prices and exchange prices:\n    ///         - pex_.lastStoredPrice: The last stored price in 1e27 decimals\n    ///         - pex_.centerPrice: The calculated or fetched center price in 1e27 decimals\n    ///         - pex_.upperRange: The upper range price limit in 1e27 decimals\n    ///         - pex_.lowerRange: The lower range price limit in 1e27 decimals\n    ///         - pex_.geometricMean: The geometric mean of upper range & lower range in 1e27 decimals\n    ///         - pex_.supplyToken0ExchangePrice: The current exchange price for supplying token0\n    ///         - pex_.borrowToken0ExchangePrice: The current exchange price for borrowing token0\n    ///         - pex_.supplyToken1ExchangePrice: The current exchange price for supplying token1\n    ///         - pex_.borrowToken1ExchangePrice: The current exchange price for borrowing token1\n    /// @dev This function performs the following operations:\n    ///      1. Determines the center price (either from storage, external source, or calculated)\n    ///      2. Retrieves the last stored price from dexVariables_\n    ///      3. Calculates the upper and lower range prices based on the center price and range percentages\n    ///      4. Checks if rebalancing is needed based on threshold settings\n    ///      5. Adjusts prices if necessary based on the time elapsed and threshold conditions\n    ///      6. Update the dexVariables2_ if changes were made\n    ///      7. Returns the calculated prices and exchange prices in the PricesAndExchangePrice struct\n    function _getPricesAndExchangePrices(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) internal returns (PricesAndExchangePrice memory pex_) {\n        uint centerPrice_;\n\n        if (((dexVariables2_ >> 248) & 1) == 0) {\n            // centerPrice_ => center price hook\n            centerPrice_ = (dexVariables2_ >> 112) & X30;\n            if (centerPrice_ == 0) {\n                centerPrice_ = (dexVariables_ >> 81) & X40;\n                centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);\n            } else {\n                // center price should be fetched from external source. For exmaple, in case of wstETH <> ETH pool,\n                // we would want the center price to be pegged to wstETH exchange rate into ETH\n                centerPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, centerPrice_)).centerPrice();\n            }\n        } else {\n            // an active centerPrice_ shift is going on\n            centerPrice_ = _calcCenterPrice(dexVariables_, dexVariables2_);\n        }\n\n        uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;\n        lastStoredPrice_ = (lastStoredPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastStoredPrice_ & DEFAULT_EXPONENT_MASK);\n\n        uint upperRange_ = ((dexVariables2_ >> 27) & X20);\n        uint lowerRange_ = ((dexVariables2_ >> 47) & X20);\n        if (((dexVariables2_ >> 26) & 1) == 1) {\n            // an active range shift is going on\n            (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);\n        }\n\n        unchecked {\n            // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n            // 1% = 1e4, 100% = 1e6\n            upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n            // 1% = 1e4, 100% = 1e6\n            lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n        }\n\n        bool changed_;\n        {\n            // goal will be to keep threshold percents 0 if center price is fetched from external source\n            // checking if threshold are set non 0 then only rebalancing is on\n            if (((dexVariables2_ >> 68) & X20) > 0) {\n                uint upperThreshold_ = (dexVariables2_ >> 68) & X10;\n                uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;\n                uint shiftingTime_ = (dexVariables2_ >> 88) & X24;\n                if (((dexVariables2_ >> 67) & 1) == 1) {\n                    // if active shift is going on for threshold then calculate threshold real time\n                    (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(\n                        upperThreshold_,\n                        lowerThreshold_,\n                        shiftingTime_\n                    );\n                }\n\n                unchecked {\n                    if (\n                        lastStoredPrice_ >\n                        (centerPrice_ +\n                            ((upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards upper range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = upperRange_;\n                        }\n                        changed_ = true;\n                    } else if (\n                        lastStoredPrice_ <\n                        (centerPrice_ -\n                            ((centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards lower range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = lowerRange_;\n                        }\n                        changed_ = true;\n                    }\n                }\n            }\n        }\n\n        // temp_ => max center price\n        uint temp_ = (dexVariables2_ >> 172) & X28;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n        if (centerPrice_ > temp_) {\n            // if center price is greater than max center price\n            centerPrice_ = temp_;\n            changed_ = true;\n        } else {\n            // check if center price is less than min center price\n            // temp_ => min center price\n            temp_ = (dexVariables2_ >> 200) & X28;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n            if (centerPrice_ < temp_) {\n                centerPrice_ = temp_;\n                changed_ = true;\n            }\n        }\n\n        // if centerPrice_ is changed then calculating upper and lower range again\n        if (changed_) {\n            upperRange_ = ((dexVariables2_ >> 27) & X20);\n            lowerRange_ = ((dexVariables2_ >> 47) & X20);\n            if (((dexVariables2_ >> 26) & 1) == 1) {\n                (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(\n                    upperRange_,\n                    lowerRange_,\n                    dexVariables2_\n                );\n            }\n\n            unchecked {\n                // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n                // 1% = 1e4, 100% = 1e6\n                upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n                // 1% = 1e4, 100% = 1e6\n                lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n            }\n        }\n\n        pex_.lastStoredPrice = lastStoredPrice_;\n        pex_.centerPrice = centerPrice_;\n        pex_.upperRange = upperRange_;\n        pex_.lowerRange = lowerRange_;\n\n        unchecked {\n            if (upperRange_ < 1e38) {\n                // 1e38 * 1e38 = 1e76 which is less than max uint limit\n                pex_.geometricMean = FixedPointMathLib.sqrt(upperRange_ * lowerRange_);\n            } else {\n                // upperRange_ price is pretty large hence lowerRange_ will also be pretty large\n                pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18;\n            }\n        }\n\n        // Exchange price will remain same as Liquidity Layer\n        (pex_.supplyToken0ExchangePrice, pex_.borrowToken0ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_0_SLOT)\n        );\n\n        (pex_.supplyToken1ExchangePrice, pex_.borrowToken1ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_1_SLOT)\n        );\n    }\n\n    /// @dev getting reserves outside range.\n    /// @param gp_ is geometric mean pricing of upper percent & lower percent\n    /// @param pa_ price of upper range or lower range\n    /// @param rx_ real reserves of token0 or token1\n    /// @param ry_ whatever is rx_ the other will be ry_\n    function _calculateReservesOutsideRange(\n        uint gp_,\n        uint pa_,\n        uint rx_,\n        uint ry_\n    ) internal pure returns (uint xa_, uint yb_) {\n        // equations we have:\n        // 1. x*y = k\n        // 2. xa*ya = k\n        // 3. xb*yb = k\n        // 4. Pa = ya / xa = upperRange_ (known)\n        // 5. Pb = yb / xb = lowerRange_ (known)\n        // 6. x - xa = rx = real reserve of x (known)\n        // 7. y - yb = ry = real reserve of y (known)\n        // With solving we get:\n        // ((Pa*Pb)^(1/2) - Pa)*xa^2 + (rx * (Pa*Pb)^(1/2) + ry)*xa + rx*ry = 0\n        // yb = yb = xa * (Pa * Pb)^(1/2)\n\n        // xa = (GP⋅rx + ry + (-rx⋅ry⋅4⋅(GP - Pa) + (GP⋅rx + ry)^2)^0.5) / (2Pa - 2GP)\n        // multiply entire equation by 1e27 to remove the price decimals precision of 1e27\n        // xa = (GP⋅rx + ry⋅1e27 + (rx⋅ry⋅4⋅(Pa - GP)⋅1e27 + (GP⋅rx + ry⋅1e27)^2)^0.5) / 2*(Pa - GP)\n        // dividing the equation with 2*(Pa - GP). Pa is always > GP so answer will be positive.\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅4⋅(Pa - GP)⋅1e27) / 4*(Pa - GP)^2) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅1e27) / (Pa - GP)) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n\n        // dividing in 3 parts for simplification:\n        // part1 = (Pa - GP)\n        // part2 = (GP⋅rx + ry⋅1e27) / (2*part1)\n        // part3 = rx⋅ry\n        // note: part1 will almost always be < 1e28 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e29\n        uint p1_ = pa_ - gp_;\n        uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);\n        uint p3_ = rx_ * ry_;\n        // to avoid overflowing\n        p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27;\n\n        // xa = part2 + (part3 + (part2 * part2))^(1/2)\n        // yb = xa_ * gp_\n        xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));\n        yb_ = (xa_ * gp_) / 1e27;\n    }\n\n    /// @dev Retrieves collateral amount from liquidity layer for a given token\n    /// @param supplyTokenSlot_ The storage slot for the supply token data\n    /// @param tokenExchangePrice_ The exchange price of the token\n    /// @param isToken0_ Boolean indicating if the token is token0 (true) or token1 (false)\n    /// @return tokenSupply_ The calculated liquidity collateral amount\n    function _getLiquidityCollateral(\n        bytes32 supplyTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenSupply_) {\n        uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);\n        tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;\n        tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);\n\n        if (tokenSupplyData_ & 1 == 1) {\n            // supply with interest is on\n            unchecked {\n                tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenSupply_ = isToken0_\n                ? ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function _getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) internal view returns (CollateralReserves memory c_) {\n        uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);\n        uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);\n\n        if (geometricMean_ < 1e27) {\n            (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(\n                geometricMean_,\n                upperRange_,\n                token0Supply_,\n                token1Supply_\n            );\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange(\n                (1e54 / geometricMean_),\n                (1e54 / lowerRange_),\n                token1Supply_,\n                token0Supply_\n            );\n        }\n\n        c_.token0RealReserves = token0Supply_;\n        c_.token1RealReserves = token1Supply_;\n        unchecked {\n            c_.token0ImaginaryReserves += token0Supply_;\n            c_.token1ImaginaryReserves += token1Supply_;\n        }\n    }\n\n    /// @notice Calculates the real and imaginary debt reserves for both tokens\n    /// @dev This function uses a quadratic equation to determine the debt reserves\n    ///      based on the geometric mean price and the current debt amounts\n    /// @param gp_ The geometric mean price of upper range & lower range\n    /// @param pb_ The price of lower range\n    /// @param dx_ The debt amount of one token\n    /// @param dy_ The debt amount of the other token\n    /// @return rx_ The real debt reserve of the first token\n    /// @return ry_ The real debt reserve of the second token\n    /// @return irx_ The imaginary debt reserve of the first token\n    /// @return iry_ The imaginary debt reserve of the second token\n    function _calculateDebtReserves(\n        uint gp_,\n        uint pb_,\n        uint dx_,\n        uint dy_\n    ) internal pure returns (uint rx_, uint ry_, uint irx_, uint iry_) {\n        // Assigning letter to knowns:\n        // c = debtA\n        // d = debtB\n        // e = upperPrice\n        // f = lowerPrice\n        // g = upperPrice^1/2\n        // h = lowerPrice^1/2\n\n        // c = 1\n        // d = 2000\n        // e = 2222.222222\n        // f = 1800\n        // g = 2222.222222^1/2\n        // h = 1800^1/2\n\n        // Assigning letter to unknowns:\n        // w = realDebtReserveA\n        // x = realDebtReserveB\n        // y = imaginaryDebtReserveA\n        // z = imaginaryDebtReserveB\n        // k = k\n\n        // below quadratic will give answer of realDebtReserveB\n        // A, B, C of quadratic equation:\n        // A = h\n        // B = dh - cfg\n        // C = -cfdh\n\n        // A = lowerPrice^1/2\n        // B = debtB⋅lowerPrice^1/2 - debtA⋅lowerPrice⋅upperPrice^1/2\n        // C = -(debtA⋅lowerPrice⋅debtB⋅lowerPrice^1/2)\n\n        // x = (cfg − dh + (4cdf(h^2)+(cfg−dh)^2))^(1/2)) / 2h\n        // simplifying dividing by h, note h = f^1/2\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((4⋅c⋅d⋅f⋅f) / (4h^2) + ((c⋅f⋅g) / 2h − (d⋅h) / 2h)^2))^(1/2))\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((c⋅d⋅f) + ((c⋅g⋅(f^1/2) − d) / 2)^2))^(1/2))\n\n        // dividing in 3 parts for simplification:\n        // part1 = (c⋅g⋅(f^1/2) − d) / 2\n        // part2 = (c⋅d⋅f)\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        // note: part1 will almost always be < 1e27 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e28\n\n        // part1 = ((debtA * upperPrice^1/2 * lowerPrice^1/2) - debtB) / 2\n        // note: upperPrice^1/2 * lowerPrice^1/2 = geometric mean\n        // part1 = ((debtA * geometricMean) - debtB) / 2\n        // part2 = debtA * debtB * lowerPrice\n\n        // converting decimals properly as price is in 1e27 decimals\n        // part1 = ((debtA * geometricMean) - (debtB * 1e27)) / (2 * 1e27)\n        // part2 = (debtA * debtB * lowerPrice) / 1e27\n        // final x equals:\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);\n        uint p2_ = (dx_ * dy_);\n        p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;\n        ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));\n\n        // finding z:\n        // x^2 - zx + cfz = 0\n        // z*(x - cf) = x^2\n        // z = x^2 / (x - cf)\n        // z = x^2 / (x - debtA * lowerPrice)\n        // converting decimals properly as price is in 1e27 decimals\n        // z = (x^2 * 1e27) / ((x * 1e27) - (debtA * lowerPrice))\n\n        iry_ = ((ry_ * 1e27) - (dx_ * pb_));\n        if (iry_ < SIX_DECIMALS) {\n            // almost impossible situation to ever get here\n            revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);\n        }\n        if (ry_ < 1e25) {\n            iry_ = (ry_ * ry_ * 1e27) / iry_;\n        } else {\n            // note: it can never result in negative as final result will always be in positive\n            iry_ = (ry_ * ry_) / (iry_ / 1e27);\n        }\n\n        // finding y\n        // x = z * c / (y + c)\n        // y + c = z * c / x\n        // y = (z * c / x) - c\n        // y = (z * debtA / x) - debtA\n        irx_ = ((iry_ * dx_) / ry_) - dx_;\n\n        // finding w\n        // w = y * d / (z + d)\n        // w = (y * debtB) / (z + debtB)\n        rx_ = (irx_ * dy_) / (iry_ + dy_);\n    }\n\n    /// @notice Calculates the debt amount for a given token from liquidity layer\n    /// @param borrowTokenSlot_ The storage slot for the token's borrow data\n    /// @param tokenExchangePrice_ The current exchange price of the token\n    /// @param isToken0_ Boolean indicating if this is for token0 (true) or token1 (false)\n    /// @return tokenDebt_ The calculated debt amount for the token\n    function _getLiquidityDebt(\n        bytes32 borrowTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenDebt_) {\n        uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);\n\n        tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;\n        tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);\n\n        if (tokenBorrowData_ & 1 == 1) {\n            // borrow with interest is on\n            unchecked {\n                tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenDebt_ = isToken0_\n                ? ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function _getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) internal view returns (DebtReserves memory d_) {\n        uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);\n        uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);\n\n        d_.token0Debt = token0Debt_;\n        d_.token1Debt = token1Debt_;\n\n        if (geometricMean_ < 1e27) {\n            (\n                d_.token0RealReserves,\n                d_.token1RealReserves,\n                d_.token0ImaginaryReserves,\n                d_.token1ImaginaryReserves\n            ) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (\n                d_.token1RealReserves,\n                d_.token0RealReserves,\n                d_.token1ImaginaryReserves,\n                d_.token0ImaginaryReserves\n            ) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_);\n        }\n    }\n\n    function _priceDiffCheck(uint oldPrice_, uint newPrice_) internal pure returns (int priceDiff_) {\n        // check newPrice_ & oldPrice_ difference should not be more than 5%\n        // old price w.r.t new price\n        priceDiff_ = int(ORACLE_PRECISION) - int((oldPrice_ * ORACLE_PRECISION) / newPrice_);\n\n        unchecked {\n            if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {\n                // if oracle price difference is more than 5% then revert\n                // in 1 swap price should only change by <= 5%\n                // if a total fall by let's say 8% then in current block price can only fall by 5% and\n                // in next block it'll fall the remaining 3%\n                revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);\n            }\n        }\n    }\n\n    function _updateOracle(uint newPrice_, uint centerPrice_, uint dexVariables_) internal returns (uint) {\n        // time difference between last & current swap\n        uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        uint temp_;\n        uint temp2_;\n        uint temp3_;\n\n        if (timeDiff_ == 0) {\n            // doesn't matter if oracle is on or off when timediff = 0 code for both is same\n\n            // temp_ => oldCenterPrice\n            temp_ = (dexVariables_ >> 81) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // Ensure that the center price is within the acceptable range of the old center price if it's not the first swap in the same block\n            unchecked {\n                if (\n                    (centerPrice_ < (((EIGHT_DECIMALS - 1) * temp_) / EIGHT_DECIMALS)) ||\n                    (centerPrice_ > (((EIGHT_DECIMALS + 1) * temp_) / EIGHT_DECIMALS))\n                ) {\n                    revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);\n                }\n            }\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n\n            // 2nd swap in same block no need to update anything around oracle, only need to update last swap price in dexVariables\n            return ((dexVariables_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41));\n        }\n\n        if (((dexVariables_ >> 195) & 1) == 0) {\n            // if oracle is not active then just returning updated DEX variable\n            temp_ = ((dexVariables_ >> 41) & X40);\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n            \n            return ((dexVariables_ & 0xfffffffffffffffffffffffffc00000000000000000000000000000000000001) |\n                (((dexVariables_ >> 41) & X40) << 1) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (centerPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121));\n        } else {\n            // oracle is active hence update oracle\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // oldPrice_ => temp2_\n            temp2_ = (dexVariables_ >> 41) & X40;\n            temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);\n\n            int priceDiff_ = _priceDiffCheck(temp2_, newPrice_);\n\n            unchecked {\n                // older price w.r.t old price\n                priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);\n            }\n\n            // priceDiffInPercentAndSign_ => temp3_\n            // priceDiff_ will always be lower than ORACLE_LIMIT due to above check\n            unchecked {\n                if (priceDiff_ < 0) {\n                    temp3_ = ((uint(-priceDiff_) * X22) / ORACLE_LIMIT) << 1;\n                } else {\n                    // if greater than or equal to 0 then make sign flag 1\n                    temp3_ = (((uint(priceDiff_) * X22) / ORACLE_LIMIT) << 1) | 1;\n                }\n            }\n\n            if (timeDiff_ > X22) {\n                // if time difference is this then that means DEX has been inactive ~45 days\n                // that means oracle price of this DEX should not be used.\n                timeDiff_ = X22;\n            }\n\n            // temp_ => lastTimeDiff_\n            temp_ = (dexVariables_ >> 154) & X22;\n            uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);\n            uint oracleMap_ = (dexVariables_ >> 179) & X16;\n            if (temp_ > X9) {\n                if (nextOracleSlot_ > 0) {\n                    // if greater than 0 then current slot has 2 or more oracle slot empty\n                    // First 9 bits are of time, so not using that\n                    temp3_ = (temp3_ << 41) | (temp_ << 9);\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));\n                    if (nextOracleSlot_ > 0) {\n                        --nextOracleSlot_;\n                    } else {\n                        // if == 0 that means the oracle slots will get filled and shift to next oracle map\n                        nextOracleSlot_ = 7;\n                        unchecked {\n                            oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                        }\n                        _oracle[oracleMap_] = 0;\n                    }\n                } else {\n                    // if == 0\n                    // then seconds will be in last map\n                    // precision will be in last map + 1\n                    // Storing precision & sign slot in first precision & sign slot and leaving time slot empty\n                    temp3_ = temp3_ << 9;\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;\n                    nextOracleSlot_ = 6; // storing 6 here as 7 is going to occupied right now\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    // Storing time in 2nd precision & sign and leaving time slot empty\n                    _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);\n                }\n            } else {\n                temp3_ = (temp3_ << 9) | temp_;\n                unchecked {\n                    if (nextOracleSlot_ < 7) {\n                        _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));\n                    } else {\n                        _oracle[oracleMap_] = temp3_ << ((7 * 32));\n                    }\n                }\n                if (nextOracleSlot_ > 0) {\n                    --nextOracleSlot_;\n                } else {\n                    nextOracleSlot_ = 7;\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    _oracle[oracleMap_] = 0;\n                }\n            }\n\n            // doing this due to stack too deep error when using params memory variables\n            temp_ = newPrice_;\n            temp2_ = centerPrice_;\n            temp3_ = dexVariables_;\n\n            // then update last price\n            return ((temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |\n                (((temp3_ >> 41) & X40) << 1) |\n                (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121) |\n                (timeDiff_ << 154) |\n                (nextOracleSlot_ << 176) |\n                (oracleMap_ << 179));\n        }\n    }\n\n    function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal {\n        try\n            IHook(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, hookAddress_)).dexPrice(\n                mode_,\n                swap0to1_,\n                TOKEN_0,\n                TOKEN_1,\n                price_\n            )\n        returns (bool isOk_) {\n            if (!isOk_) revert FluidDexError(ErrorTypes.DexT1__HookReturnedFalse);\n        } catch (bytes memory /*lowLevelData*/) {\n            // skip checking hook nothing\n        }\n    }\n\n    function _updateSupplyShares(uint newTotalShares_) internal {\n        uint totalSupplyShares_ = _totalSupplyShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max supply shares\n        if (\n            (newTotalShares_ > (totalSupplyShares_ & X128)) && \n            newTotalShares_ > (totalSupplyShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__SupplySharesOverflow);\n        }\n\n        // keeping max supply shares intact\n        _totalSupplyShares = ((totalSupplyShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    function _updateBorrowShares(uint newTotalShares_) internal {\n        uint totalBorrowShares_ = _totalBorrowShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max borrow shares\n        if (\n            (newTotalShares_ > (totalBorrowShares_ & X128)) && \n            newTotalShares_ > (totalBorrowShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__BorrowSharesOverflow);\n        }\n\n        // keeping max borrow shares intact\n        _totalBorrowShares = ((totalBorrowShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    constructor(ConstantViews memory constantViews_) ImmutableVariables(constantViews_) {}\n}\n"},"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { ConstantVariables } from \"../common/constantVariables.sol\";\nimport { IFluidDexFactory } from \"../../interfaces/iDexFactory.sol\";\nimport { Error } from \"../../error.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\n\nabstract contract ImmutableVariables is ConstantVariables, Structs, Error {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public immutable DEX_ID;\n\n    /// @dev Address of token 0\n    address internal immutable TOKEN_0;\n\n    /// @dev Address of token 1\n    address internal immutable TOKEN_1;\n\n    address internal immutable THIS_CONTRACT;\n\n    uint256 internal immutable TOKEN_0_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_0_DENOMINATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_DENOMINATOR_PRECISION;\n\n    /// @dev Address of liquidity contract\n    IFluidLiquidity internal immutable LIQUIDITY;\n\n    /// @dev Address of DEX factory contract\n    IFluidDexFactory internal immutable DEX_FACTORY;\n\n    /// @dev Address of Shift implementation\n    address internal immutable SHIFT_IMPLEMENTATION;\n\n    /// @dev Address of Admin implementation\n    address internal immutable ADMIN_IMPLEMENTATION;\n\n    /// @dev Address of Col Operations implementation\n    address internal immutable COL_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Debt Operations implementation\n    address internal immutable DEBT_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Perfect Operations and Swap Out implementation\n    address internal immutable PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n\n    /// @dev Address of contract used for deploying center price & hook related contract\n    address internal immutable DEPLOYER_CONTRACT;\n\n    /// @dev Liquidity layer slots\n    bytes32 internal immutable SUPPLY_TOKEN_0_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_0_SLOT;\n    bytes32 internal immutable SUPPLY_TOKEN_1_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_1_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_0_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_1_SLOT;\n    uint256 internal immutable TOTAL_ORACLE_MAPPING;\n\n    function _calcNumeratorAndDenominator(\n        address token_\n    ) private view returns (uint256 numerator_, uint256 denominator_) {\n        uint256 decimals_ = _decimals(token_);\n        if (decimals_ > TOKENS_DECIMALS_PRECISION) {\n            numerator_ = 1;\n            denominator_ = 10 ** (decimals_ - TOKENS_DECIMALS_PRECISION);\n        } else {\n            numerator_ = 10 ** (TOKENS_DECIMALS_PRECISION - decimals_);\n            denominator_ = 1;\n        }\n    }\n\n    constructor(ConstantViews memory constants_) {\n        THIS_CONTRACT = address(this);\n\n        DEX_ID = constants_.dexId;\n        LIQUIDITY = IFluidLiquidity(constants_.liquidity);\n        DEX_FACTORY = IFluidDexFactory(constants_.factory);\n\n        TOKEN_0 = constants_.token0;\n        TOKEN_1 = constants_.token1;\n\n        if (TOKEN_0 >= TOKEN_1) revert FluidDexError(ErrorTypes.DexT1__Token0ShouldBeSmallerThanToken1);\n\n        (TOKEN_0_NUMERATOR_PRECISION, TOKEN_0_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_0);\n        (TOKEN_1_NUMERATOR_PRECISION, TOKEN_1_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_1);\n\n        if (constants_.implementations.shift != address(0)) {\n            SHIFT_IMPLEMENTATION = constants_.implementations.shift;\n        } else {\n            SHIFT_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.admin != address(0)) {\n            ADMIN_IMPLEMENTATION = constants_.implementations.admin;\n        } else {\n            ADMIN_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.colOperations != address(0)) {\n            COL_OPERATIONS_IMPLEMENTATION = constants_.implementations.colOperations;\n        } else {\n            COL_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.debtOperations != address(0)) {\n            DEBT_OPERATIONS_IMPLEMENTATION = constants_.implementations.debtOperations;\n        } else {\n            DEBT_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.perfectOperationsAndSwapOut != address(0)) {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = constants_.implementations.perfectOperationsAndSwapOut;\n        } else {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = address(this);\n        }\n\n        DEPLOYER_CONTRACT = constants_.deployerContract;\n\n        SUPPLY_TOKEN_0_SLOT = constants_.supplyToken0Slot;\n        BORROW_TOKEN_0_SLOT = constants_.borrowToken0Slot;\n        SUPPLY_TOKEN_1_SLOT = constants_.supplyToken1Slot;\n        BORROW_TOKEN_1_SLOT = constants_.borrowToken1Slot;\n        EXCHANGE_PRICE_TOKEN_0_SLOT = constants_.exchangePriceToken0Slot;\n        EXCHANGE_PRICE_TOKEN_1_SLOT = constants_.exchangePriceToken1Slot;\n\n        if (constants_.oracleMapping > X16) revert FluidDexError(ErrorTypes.DexT1__OracleMappingOverflow);\n\n        TOTAL_ORACLE_MAPPING = constants_.oracleMapping;\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/interfaces.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface IHook {\n    /// @notice Hook function to check for liquidation opportunities before external swaps\n    /// @dev The primary use of this hook is to check if a particular pair vault has liquidation available.\n    ///      If liquidation is available, it gives priority to the liquidation process before allowing external swaps.\n    ///      In most cases, this hook will not be set.\n    /// @param id_ Identifier for the operation type: 1 for swap, 2 for internal arbitrage\n    /// @param swap0to1_ Direction of the swap: true if swapping token0 for token1, false otherwise\n    /// @param token0_ Address of the first token in the pair\n    /// @param token1_ Address of the second token in the pair\n    /// @param price_ The price ratio of token1 to token0, expressed with 27 decimal places\n    /// @return isOk_ Boolean indicating whether the operation should proceed\n    function dexPrice(\n        uint id_,\n        bool swap0to1_,\n        address token0_,\n        address token1_,\n        uint price_\n    ) external returns (bool isOk_);\n}\n\ninterface ICenterPrice {\n    /// @notice Retrieves the center price for the pool\n    /// @dev This function is marked as non-constant (potentially state-changing) to allow flexibility in price fetching mechanisms.\n    ///      While typically used as a read-only operation, this design permits write operations if needed for certain token pairs\n    ///      (e.g., fetching up-to-date exchange rates that may require state changes).\n    /// @return price The current price ratio of token1 to token0, expressed with 27 decimal places\n    function centerPrice() external returns (uint price);\n}\n"},"contracts/protocols/dex/poolT1/coreModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct ExchangePrices {\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct CollateralReservesSwap {\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReservesSwap {\n        uint tokenInDebt;\n        uint tokenOutDebt;\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct SwapInMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtInAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee; // fee of pool\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n    }\n\n    struct SwapOutMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtOutAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee;\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n        uint msgValue;\n    }\n\n    struct DepositColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n    }\n\n    struct WithdrawColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n        address to;\n    }\n\n    struct BorrowDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n        address to;\n    }\n\n    struct PaybackDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n    }\n\n    struct OraclePriceMemory {\n        uint lowestPrice1by0;\n        uint highestPrice1by0;\n        uint oracleSlot;\n        uint oracleMap;\n        uint oracle;\n    }\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndSwapOut;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n}\n"},"solmate/src/utils/FixedPointMathLib.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(\n        uint256 x,\n        uint256 n,\n        uint256 scalar\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\n    }\n}\n"}},"compilation":{"language":"Solidity","compiler":"solc","compilerVersion":"0.8.21+commit.d9974bed","compilerSettings":{"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"libraries":{},"optimizer":{"runs":10000000,"enabled":true},"evmVersion":"paris","remappings":[]},"name":"FluidDexT1","fullyQualifiedName":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},"abi":[{"type":"constructor","inputs":[{"name":"constantViews_","type":"tuple","components":[{"name":"dexId","type":"uint256","internalType":"uint256"},{"name":"liquidity","type":"address","internalType":"address"},{"name":"factory","type":"address","internalType":"address"},{"name":"implementations","type":"tuple","components":[{"name":"shift","type":"address","internalType":"address"},{"name":"admin","type":"address","internalType":"address"},{"name":"colOperations","type":"address","internalType":"address"},{"name":"debtOperations","type":"address","internalType":"address"},{"name":"perfectOperationsAndSwapOut","type":"address","internalType":"address"}],"internalType":"struct Structs.Implementations"},{"name":"deployerContract","type":"address","internalType":"address"},{"name":"token0","type":"address","internalType":"address"},{"name":"token1","type":"address","internalType":"address"},{"name":"supplyToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"supplyToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"oracleMapping","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews"}],"stateMutability":"nonpayable"},{"name":"FluidDexError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexFactoryError","type":"error","inputs":[{"name":"errorId","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexLiquidityOutput","type":"error","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexPerfectLiquidityOutput","type":"error","inputs":[{"name":"token0Amt","type":"uint256","internalType":"uint256"},{"name":"token1Amt","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexPricesAndExchangeRates","type":"error","inputs":[{"name":"pex_","type":"tuple","components":[{"name":"lastStoredPrice","type":"uint256","internalType":"uint256"},{"name":"centerPrice","type":"uint256","internalType":"uint256"},{"name":"upperRange","type":"uint256","internalType":"uint256"},{"name":"lowerRange","type":"uint256","internalType":"uint256"},{"name":"geometricMean","type":"uint256","internalType":"uint256"},{"name":"supplyToken0ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"borrowToken0ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"supplyToken1ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"borrowToken1ExchangePrice","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.PricesAndExchangePrice"}]},{"name":"FluidDexSingleTokenOutput","type":"error","inputs":[{"name":"tokenAmt","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexSwapResult","type":"error","inputs":[{"name":"amountOut","type":"uint256","internalType":"uint256"}]},{"name":"FluidLiquidityCalcsError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"FluidSafeTransferError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"LogArbitrage","type":"event","inputs":[{"name":"routing","type":"int256","indexed":false,"internalType":"int256"},{"name":"amtOut","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogBorrowDebtLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogBorrowPerfectDebtLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogDepositColLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogDepositPerfectColLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackDebtInOneToken","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackDebtLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackPerfectDebtLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawColInOneToken","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawColLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawPerfectColLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Swap","type":"event","inputs":[{"name":"swap0to1","type":"bool","indexed":false,"internalType":"bool"},{"name":"amountIn","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amountOut","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"to","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"name":"DEX_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"borrow","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"maxSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"borrowPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0Borrow_","type":"uint256","internalType":"uint256"},{"name":"minToken1Borrow_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"constantsView","type":"function","inputs":[],"outputs":[{"name":"constantsView_","type":"tuple","components":[{"name":"dexId","type":"uint256","internalType":"uint256"},{"name":"liquidity","type":"address","internalType":"address"},{"name":"factory","type":"address","internalType":"address"},{"name":"implementations","type":"tuple","components":[{"name":"shift","type":"address","internalType":"address"},{"name":"admin","type":"address","internalType":"address"},{"name":"colOperations","type":"address","internalType":"address"},{"name":"debtOperations","type":"address","internalType":"address"},{"name":"perfectOperationsAndSwapOut","type":"address","internalType":"address"}],"internalType":"struct Structs.Implementations"},{"name":"deployerContract","type":"address","internalType":"address"},{"name":"token0","type":"address","internalType":"address"},{"name":"token1","type":"address","internalType":"address"},{"name":"supplyToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"supplyToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"oracleMapping","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews"}],"stateMutability":"view"},{"name":"constantsView2","type":"function","inputs":[],"outputs":[{"name":"constantsView2_","type":"tuple","components":[{"name":"token0NumeratorPrecision","type":"uint256","internalType":"uint256"},{"name":"token0DenominatorPrecision","type":"uint256","internalType":"uint256"},{"name":"token1NumeratorPrecision","type":"uint256","internalType":"uint256"},{"name":"token1DenominatorPrecision","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews2"}],"stateMutability":"view"},{"name":"deposit","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"minSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"depositPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0Deposit_","type":"uint256","internalType":"uint256"},{"name":"maxToken1Deposit_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"getCollateralReserves","type":"function","inputs":[{"name":"geometricMean_","type":"uint256","internalType":"uint256"},{"name":"upperRange_","type":"uint256","internalType":"uint256"},{"name":"lowerRange_","type":"uint256","internalType":"uint256"},{"name":"token0SupplyExchangePrice_","type":"uint256","internalType":"uint256"},{"name":"token1SupplyExchangePrice_","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"c_","type":"tuple","components":[{"name":"token0RealReserves","type":"uint256","internalType":"uint256"},{"name":"token1RealReserves","type":"uint256","internalType":"uint256"},{"name":"token0ImaginaryReserves","type":"uint256","internalType":"uint256"},{"name":"token1ImaginaryReserves","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.CollateralReserves"}],"stateMutability":"view"},{"name":"getDebtReserves","type":"function","inputs":[{"name":"geometricMean_","type":"uint256","internalType":"uint256"},{"name":"upperRange_","type":"uint256","internalType":"uint256"},{"name":"lowerRange_","type":"uint256","internalType":"uint256"},{"name":"token0BorrowExchangePrice_","type":"uint256","internalType":"uint256"},{"name":"token1BorrowExchangePrice_","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"d_","type":"tuple","components":[{"name":"token0Debt","type":"uint256","internalType":"uint256"},{"name":"token1Debt","type":"uint256","internalType":"uint256"},{"name":"token0RealReserves","type":"uint256","internalType":"uint256"},{"name":"token1RealReserves","type":"uint256","internalType":"uint256"},{"name":"token0ImaginaryReserves","type":"uint256","internalType":"uint256"},{"name":"token1ImaginaryReserves","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.DebtReserves"}],"stateMutability":"view"},{"name":"getPricesAndExchangePrices","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"liquidityCallback","type":"function","inputs":[{"name":"token_","type":"address","internalType":"address"},{"name":"amount_","type":"uint256","internalType":"uint256"},{"name":"data_","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"oraclePrice","type":"function","inputs":[{"name":"secondsAgos_","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"twaps_","type":"tuple[]","components":[{"name":"twap1by0","type":"uint256","internalType":"uint256"},{"name":"lowestPrice1by0","type":"uint256","internalType":"uint256"},{"name":"highestPrice1by0","type":"uint256","internalType":"uint256"},{"name":"twap0by1","type":"uint256","internalType":"uint256"},{"name":"lowestPrice0by1","type":"uint256","internalType":"uint256"},{"name":"highestPrice0by1","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.Oracle[]"},{"name":"currentPrice_","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"payback","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"minSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"paybackPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0Payback_","type":"uint256","internalType":"uint256"},{"name":"maxToken1Payback_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"paybackPerfectInOneToken","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0_","type":"uint256","internalType":"uint256"},{"name":"maxToken1_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"paybackAmt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"readFromStorage","type":"function","inputs":[{"name":"slot_","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"result_","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"swapIn","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountIn_","type":"uint256","internalType":"uint256"},{"name":"amountOutMin_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountOut_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapInWithCallback","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountIn_","type":"uint256","internalType":"uint256"},{"name":"amountOutMin_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountOut_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapOut","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountOut_","type":"uint256","internalType":"uint256"},{"name":"amountInMax_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountIn_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapOutWithCallback","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountOut_","type":"uint256","internalType":"uint256"},{"name":"amountInMax_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountIn_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"withdraw","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"maxSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"withdrawPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0Withdraw_","type":"uint256","internalType":"uint256"},{"name":"minToken1Withdraw_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"withdrawPerfectInOneToken","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0_","type":"uint256","internalType":"uint256"},{"name":"minToken1_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"withdrawAmt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"receive","stateMutability":"payable"}],"metadata":{"compiler":{"version":"0.8.21+commit.d9974bed"},"language":"Solidity","output":{"abi":[{"inputs":[{"components":[{"internalType":"uint256","name":"dexId","type":"uint256"},{"internalType":"address","name":"liquidity","type":"address"},{"internalType":"address","name":"factory","type":"address"},{"components":[{"internalType":"address","name":"shift","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"colOperations","type":"address"},{"internalType":"address","name":"debtOperations","type":"address"},{"internalType":"address","name":"perfectOperationsAndSwapOut","type":"address"}],"internalType":"struct Structs.Implementations","name":"implementations","type":"tuple"},{"internalType":"address","name":"deployerContract","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"bytes32","name":"supplyToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"borrowToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"supplyToken1Slot","type":"bytes32"},{"internalType":"bytes32","name":"borrowToken1Slot","type":"bytes32"},{"internalType":"bytes32","name":"exchangePriceToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"exchangePriceToken1Slot","type":"bytes32"},{"internalType":"uint256","name":"oracleMapping","type":"uint256"}],"internalType":"struct Structs.ConstantViews","name":"constantViews_","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidDexError","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId","type":"uint256"}],"name":"FluidDexFactoryError","type":"error"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"name":"FluidDexLiquidityOutput","type":"error"},{"inputs":[{"internalType":"uint256","name":"token0Amt","type":"uint256"},{"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"FluidDexPerfectLiquidityOutput","type":"error"},{"inputs":[{"components":[{"internalType":"uint256","name":"lastStoredPrice","type":"uint256"},{"internalType":"uint256","name":"centerPrice","type":"uint256"},{"internalType":"uint256","name":"upperRange","type":"uint256"},{"internalType":"uint256","name":"lowerRange","type":"uint256"},{"internalType":"uint256","name":"geometricMean","type":"uint256"},{"internalType":"uint256","name":"supplyToken0ExchangePrice","type":"uint256"},{"internalType":"uint256","name":"borrowToken0ExchangePrice","type":"uint256"},{"internalType":"uint256","name":"supplyToken1ExchangePrice","type":"uint256"},{"internalType":"uint256","name":"borrowToken1ExchangePrice","type":"uint256"}],"internalType":"struct Structs.PricesAndExchangePrice","name":"pex_","type":"tuple"}],"name":"FluidDexPricesAndExchangeRates","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenAmt","type":"uint256"}],"name":"FluidDexSingleTokenOutput","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"FluidDexSwapResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidLiquidityCalcsError","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidSafeTransferError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int256","name":"routing","type":"int256"},{"indexed":false,"internalType":"uint256","name":"amtOut","type":"uint256"}],"name":"LogArbitrage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"LogBorrowDebtLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogBorrowPerfectDebtLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"LogDepositColLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogDepositPerfectColLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogPaybackDebtInOneToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"LogPaybackDebtLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogPaybackPerfectDebtLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogWithdrawColInOneToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"LogWithdrawColLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Amt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Amt","type":"uint256"}],"name":"LogWithdrawPerfectColLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"swap0to1","type":"bool"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEX_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"},{"internalType":"uint256","name":"maxSharesAmt_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"minToken0Borrow_","type":"uint256"},{"internalType":"uint256","name":"minToken1Borrow_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"borrowPerfect","outputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"constantsView","outputs":[{"components":[{"internalType":"uint256","name":"dexId","type":"uint256"},{"internalType":"address","name":"liquidity","type":"address"},{"internalType":"address","name":"factory","type":"address"},{"components":[{"internalType":"address","name":"shift","type":"address"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"colOperations","type":"address"},{"internalType":"address","name":"debtOperations","type":"address"},{"internalType":"address","name":"perfectOperationsAndSwapOut","type":"address"}],"internalType":"struct Structs.Implementations","name":"implementations","type":"tuple"},{"internalType":"address","name":"deployerContract","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"bytes32","name":"supplyToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"borrowToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"supplyToken1Slot","type":"bytes32"},{"internalType":"bytes32","name":"borrowToken1Slot","type":"bytes32"},{"internalType":"bytes32","name":"exchangePriceToken0Slot","type":"bytes32"},{"internalType":"bytes32","name":"exchangePriceToken1Slot","type":"bytes32"},{"internalType":"uint256","name":"oracleMapping","type":"uint256"}],"internalType":"struct Structs.ConstantViews","name":"constantsView_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"constantsView2","outputs":[{"components":[{"internalType":"uint256","name":"token0NumeratorPrecision","type":"uint256"},{"internalType":"uint256","name":"token0DenominatorPrecision","type":"uint256"},{"internalType":"uint256","name":"token1NumeratorPrecision","type":"uint256"},{"internalType":"uint256","name":"token1DenominatorPrecision","type":"uint256"}],"internalType":"struct Structs.ConstantViews2","name":"constantsView2_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"},{"internalType":"uint256","name":"minSharesAmt_","type":"uint256"},{"internalType":"bool","name":"estimate_","type":"bool"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"maxToken0Deposit_","type":"uint256"},{"internalType":"uint256","name":"maxToken1Deposit_","type":"uint256"},{"internalType":"bool","name":"estimate_","type":"bool"}],"name":"depositPerfect","outputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"geometricMean_","type":"uint256"},{"internalType":"uint256","name":"upperRange_","type":"uint256"},{"internalType":"uint256","name":"lowerRange_","type":"uint256"},{"internalType":"uint256","name":"token0SupplyExchangePrice_","type":"uint256"},{"internalType":"uint256","name":"token1SupplyExchangePrice_","type":"uint256"}],"name":"getCollateralReserves","outputs":[{"components":[{"internalType":"uint256","name":"token0RealReserves","type":"uint256"},{"internalType":"uint256","name":"token1RealReserves","type":"uint256"},{"internalType":"uint256","name":"token0ImaginaryReserves","type":"uint256"},{"internalType":"uint256","name":"token1ImaginaryReserves","type":"uint256"}],"internalType":"struct Structs.CollateralReserves","name":"c_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"geometricMean_","type":"uint256"},{"internalType":"uint256","name":"upperRange_","type":"uint256"},{"internalType":"uint256","name":"lowerRange_","type":"uint256"},{"internalType":"uint256","name":"token0BorrowExchangePrice_","type":"uint256"},{"internalType":"uint256","name":"token1BorrowExchangePrice_","type":"uint256"}],"name":"getDebtReserves","outputs":[{"components":[{"internalType":"uint256","name":"token0Debt","type":"uint256"},{"internalType":"uint256","name":"token1Debt","type":"uint256"},{"internalType":"uint256","name":"token0RealReserves","type":"uint256"},{"internalType":"uint256","name":"token1RealReserves","type":"uint256"},{"internalType":"uint256","name":"token0ImaginaryReserves","type":"uint256"},{"internalType":"uint256","name":"token1ImaginaryReserves","type":"uint256"}],"internalType":"struct Structs.DebtReserves","name":"d_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPricesAndExchangePrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"liquidityCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"secondsAgos_","type":"uint256[]"}],"name":"oraclePrice","outputs":[{"components":[{"internalType":"uint256","name":"twap1by0","type":"uint256"},{"internalType":"uint256","name":"lowestPrice1by0","type":"uint256"},{"internalType":"uint256","name":"highestPrice1by0","type":"uint256"},{"internalType":"uint256","name":"twap0by1","type":"uint256"},{"internalType":"uint256","name":"lowestPrice0by1","type":"uint256"},{"internalType":"uint256","name":"highestPrice0by1","type":"uint256"}],"internalType":"struct Structs.Oracle[]","name":"twaps_","type":"tuple[]"},{"internalType":"uint256","name":"currentPrice_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"},{"internalType":"uint256","name":"minSharesAmt_","type":"uint256"},{"internalType":"bool","name":"estimate_","type":"bool"}],"name":"payback","outputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"maxToken0Payback_","type":"uint256"},{"internalType":"uint256","name":"maxToken1Payback_","type":"uint256"},{"internalType":"bool","name":"estimate_","type":"bool"}],"name":"paybackPerfect","outputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"maxToken0_","type":"uint256"},{"internalType":"uint256","name":"maxToken1_","type":"uint256"},{"internalType":"bool","name":"estimate_","type":"bool"}],"name":"paybackPerfectInOneToken","outputs":[{"internalType":"uint256","name":"paybackAmt_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"slot_","type":"bytes32"}],"name":"readFromStorage","outputs":[{"internalType":"uint256","name":"result_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"swap0to1_","type":"bool"},{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"amountOutMin_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"swapIn","outputs":[{"internalType":"uint256","name":"amountOut_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"swap0to1_","type":"bool"},{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"amountOutMin_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"swapInWithCallback","outputs":[{"internalType":"uint256","name":"amountOut_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"swap0to1_","type":"bool"},{"internalType":"uint256","name":"amountOut_","type":"uint256"},{"internalType":"uint256","name":"amountInMax_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"swapOut","outputs":[{"internalType":"uint256","name":"amountIn_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"swap0to1_","type":"bool"},{"internalType":"uint256","name":"amountOut_","type":"uint256"},{"internalType":"uint256","name":"amountInMax_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"swapOutWithCallback","outputs":[{"internalType":"uint256","name":"amountIn_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"},{"internalType":"uint256","name":"maxSharesAmt_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"minToken0Withdraw_","type":"uint256"},{"internalType":"uint256","name":"minToken1Withdraw_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"withdrawPerfect","outputs":[{"internalType":"uint256","name":"token0Amt_","type":"uint256"},{"internalType":"uint256","name":"token1Amt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares_","type":"uint256"},{"internalType":"uint256","name":"minToken0_","type":"uint256"},{"internalType":"uint256","name":"minToken1_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"withdrawPerfectInOneToken","outputs":[{"internalType":"uint256","name":"withdrawAmt_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"devdoc":{"events":{"LogArbitrage(int256,uint256)":{"params":{"amtOut":"if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow","routing":"if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback"}},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"params":{"amount0":"Amount of token0 borrowed.","amount1":"Amount of token1 borrowed.","shares":"Amount of shares minted."}},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares minted","token0Amt":"Amount of token0 borrowed.","token1Amt":"Amount of token1 borrowed."}},"LogDepositColLiquidity(uint256,uint256,uint256)":{"params":{"amount0":"Amount of token0 deposited.","amount1":"Amount of token1 deposited.","shares":"Amount of shares minted."}},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Expected exact shares to be received.","token0Amt":"Amount of token1 deposited."}},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"params":{"amount0":"Amount of token0 paid back.","amount1":"Amount of token1 paid back.","shares":"Amount of shares burned."}},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"params":{"amount0":"Amount of token0 withdrawn.","amount1":"Amount of token1 withdrawn.","shares":"Amount of shares burned."}},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}},"Swap(bool,uint256,uint256,address)":{"params":{"amountIn":"The amount of tokens to be sent to the vault to swap.","amountOut":"The amount of tokens user got from the swap.","swap0to1":"Indicates whether the swap is from token0 to token1 or vice-versa.","to":"Recepient of swapped tokens."}}},"kind":"dev","methods":{"borrow(uint256,uint256,uint256,address)":{"details":"This function allows users to borrow tokens in any proportion from the debt pool","params":{"maxSharesAmt_":"The maximum amount of shares the user is willing to receive","to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to borrow","token1Amt_":"The amount of token1 to borrow"},"returns":{"shares_":"The amount of borrow shares minted to represent the borrowed amount"}},"borrowPerfect(uint256,uint256,uint256,address)":{"details":"This function allows users to borrow tokens in equal proportion to the current debt pool ratio","params":{"minToken0Borrow_":"Minimum amount of token0 to borrow","minToken1Borrow_":"Minimum amount of token1 to borrow","shares_":"The number of shares to borrow","to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_"},"returns":{"token0Amt_":"Amount of token0 borrowed","token1Amt_":"Amount of token1 borrowed"}},"deposit(uint256,uint256,uint256,bool)":{"details":"This function allows users to deposit tokens in any proportion into the col pool","params":{"estimate_":"If true, function will revert with estimated shares without executing the deposit","minSharesAmt_":"The minimum amount of shares the user expects to receive","token0Amt_":"The amount of token0 to deposit","token1Amt_":"The amount of token1 to deposit"},"returns":{"shares_":"The amount of shares minted for the deposit"}},"depositPerfect(uint256,uint256,uint256,bool)":{"details":"Deposit tokens in equal proportion to the current pool ratio","params":{"estimate_":"If true, function will revert with estimated deposit amounts without executing the deposit","maxToken0Deposit_":"Maximum amount of token0 to deposit","maxToken1Deposit_":"Maximum amount of token1 to deposit","shares_":"The number of shares to mint"},"returns":{"token0Amt_":"Amount of token0 deposited","token1Amt_":"Amount of token1 deposited"}},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"details":"This function retrieves the supply of both tokens from the liquidity layer,      adjusts them based on exchange prices, and calculates imaginary reserves      based on the geometric mean and price range","params":{"geometricMean_":"The geometric mean of the token prices","lowerRange_":"The lower price range","token0SupplyExchangePrice_":"The exchange price for token0 from liquidity layer","token1SupplyExchangePrice_":"The exchange price for token1 from liquidity layer","upperRange_":"The upper price range"},"returns":{"c_":"A struct containing the calculated real and imaginary reserves for both tokens:         - token0RealReserves: The real reserves of token0         - token1RealReserves: The real reserves of token1         - token0ImaginaryReserves: The imaginary reserves of token0         - token1ImaginaryReserves: The imaginary reserves of token1"}},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"params":{"geometricMean_":"The geometric mean of the upper and lower price ranges","lowerRange_":"The lower price range","token0BorrowExchangePrice_":"The exchange price of token0 from liquidity layer","token1BorrowExchangePrice_":"The exchange price of token1 from liquidity layer","upperRange_":"The upper price range"},"returns":{"d_":"The calculated debt reserves for both tokens, containing:         - token0Debt: The debt amount of token0         - token1Debt: The debt amount of token1         - token0RealReserves: The real reserves of token0 derived from token1 debt         - token1RealReserves: The real reserves of token1 derived from token0 debt         - token0ImaginaryReserves: The imaginary debt reserves of token0         - token1ImaginaryReserves: The imaginary debt reserves of token1"}},"liquidityCallback(address,uint256,bytes)":{"details":"liquidity callback for cheaper token transfers in case of deposit or payback. only callable by Liquidity during an operation."},"oraclePrice(uint256[])":{"details":"the oracle assumes last set price of pool till the next swap happens. There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration but the difference due to interest will be super low so this difference is ignored For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other. then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%","params":{"secondsAgos_":"array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]"},"returns":{"currentPrice_":"price of pool after the most recent swap","twaps_":"twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints"}},"payback(uint256,uint256,uint256,bool)":{"details":"This function allows users to payback tokens in any proportion to the debt pool","params":{"estimate_":"If true, function will revert with estimated shares without executing the payback","minSharesAmt_":"The minimum amount of shares the user expects to burn","token0Amt_":"The amount of token0 to payback","token1Amt_":"The amount of token1 to payback"},"returns":{"shares_":"The amount of borrow shares burned for the payback"}},"paybackPerfect(uint256,uint256,uint256,bool)":{"details":"This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio","params":{"estimate_":"If true, function will revert with estimated payback amounts without executing the payback","maxToken0Payback_":"Maximum amount of token0 to pay back","maxToken1Payback_":"Maximum amount of token1 to pay back","shares_":"The number of shares to pay back"},"returns":{"token0Amt_":"Amount of token0 paid back","token1Amt_":"Amount of token1 paid back"}},"paybackPerfectInOneToken(uint256,uint256,uint256,bool)":{"details":"This function allows users to payback their debt with perfect shares in one token","params":{"estimate_":"If true, the function will revert with the estimated payback amount without executing the payback","maxToken0_":"The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)","maxToken1_":"The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)","shares_":"The number of shares to burn for payback"},"returns":{"paybackAmt_":"The amount of tokens paid back in the chosen token"}},"swapIn(bool,uint256,uint256,address)":{"details":"Swap tokens with perfect amount in","params":{"amountIn_":"The exact amount of tokens to swap in","amountOutMin_":"The minimum amount of tokens to receive after swap","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_"},"returns":{"amountOut_":"The amount of output tokens received from the swap"}},"swapInWithCallback(bool,uint256,uint256,address)":{"details":"Swap tokens with perfect amount in and callback functionality","params":{"amountIn_":"The exact amount of tokens to swap in","amountOutMin_":"The minimum amount of tokens to receive after swap","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_"},"returns":{"amountOut_":"The amount of output tokens received from the swap"}},"swapOut(bool,uint256,uint256,address)":{"details":"Swap tokens with perfect amount out","params":{"amountInMax_":"Maximum amount of tokens to swap in","amountOut_":"The exact amount of tokens to receive after swap","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_"},"returns":{"amountIn_":"The amount of input tokens used for the swap"}},"swapOutWithCallback(bool,uint256,uint256,address)":{"details":"Swap tokens with perfect amount out and callback functionality","params":{"amountInMax_":"Maximum amount of tokens to swap in","amountOut_":"The exact amount of tokens to receive after swap","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_"},"returns":{"amountIn_":"The amount of input tokens used for the swap"}},"withdraw(uint256,uint256,uint256,address)":{"details":"This function allows users to withdraw tokens in any proportion from the col pool","params":{"maxSharesAmt_":"The maximum number of shares the user is willing to burn","to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to withdraw","token1Amt_":"The amount of token1 to withdraw"},"returns":{"shares_":"The number of shares burned for the withdrawal"}},"withdrawPerfect(uint256,uint256,uint256,address)":{"details":"This function allows users to withdraw a perfect amount of collateral liquidity","params":{"minToken0Withdraw_":"The minimum amount of token0 the user is willing to accept","minToken1Withdraw_":"The minimum amount of token1 the user is willing to accept","shares_":"The number of shares to withdraw","to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_"},"returns":{"token0Amt_":"The amount of token0 withdrawn","token1Amt_":"The amount of token1 withdrawn"}},"withdrawPerfectInOneToken(uint256,uint256,uint256,address)":{"details":"This function allows users to withdraw their collateral with perfect shares in one token","params":{"minToken0_":"The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)","minToken1_":"The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)","shares_":"The number of shares to burn for withdrawal","to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_"},"returns":{"withdrawAmt_":"The amount of tokens withdrawn in the chosen token"}}},"title":"FluidDexT1","version":1},"userdoc":{"errors":{"FluidDexSwapResult(uint256)":[{"notice":"used to simulate swap to find the output amount"}]},"events":{"LogArbitrage(int256,uint256)":{"notice":"Emitted when internal arbitrage between 2 pools happen"},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with specified token0 & token1 amount"},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with shares specified."},"LogDepositColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is deposited with specified token0 & token1 amount"},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is added with shares specified."},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified from one token only."},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with specified token0 & token1 amount"},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified."},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified into one token only."},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with specified token0 & token1 amount"},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified."},"Swap(bool,uint256,uint256,address)":{"notice":"Emitted on token swaps"}},"kind":"user","methods":{"constantsView()":{"notice":"returns all Vault constants"},"constantsView2()":{"notice":"returns all Vault constants"},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the real and imaginary reserves for collateral tokens"},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the debt reserves for both tokens"}},"notice":"Implements core logics for Fluid Dex protocol. Note Token transfers happen directly from user to Liquidity contract and vice-versa.","version":1}},"settings":{"compilationTarget":{"contracts/protocols/dex/poolT1/coreModule/core/main.sol":"FluidDexT1"},"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":10000000},"remappings":[]},"sources":{"contracts/infiniteProxy/interfaces/iProxy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IProxy {\n    function setAdmin(address newAdmin_) external;\n\n    function setDummyImplementation(address newDummyImplementation_) external;\n\n    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\n\n    function removeImplementation(address implementation_) external;\n\n    function getAdmin() external view returns (address);\n\n    function getDummyImplementation() external view returns (address);\n\n    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\n\n    function getSigsImplementation(bytes4 sig_) external view returns (address);\n\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n","keccak256":"0xbb605491d4bac08e816248feecae7dd17cfc1877c88b2e555abece2970f5ea00","license":"MIT"},"contracts/libraries/addressCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements calculation of address for contracts deployed through CREATE.\n/// Accepts contract deployed from which address & nonce\nlibrary AddressCalcs {\n\n    /// @notice                         Computes the address of a contract based\n    /// @param deployedFrom_            Address from which the contract was deployed\n    /// @param nonce_                   Nonce at which the contract was deployed\n    /// @return contract_               Address of deployed contract\n    function addressCalc(address deployedFrom_, uint nonce_) internal pure returns (address contract_) {\n        // @dev based on https://ethereum.stackexchange.com/a/61413\n\n        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment\n        // hence, nonce of vault deployment starts with 1.\n        bytes memory data;\n        if (nonce_ == 0x00) {\n            return address(0);\n        } else if (nonce_ <= 0x7f) {\n            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployedFrom_, uint8(nonce_));\n        } else if (nonce_ <= 0xff) {\n            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployedFrom_, bytes1(0x81), uint8(nonce_));\n        } else if (nonce_ <= 0xffff) {\n            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployedFrom_, bytes1(0x82), uint16(nonce_));\n        } else if (nonce_ <= 0xffffff) {\n            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployedFrom_, bytes1(0x83), uint24(nonce_));\n        } else {\n            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), deployedFrom_, bytes1(0x84), uint32(nonce_));\n        }\n\n        return address(uint160(uint256(keccak256(data))));\n    }\n\n}","keccak256":"0xca389bcfef035463ff43939ac5eccab07ab74cbb053e201541f9bcd846b3105a","license":"BUSL-1.1"},"contracts/libraries/bigMathMinified.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\n/// result in significant gas cost reduction due to storage space reduction.\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\nlibrary BigMathMinified {\n    /// @dev constants to use for `roundUp` input param to increase readability\n    bool internal constant ROUND_DOWN = false;\n    bool internal constant ROUND_UP = true;\n\n    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\n    /// e.g.:\n    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\n    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\n    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\n    ///                                                                        ^-------------------- 51(exponent) -------------- ^\n    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)\n    /// exponent =                                            0011,0011     (51)\n    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)\n    ///\n    /// @param normal number which needs to be converted into Big Number\n    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\n    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\n    /// @param roundUp signals if result should be rounded down or up\n    /// @return bigNumber converted bigNumber (coefficient << exponent)\n    function toBigNumber(\n        uint256 normal,\n        uint256 coefficientSize,\n        uint256 exponentSize,\n        bool roundUp\n    ) internal pure returns (uint256 bigNumber) {\n        assembly {\n            let lastBit_\n            let number_ := normal\n            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit_ := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit_ := add(lastBit_, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit_ := add(lastBit_, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit_ := add(lastBit_, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit_ := add(lastBit_, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit_ := add(lastBit_, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit_ := add(lastBit_, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if gt(number_, 0) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if lt(lastBit_, coefficientSize) {\n                // for throw exception\n                lastBit_ := coefficientSize\n            }\n            let exponent := sub(lastBit_, coefficientSize)\n            let coefficient := shr(exponent, normal)\n            if and(roundUp, gt(exponent, 0)) {\n                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\n                coefficient := add(coefficient, 1)\n                if eq(shl(coefficientSize, 1), coefficient) {\n                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\n                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\n                    coefficient := shl(sub(coefficientSize, 1), 1)\n                    exponent := add(exponent, 1)\n                }\n            }\n            if iszero(lt(exponent, shl(exponentSize, 1))) {\n                // if exponent is >= exponentSize, the normal number is too big to fit within\n                // BigNumber with too small sizes for coefficient and exponent\n                revert(0, 0)\n            }\n            bigNumber := shl(exponentSize, coefficient)\n            bigNumber := add(bigNumber, exponent)\n        }\n    }\n\n    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\n    function fromBigNumber(\n        uint256 bigNumber,\n        uint256 exponentSize,\n        uint256 exponentMask\n    ) internal pure returns (uint256 normal) {\n        assembly {\n            let coefficient := shr(exponentSize, bigNumber)\n            let exponent := and(bigNumber, exponentMask)\n            normal := shl(exponent, coefficient)\n        }\n    }\n\n    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\n    /// e.g.\n    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\n    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^\n    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\n        assembly {\n            let number_ := normal\n            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit := add(lastBit, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit := add(lastBit, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit := add(lastBit, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit := add(lastBit, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit := add(lastBit, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit := add(lastBit, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit := add(lastBit, 1)\n            }\n            if gt(number_, 0) {\n                lastBit := add(lastBit, 1)\n            }\n        }\n    }\n}\n","keccak256":"0xf0be1002909edf30aec3dc6623c2bd2407ed94064b62674c01032b844dec206a","license":"BUSL-1.1"},"contracts/libraries/dexCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\nimport { DexSlotsLink } from \"./dexSlotsLink.sol\";\n\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n// @DEV ATTENTION: ON ANY CHANGES HERE, MAKE SURE THAT LOGIC IN VAULTS WILL STILL BE VALID.\n// SOME CODE THERE ASSUMES DEXCALCS == LIQUIDITYCALCS.\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n/// @notice implements calculation methods used for Fluid Dex such as updated withdrawal / borrow limits.\nlibrary DexCalcs {\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) &\n            X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ = block.timestamp - ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ = block.timestamp - ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n}\n","keccak256":"0xd033a77bd57f4a608e693fdf6147ddd3bbfa0d80d86c1097d24e428c886c0d5e","license":"BUSL-1.1"},"contracts/libraries/dexSlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Dex.\n/// @dev as all data for Fluid Dex is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidDexResolver.\nlibrary DexSlotsLink {\n    /// @dev storage slot for variables at Dex\n    uint256 internal constant DEX_VARIABLES_SLOT = 0;\n    /// @dev storage slot for variables2 at Dex\n    uint256 internal constant DEX_VARIABLES2_SLOT = 1;\n    /// @dev storage slot for total supply shares at Dex\n    uint256 internal constant DEX_TOTAL_SUPPLY_SHARES_SLOT = 2;\n    /// @dev storage slot for user supply mapping at Dex\n    uint256 internal constant DEX_USER_SUPPLY_MAPPING_SLOT = 3;\n    /// @dev storage slot for total borrow shares at Dex\n    uint256 internal constant DEX_TOTAL_BORROW_SHARES_SLOT = 4;\n    /// @dev storage slot for user borrow mapping at Dex\n    uint256 internal constant DEX_USER_BORROW_MAPPING_SLOT = 5;\n    /// @dev storage slot for oracle mapping at Dex\n    uint256 internal constant DEX_ORACLE_MAPPING_SLOT = 6;\n    /// @dev storage slot for range and threshold shifts at Dex\n    uint256 internal constant DEX_RANGE_THRESHOLD_SHIFTS_SLOT = 7;\n    /// @dev storage slot for center price shift at Dex\n    uint256 internal constant DEX_CENTER_PRICE_SHIFT_SLOT = 8;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_ALLOWED = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_ALLOWED = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Dex contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Dex contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n","keccak256":"0xf1d6550d83fb0155a26655234922c9bdf4a1bbcf7a3ca767e9123d367a795307","license":"BUSL-1.1"},"contracts/libraries/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary LibsErrorTypes {\n    /***********************************|\n    |         LiquidityCalcs            | \n    |__________________________________*/\n\n    /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet)\n    uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001;\n\n    /// @notice thrown when rate data is set to a version that is not implemented\n    uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002;\n\n    /// @notice thrown when the calculated borrow rate turns negative. This should never happen.\n    uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003;\n\n    /***********************************|\n    |           SafeTransfer            | \n    |__________________________________*/\n\n    /// @notice thrown when safe transfer from for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFromFailed = 71001;\n\n    /// @notice thrown when safe transfer for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFailed = 71002;\n\n    /***********************************|\n    |           SafeApprove             | \n    |__________________________________*/\n\n    /// @notice thrown when safe approve from for an ERC20 fails\n    uint256 internal constant SafeApprove__ApproveFailed = 81001;\n}\n","keccak256":"0x4057f500fd44ce9e89049512d06d5f72c46f91938ed37312fb044c204451009b","license":"BUSL-1.1"},"contracts/libraries/liquidityCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\nimport { LiquiditySlotsLink } from \"./liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\n\n/// @notice implements calculation methods used for Fluid liquidity such as updated exchange prices,\n/// borrow rate, withdrawal / borrow limits, revenue amount.\nlibrary LiquidityCalcs {\n    error FluidLiquidityCalcsError(uint256 errorId_);\n\n    /// @notice emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\n    event BorrowRateMaxCap();\n\n    /// @dev constants as from Liquidity variables.sol\n    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n    /// @dev Ignoring leap years\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant TWELVE_DECIMALS = 1e12;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X15 = 0x7fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                  CALC EXCHANGE PRICES                  /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @return supplyExchangePrice_ updated supplyExchangePrice\n    /// @return borrowExchangePrice_ updated borrowExchangePrice\n    function calcExchangePrices(\n        uint256 exchangePricesAndConfig_\n    ) internal view returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\n        // Extracting exchange prices\n        supplyExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\n            X64;\n        borrowExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\n            X64;\n\n        if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\n        }\n\n        uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\n\n        unchecked {\n            // last timestamp can not be > current timestamp\n            uint256 secondsSinceLastUpdate_ = block.timestamp -\n                ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\n\n            uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\n                X15;\n            if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\n                // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\n                // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // calculate new borrow exchange price.\n            // formula borrowExchangePriceIncrease: previous price * borrow rate * secondsSinceLastUpdate_.\n            // nominator is max uint112 (uint64 * uint16 * uint32). Divisor can not be 0.\n            borrowExchangePrice_ +=\n                (borrowExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS);\n\n            // FOR SUPPLY EXCHANGE PRICE:\n            // all yield paid by borrowers (in mode with interest) goes to suppliers in mode with interest.\n            // formula: previous price * supply rate * secondsSinceLastUpdate_.\n            // where supply rate = (borrow rate  - revenueFee%) * ratioSupplyYield. And\n            // ratioSupplyYield = utilization * supplyRatio * borrowRatio\n            //\n            // Example:\n            // supplyRawInterest is 80, supplyInterestFree is 20. totalSupply is 100. BorrowedRawInterest is 50.\n            // BorrowInterestFree is 10. TotalBorrow is 60. borrow rate 40%, revenueFee 10%.\n            // yield is 10 (so half a year must have passed).\n            // supplyRawInterest must become worth 89. totalSupply must become 109. BorrowedRawInterest must become 60.\n            // borrowInterestFree must still be 10. supplyInterestFree still 20. totalBorrow 70.\n            // supplyExchangePrice would have to go from 1 to 1,125 (+ 0.125). borrowExchangePrice from 1 to 1,2 (+0.2).\n            // utilization is 60%. supplyRatio = 20 / 80 = 25% (only 80% of lenders receiving yield).\n            // borrowRatio = 10 / 50 = 20% (only 83,333% of borrowers paying yield):\n            // x of borrowers paying yield = 100% - (20 / (100 + 20)) = 100% - 16.6666666% = 83,333%.\n            // ratioSupplyYield = 60% * 83,33333% * (100% + 20%) = 62,5%\n            // supplyRate = (40% * (100% - 10%)) * = 36% * 62,5% = 22.5%\n            // increase in supplyExchangePrice, assuming 100 as previous price.\n            // 100 * 22,5% * 1/2 (half a year) = 0,1125.\n            // cross-check supplyRawInterest worth = 80 * 1.1125 = 89. totalSupply worth = 89 + 20.\n\n            // -------------- 1. calculate ratioSupplyYield --------------------------------\n            // step1: utilization * supplyRatio (or actually part of lenders receiving yield)\n\n            // temp_ => supplyRatio (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n            // if first bit 0 then ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n            // else ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n            temp_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) & X15;\n\n            if (temp_ == 1) {\n                // if no raw supply: no exchange price update needed\n                // (if supplyRatio_ == 1 means there is only supplyInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // ratioSupplyYield precision is 1e27 as 100% for increased precision when supplyInterestFree > supplyWithInterest\n            if (temp_ & 1 == 1) {\n                // ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n                temp_ = temp_ >> 1;\n\n                // Note: case where temp_ == 0 (only supplyInterestFree, no yield) already covered by early return\n                // in the if statement a little above.\n\n                // based on above example but supplyRawInterest is 20, supplyInterestFree is 80. no fee.\n                // supplyRawInterest must become worth 30. totalSupply must become 110.\n                // supplyExchangePrice would have to go from 1 to 1,5. borrowExchangePrice from 1 to 1,2.\n                // so ratioSupplyYield must come out as 2.5 (250%).\n                // supplyRatio would be (20 * 10_000 / 80) = 2500. but must be inverted.\n                temp_ = (1e27 * FOUR_DECIMALS) / temp_; // e.g. 1e31 / 2500 = 4e27. (* 1e27 for precision)\n                // e.g. 5_000 * (1e27 + 4e27) / 1e27 = 25_000 (=250%).\n                temp_ =\n                    // utilization * (100% + 100% / supplyRatio)\n                    (((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) *\n                        (1e27 + temp_)) / // extract utilization (max 16_383 so there is no way this can overflow).\n                    (FOUR_DECIMALS);\n                // max possible value of temp_ here is 16383 * (1e27 + 1e31) / 1e4 = ~1.64e31\n            } else {\n                // ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n                temp_ = temp_ >> 1;\n                // if temp_ == 0 then only supplyWithInterest => full yield. temp_ is already 0\n\n                // e.g. 5_000 * 10_000 + (20 * 10_000 / 80) / 10_000 = 5000 * 12500 / 10000 = 6250 (=62.5%).\n                temp_ =\n                    // 1e27 * utilization * (100% + supplyRatio) / 100%\n                    (1e27 *\n                        ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) * // extract utilization (max 16_383 so there is no way this can overflow).\n                        (FOUR_DECIMALS + temp_)) /\n                    (FOUR_DECIMALS * FOUR_DECIMALS);\n                // max possible temp_ value: 1e27 * 16383 * 2e4 / 1e8 = 3.2766e27\n            }\n            // from here temp_ => ratioSupplyYield (utilization * supplyRatio part) scaled by 1e27. max possible value ~1.64e31\n\n            // step2 of ratioSupplyYield: add borrowRatio (only x% of borrowers paying yield)\n            if (borrowRatio_ & 1 == 1) {\n                // ratio is borrowWithInterest / borrowInterestFree (borrowInterestFree is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n\n                // Note: case where borrowRatio_ == 0 (only borrowInterestFree, no yield) already covered\n                // at the beginning of the method by early return if `borrowRatio_ == 1`.\n\n                // based on above example but borrowRawInterest is 10, borrowInterestFree is 50. no fee. borrowRatio = 20%.\n                // so only 16.66% of borrowers are paying yield. so the 100% - part of the formula is not needed.\n                // x of borrowers paying yield = (borrowRatio / (100 + borrowRatio)) = 16.6666666%\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                borrowRatio_ = (borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_);\n                // max value here for borrowRatio_ is (1e31 / (1e4 + 1e4))= 5e26 (= 50% of borrowers paying yield).\n            } else {\n                // ratio is borrowInterestFree / borrowWithInterest (borrowWithInterest is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                // x of borrowers paying yield = 100% - (borrowRatio / (100 + borrowRatio)) = 100% - 16.6666666% = 83,333%.\n                borrowRatio_ = (1e27 - ((borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_)));\n                // borrowRatio can never be > 100%. so max subtraction can be 100% - 100% / 200%.\n                // or if borrowRatio_ is 0 -> 100% - 0. or if borrowRatio_ is 1 -> 100% - 1 / 101.\n                // max value here for borrowRatio_ is 1e27 - 0 = 1e27 (= 100% of borrowers paying yield).\n            }\n\n            // temp_ => ratioSupplyYield. scaled down from 1e25 = 1% each to normal percent precision 1e2 = 1%.\n            // max nominator value is ~1.64e31 * 1e27 = 1.64e58. max result = 1.64e8\n            temp_ = (FOUR_DECIMALS * temp_ * borrowRatio_) / 1e54;\n\n            // 2. calculate supply rate\n            // temp_ => supply rate (borrow rate  - revenueFee%) * ratioSupplyYield.\n            // division part is done in next step to increase precision. (divided by 2x FOUR_DECIMALS, fee + borrowRate)\n            // Note that all calculation divisions for supplyExchangePrice are rounded down.\n            // Note supply rate can be bigger than the borrowRate, e.g. if there are only few lenders with interest\n            // but more suppliers not earning interest.\n            temp_ = ((exchangePricesAndConfig_ & X16) * // borrow rate\n                temp_ * // ratioSupplyYield\n                (FOUR_DECIMALS - ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14))); // revenueFee\n            // fee can not be > 100%. max possible = 65535 * ~1.64e8 * 1e4 =~1.074774e17.\n\n            // 3. calculate increase in supply exchange price\n            supplyExchangePrice_ += ((supplyExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS * FOUR_DECIMALS * FOUR_DECIMALS));\n            // max possible nominator = max uint 64 * 1.074774e17 * max uint32 = ~8.52e45. Denominator can not be 0.\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                     CALC REVENUE                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from storage\n    /// and the current balance of the Fluid liquidity contract for the token.\n    /// @param totalAmounts_ total amounts packed uint256 read from storage\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @param liquidityTokenBalance_   current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\n    /// @return revenueAmount_ collectable revenue amount\n    function calcRevenue(\n        uint256 totalAmounts_,\n        uint256 exchangePricesAndConfig_,\n        uint256 liquidityTokenBalance_\n    ) internal view returns (uint256 revenueAmount_) {\n        // @dev no need to super-optimize this method as it is only used by admin\n\n        // calculate the new exchange prices based on earned interest\n        (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = calcExchangePrices(exchangePricesAndConfig_);\n\n        // total supply = interest free + with interest converted from raw\n        uint256 totalSupply_ = getTotalSupply(totalAmounts_, supplyExchangePrice_);\n\n        if (totalSupply_ > 0) {\n            // available revenue: balanceOf(token) + totalBorrowings - totalLendings.\n            revenueAmount_ = liquidityTokenBalance_ + getTotalBorrow(totalAmounts_, borrowExchangePrice_);\n            // ensure there is no possible case because of rounding etc. where this would revert,\n            // explicitly check if >\n            revenueAmount_ = revenueAmount_ > totalSupply_ ? revenueAmount_ - totalSupply_ : 0;\n            // Note: if utilization > 100% (totalSupply < totalBorrow), then all the amount above 100% utilization\n            // can only be revenue.\n        } else {\n            // if supply is 0, then rest of balance can be withdrawn as revenue so that no amounts get stuck\n            revenueAmount_ = liquidityTokenBalance_;\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >>\n            LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) & X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ =\n                block.timestamp -\n                ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ =\n                block.timestamp -\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC RATES                        /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev Calculates new borrow rate from utilization for a token\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_ totalBorrow / totalSupply. 1e4 = 100% utilization\n    /// @return rate_ rate for that particular token in 1e2 precision (e.g. 5% rate = 500)\n    function calcBorrowRateFromUtilization(uint256 rateData_, uint256 utilization_) internal returns (uint256 rate_) {\n        // extract rate version: 4 bits (0xF) starting from bit 0\n        uint256 rateVersion_ = (rateData_ & 0xF);\n\n        if (rateVersion_ == 1) {\n            rate_ = calcRateV1(rateData_, utilization_);\n        } else if (rateVersion_ == 2) {\n            rate_ = calcRateV2(rateData_, utilization_);\n        } else {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__UnsupportedRateVersion);\n        }\n\n        if (rate_ > X16) {\n            // hard cap for borrow rate at maximum value 16 bits (65535) to make sure it does not overflow storage space.\n            // this is unlikely to ever happen if configs stay within expected levels.\n            rate_ = X16;\n            // emit event to more easily become aware\n            emit BorrowRateMaxCap();\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 1 (with one kink) in 1e2 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e2 precision\n    function calcRateV1(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v1 (one kink) ------------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 188 bits =>  68-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // else utilization is greater than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;\n            x1_ = kink1_;\n            x2_ = FOUR_DECIMALS; // 100%\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 2 (with two kinks) in 1e4 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e4 precision\n    function calcRateV2(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v2 (two kinks) -----------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 156 bits => 100-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink1\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // extract kink2: 16 bits (0xFFFF) starting from bit 52\n            uint256 kink2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;\n            if (utilization_ < kink2_) {\n                // if utilization is less than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                x1_ = kink1_;\n                x2_ = kink2_;\n            } else {\n                // else utilization is greater than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;\n                x1_ = kink2_;\n                x2_ = FOUR_DECIMALS;\n            }\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev reads the total supply out of Liquidity packed storage `totalAmounts_` for `supplyExchangePrice_`\n    function getTotalSupply(\n        uint256 totalAmounts_,\n        uint256 supplyExchangePrice_\n    ) internal pure returns (uint256 totalSupply_) {\n        // totalSupply_ => supplyInterestFree\n        totalSupply_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\n        totalSupply_ = (totalSupply_ >> DEFAULT_EXPONENT_SIZE) << (totalSupply_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalSupplyRaw_ = totalAmounts_ & X64; // no shifting as supplyRaw is first 64 bits\n        totalSupplyRaw_ = (totalSupplyRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalSupplyRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalSupply = supplyInterestFree + supplyRawInterest normalized from raw\n        totalSupply_ += ((totalSupplyRaw_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n\n    /// @dev reads the total borrow out of Liquidity packed storage `totalAmounts_` for `borrowExchangePrice_`\n    function getTotalBorrow(\n        uint256 totalAmounts_,\n        uint256 borrowExchangePrice_\n    ) internal pure returns (uint256 totalBorrow_) {\n        // totalBorrow_ => borrowInterestFree\n        // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\n        totalBorrow_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\n        totalBorrow_ = (totalBorrow_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrow_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalBorrowRaw_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\n        totalBorrowRaw_ = (totalBorrowRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrowRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalBorrow = borrowInterestFree + borrowRawInterest normalized from raw\n        totalBorrow_ += ((totalBorrowRaw_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n}\n","keccak256":"0xa65e2f84b2c33769ceb6b28fbd3221be29da2f8ac96e4d8b8cea91948d81a707","license":"BUSL-1.1"},"contracts/libraries/liquiditySlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\nlibrary LiquiditySlotsLink {\n    /// @dev storage slot for status at Liquidity\n    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\n    /// @dev storage slot for auths mapping at Liquidity\n    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\n    /// @dev storage slot for guardians mapping at Liquidity\n    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\n    /// @dev storage slot for user class mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\n    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\n    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\n    /// @dev storage slot for rateData mapping at Liquidity\n    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\n    /// @dev storage slot for totalAmounts mapping at Liquidity\n    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\n    /// @dev storage slot for user supply double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\n    /// @dev storage slot for user borrow double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // ExchangePricesAndConfig\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\n    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\n    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\n    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\n\n    // RateData:\n    uint256 internal constant BITS_RATE_DATA_VERSION = 0;\n    // RateData: V1\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\n    // RateData: V2\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\n\n    // TotalAmounts\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_MODE = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\n\n    // Configs2\n    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n","keccak256":"0x0ae3e1d231bb6c14b54fc1f5ffa306edc0ac827a6a92279c77c0c09627fe08ae","license":"BUSL-1.1"},"contracts/libraries/safeTransfer.sol":{"content":"// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\n\n/// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom\nlibrary SafeTransfer {\n    uint256 internal constant MAX_NATIVE_TRANSFER_GAS = 20000; // pass max. 20k gas for native transfers\n\n    error FluidSafeTransferError(uint256 errorId_);\n\n    /// @dev Transfer `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    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63\n    function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from_\" argument.\n            mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 68), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of `token_` to `to_`.\n    /// If `token_` returns no value, non-reverting calls are assumed to be successful.\n    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95\n    function safeTransfer(address token_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 36), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of ` native token to `to_`.\n    /// Minimally modified from Solmate SafeTransferLib (Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L15-L25\n    function safeTransferNative(address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and store if it succeeded or not. Pass limited gas\n            success_ := call(MAX_NATIVE_TRANSFER_GAS, to_, amount_, 0, 0, 0, 0)\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n}\n","keccak256":"0x7f7d3a39d984c62e41c669a3d11deb899b3512ace9313263592575bf48a6e079","license":"MIT OR Apache-2.0"},"contracts/libraries/storageRead.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.\ncontract StorageRead {\n    function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {\n        assembly {\n            result_ := sload(slot_) // read value from the storage slot\n        }\n    }\n}\n","keccak256":"0x1b03dfe294c2f0376f7e34c3960fe7088d7ff44bb2ffd9cb2ac940486bfba8c9","license":"BUSL-1.1"},"contracts/liquidity/adminModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct AddressBool {\n        address addr;\n        bool value;\n    }\n\n    struct AddressUint256 {\n        address addr;\n        uint256 value;\n    }\n\n    /// @notice struct to set borrow rate data for version 1\n    struct RateDataV1Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\n        uint256 kink;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink;\n        ///\n        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set borrow rate data for version 2\n    struct RateDataV2Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\n        uint256 kink1;\n        ///\n        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\n        uint256 kink2;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink1;\n        ///\n        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\n        uint256 rateAtUtilizationKink2;\n        ///\n        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set token config\n    struct TokenConfig {\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\n        uint256 fee;\n        ///\n        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\n        uint256 threshold;\n        ///\n        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\n        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).\n        uint256 maxUtilization;\n    }\n\n    /// @notice struct to set user supply & withdrawal config\n    struct UserSupplyConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which withdrawal limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration withdrawal limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseWithdrawalLimit;\n    }\n\n    /// @notice struct to set user borrow & payback config\n    struct UserBorrowConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which debt limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration debt limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\n        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseDebtCeiling;\n        ///\n        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 maxDebtCeiling;\n    }\n}\n","keccak256":"0x10353c70015f27b880125cefab806dbed24a4458f187da66964f3ef60488f757","license":"BUSL-1.1"},"contracts/liquidity/interfaces/iLiquidity.sol":{"content":"//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IProxy } from \"../../infiniteProxy/interfaces/iProxy.sol\";\nimport { Structs as AdminModuleStructs } from \"../adminModule/structs.sol\";\n\ninterface IFluidLiquidityAdmin {\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\n    /// @param authsStatus_ array of structs setting allowed status for an address.\n    ///                     status true => add auth, false => remove auth\n    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\n\n    /// @notice adds/removes guardians. Only callable by Governance.\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\n    ///                         status true => add guardian, false => remove guardian\n    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\n\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n    /// @param revenueCollector_  new revenue collector address\n    function updateRevenueCollector(address revenueCollector_) external;\n\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n    /// @param newStatus_ new status\n    ///        status = 2 -> pause, status = 1 -> resume.\n    function changeStatus(uint256 newStatus_) external;\n\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\n    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\n\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\n    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\n\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n    ///         Only callable by Auths.\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\n    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\n\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n    ///         Only callable by Auths.\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\n    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\n\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\n\n    /// @notice sets a new withdrawal limit as the current limit for a certain user\n    /// @param user_ user address for which to update the withdrawal limit\n    /// @param token_ token address for which to update the withdrawal limit\n    /// @param newLimit_ new limit until which user supply can decrease to.\n    ///                  Important: input in raw. Must account for exchange price in input param calculation.\n    ///                  Note any limit that is < max expansion or > current user supply will set max expansion limit or\n    ///                  current user supply as limit respectively.\n    ///                  - set 0 to make maximum possible withdrawable: instant full expansion, and if that goes\n    ///                  below base limit then fully down to 0.\n    ///                  - set type(uint256).max to make current withdrawable 0 (sets current user supply as limit).\n    function updateUserWithdrawalLimit(address user_, address token_, uint256 newLimit_) external;\n\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\n\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to pause operations for\n    /// @param supplyTokens_  token addresses to pause withdrawals for\n    /// @param borrowTokens_  token addresses to pause borrowings for\n    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to unpause operations for\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\n    /// @param borrowTokens_  token addresses to unpause borrowings for\n    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\n    /// @param tokens_  array of tokens to collect revenue for\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\n    function collectRevenue(address[] calldata tokens_) external;\n\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\n    /// @param tokens_ tokens to update exchange prices for\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\n    function updateExchangePrices(\n        address[] calldata tokens_\n    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\n}\n\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\n    /// @notice Single function which handles supply, withdraw, borrow & payback\n    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\n    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\n    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\n    /// @param withdrawTo_ if withdrawal then to which address\n    /// @param borrowTo_ if borrow then to which address\n    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\n    /// @return memVar3_ updated supplyExchangePrice\n    /// @return memVar4_ updated borrowExchangePrice\n    /// @dev to trigger skipping in / out transfers (gas optimization):\n    /// -  ` callbackData_` MUST be encoded so that \"from\" address is the last 20 bytes in the last 32 bytes slot,\n    ///     also for native token operations where liquidityCallback is not triggered!\n    ///     from address must come at last position if there is more data. I.e. encode like:\n    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\n    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\n    /// -   this \"from\" address must match withdrawTo_ or borrowTo_ and must be == `msg.sender`\n    /// -   `callbackData_` must in addition to the from address as described above include bytes32 SKIP_TRANSFERS\n    ///     in the slot before (bytes 32 to 63)\n    /// -   `msg.value` must be 0.\n    /// -   Amounts must be either:\n    ///     -  supply(+) == borrow(+), withdraw(-) == payback(-).\n    ///     -  Liquidity must be on the winning side (deposit < borrow OR payback < withdraw).\n    function operate(\n        address token_,\n        int256 supplyAmount_,\n        int256 borrowAmount_,\n        address withdrawTo_,\n        address borrowTo_,\n        bytes calldata callbackData_\n    ) external payable returns (uint256 memVar3_, uint256 memVar4_);\n}\n\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\n","keccak256":"0x4aa83e84baa7c2f4d58b07a3eca4ab7fe7d6fc660898daaac338dc3f129c4123","license":"MIT"},"contracts/protocols/dex/error.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs } from \"./poolT1/coreModule/structs.sol\";\n\nabstract contract Error {\n    error FluidDexError(uint256 errorId_);\n\n    error FluidDexFactoryError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares_);\n\n    error FluidDexPricesAndExchangeRates(Structs.PricesAndExchangePrice pex_);\n}\n","keccak256":"0xfb70930e36c5c0d60e06fb1be8a6fffdfbc17d0ae9745582f4dda666e3b010aa","license":"BUSL-1.1"},"contracts/protocols/dex/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n    /***********************************|\n    |             DexT1                 | \n    |__________________________________*/\n\n    /// @notice thrown at reentrancy\n    uint256 internal constant DexT1__AlreadyEntered = 51001;\n\n    uint256 internal constant DexT1__NotAnAuth = 51002;\n\n    uint256 internal constant DexT1__SmartColNotEnabled = 51003;\n\n    uint256 internal constant DexT1__SmartDebtNotEnabled = 51004;\n\n    uint256 internal constant DexT1__PoolNotInitialized = 51005;\n\n    uint256 internal constant DexT1__TokenReservesTooLow = 51006;\n\n    uint256 internal constant DexT1__EthAndAmountInMisMatch = 51007;\n\n    uint256 internal constant DexT1__EthSentForNonNativeSwap = 51008;\n\n    uint256 internal constant DexT1__NoSwapRoute = 51009;\n\n    uint256 internal constant DexT1__NotEnoughAmountOut = 51010;\n\n    uint256 internal constant DexT1__LiquidityLayerTokenUtilizationCapReached = 51011;\n\n    uint256 internal constant DexT1__HookReturnedFalse = 51012;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserSupplyInNotOn = 51013;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserDebtInNotOn = 51014;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants to give on deposit\n    uint256 internal constant DexT1__AboveDepositMax = 51015;\n\n    uint256 internal constant DexT1__MsgValueLowOnDepositOrPayback = 51016;\n\n    uint256 internal constant DexT1__WithdrawLimitReached = 51017;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on withdraw\n    uint256 internal constant DexT1__BelowWithdrawMin = 51018;\n\n    uint256 internal constant DexT1__DebtLimitReached = 51019;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on borrow\n    uint256 internal constant DexT1__BelowBorrowMin = 51020;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants on payback\n    uint256 internal constant DexT1__AbovePaybackMax = 51021;\n\n    uint256 internal constant DexT1__InvalidDepositAmts = 51022;\n\n    uint256 internal constant DexT1__DepositAmtsZero = 51023;\n\n    uint256 internal constant DexT1__SharesMintedLess = 51024;\n\n    uint256 internal constant DexT1__WithdrawalNotEnough = 51025;\n\n    uint256 internal constant DexT1__InvalidWithdrawAmts = 51026;\n\n    uint256 internal constant DexT1__WithdrawAmtsZero = 51027;\n\n    uint256 internal constant DexT1__WithdrawExcessSharesBurn = 51028;\n\n    uint256 internal constant DexT1__InvalidBorrowAmts = 51029;\n\n    uint256 internal constant DexT1__BorrowAmtsZero = 51030;\n\n    uint256 internal constant DexT1__BorrowExcessSharesMinted = 51031;\n\n    uint256 internal constant DexT1__PaybackAmtTooHigh = 51032;\n\n    uint256 internal constant DexT1__InvalidPaybackAmts = 51033;\n\n    uint256 internal constant DexT1__PaybackAmtsZero = 51034;\n\n    uint256 internal constant DexT1__PaybackSharedBurnedLess = 51035;\n\n    uint256 internal constant DexT1__NothingToArbitrage = 51036;\n\n    uint256 internal constant DexT1__MsgSenderNotLiquidity = 51037;\n\n    // On liquidity callback reentrancy bit should be on\n    uint256 internal constant DexT1__ReentrancyBitShouldBeOn = 51038;\n\n    // Thrown is reentrancy is already on and someone tries to fetch oracle price. Should not be possible to this\n    uint256 internal constant DexT1__OraclePriceFetchAlreadyEntered = 51039;\n\n    // Thrown when swap changes the current price by more than 5%\n    uint256 internal constant DexT1__OracleUpdateHugeSwapDiff = 51040;\n\n    uint256 internal constant DexT1__Token0ShouldBeSmallerThanToken1 = 51041;\n\n    uint256 internal constant DexT1__OracleMappingOverflow = 51042;\n\n    /// @notice thrown if governance has paused the swapping & arbitrage so only perfect functions are usable\n    uint256 internal constant DexT1__SwapAndArbitragePaused = 51043;\n\n    uint256 internal constant DexT1__ExceedsAmountInMax = 51044;\n\n    /// @notice thrown if amount in is too high or too low\n    uint256 internal constant DexT1__SwapInLimitingAmounts = 51045;\n\n    /// @notice thrown if amount out is too high or too low\n    uint256 internal constant DexT1__SwapOutLimitingAmounts = 51046;\n\n    uint256 internal constant DexT1__MintAmtOverflow = 51047;\n\n    uint256 internal constant DexT1__BurnAmtOverflow = 51048;\n\n    uint256 internal constant DexT1__LimitingAmountsSwapAndNonPerfectActions = 51049;\n\n    uint256 internal constant DexT1__InsufficientOracleData = 51050;\n\n    uint256 internal constant DexT1__SharesAmountInsufficient = 51051;\n\n    uint256 internal constant DexT1__CenterPriceOutOfRange = 51052;\n\n    uint256 internal constant DexT1__DebtReservesTooLow = 51053;\n\n    uint256 internal constant DexT1__SwapAndDepositTooLowOrTooHigh = 51054;\n\n    uint256 internal constant DexT1__WithdrawAndSwapTooLowOrTooHigh = 51055;\n\n    uint256 internal constant DexT1__BorrowAndSwapTooLowOrTooHigh = 51056;\n\n    uint256 internal constant DexT1__SwapAndPaybackTooLowOrTooHigh = 51057;\n\n    uint256 internal constant DexT1__InvalidImplementation = 51058;\n\n    uint256 internal constant DexT1__OnlyDelegateCallAllowed = 51059;\n\n    uint256 internal constant DexT1__IncorrectDataLength = 51060;\n\n    uint256 internal constant DexT1__AmountToSendLessThanAmount = 51061;\n\n    uint256 internal constant DexT1__InvalidCollateralReserves = 51062;\n\n    uint256 internal constant DexT1__InvalidDebtReserves = 51063;\n\n    uint256 internal constant DexT1__SupplySharesOverflow = 51064;\n\n    uint256 internal constant DexT1__BorrowSharesOverflow = 51065;\n\n    uint256 internal constant DexT1__OracleNotActive = 51066;\n\n    /***********************************|\n    |            DEX Admin              | \n    |__________________________________*/\n\n    /// @notice thrown when pool is not initialized\n    uint256 internal constant DexT1Admin__PoolNotInitialized = 52001;\n\n    uint256 internal constant DexT1Admin__SmartColIsAlreadyOn = 52002;\n\n    uint256 internal constant DexT1Admin__SmartDebtIsAlreadyOn = 52003;\n\n    /// @notice thrown when any of the configs value overflow the maximum limit\n    uint256 internal constant DexT1Admin__ConfigOverflow = 52004;\n\n    uint256 internal constant DexT1Admin__AddressNotAContract = 52005;\n\n    uint256 internal constant DexT1Admin__InvalidParams = 52006;\n\n    uint256 internal constant DexT1Admin__UserNotDefined = 52007;\n\n    uint256 internal constant DexT1Admin__OnlyDelegateCallAllowed = 52008;\n\n    uint256 internal constant DexT1Admin__UnexpectedPoolState = 52009;\n\n    /// @notice thrown when trying to pause or unpause but user is already in the target pause state\n    uint256 internal constant DexT1Admin__InvalidPauseToggle = 52009;\n\n    /***********************************|\n    |            DEX Factory            | \n    |__________________________________*/\n\n    uint256 internal constant DexFactory__InvalidOperation = 53001;\n    uint256 internal constant DexFactory__Unauthorized = 53002;\n    uint256 internal constant DexFactory__SameTokenNotAllowed = 53003;\n    uint256 internal constant DexFactory__TokenConfigNotProper = 53004;\n    uint256 internal constant DexFactory__InvalidParams = 53005;\n    uint256 internal constant DexFactory__OnlyDelegateCallAllowed = 53006;\n    uint256 internal constant DexFactory__InvalidDexAddress = 53007;\n}\n","keccak256":"0xc1f51cbf40f6b5c904a1f3a455dc76ef6d4ab9625e1f604d11b72670a268b6fb","license":"BUSL-1.1"},"contracts/protocols/dex/interfaces/iDexFactory.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexFactory {\n    /// @notice Global auth is auth for all dexes\n    function isGlobalAuth(address auth_) external view returns (bool);\n\n    /// @notice Dex auth is auth for a specific dex\n    function isDexAuth(address vault_, address auth_) external view returns (bool);\n\n    /// @notice Total dexes deployed.\n    function totalDexes() external view returns (uint256);\n\n    /// @notice Compute dexAddress\n    function getDexAddress(uint256 dexId_) external view returns (address);\n\n    /// @notice read uint256 `result_` for a storage `slot_` key\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n","keccak256":"0xfc81e2f8de72dcf84022b69495996f59fe560cac430767f504de1064c32f550e","license":"MIT"},"contracts/protocols/dex/interfaces/iDexT1.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexT1 {\n    error FluidDexError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares);\n\n    error FluidDexPricesAndExchangeRates(PricesAndExchangePrice pex_);\n\n    /// @notice returns the dex id\n    function DEX_ID() external view returns (uint256);\n\n    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndOracle;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) external view returns (CollateralReserves memory c_);\n\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) external view returns (DebtReserves memory d_);\n\n    // reverts with FluidDexPricesAndExchangeRates(pex_);\n    function getPricesAndExchangePrices() external;\n\n    function constantsView() external view returns (ConstantViews memory constantsView_);\n\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_);\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param amountOutMin_ The minimum amount of output tokens the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) external payable returns (uint256 amountOut_);\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) external payable returns (uint256 amountIn_);\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) external returns (\n        uint withdrawAmt_\n    );\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) external payable returns (\n        uint paybackAmt_\n    );\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (\n        Oracle[] memory twaps_,\n        uint currentPrice_\n    );\n}\n","keccak256":"0xa405007cdd45409412ce0fe02a991cadbae17760bc15402c839375505f69d7b2","license":"MIT"},"contracts/protocols/dex/poolT1/common/constantVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { StorageRead } from \"../../../../libraries/storageRead.sol\";\n\ninterface ITokenDecimals {\n    function decimals() external view returns (uint8);\n}\n\nabstract contract ConstantVariables is StorageRead {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    address internal constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;\n\n    address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n    uint256 internal constant NATIVE_TOKEN_DECIMALS = 18;\n    address internal constant ADDRESS_DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint256 internal constant TOKENS_DECIMALS_PRECISION = 12;\n    uint256 internal constant TOKENS_DECIMALS = 1e12;\n\n    uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\n    uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant X2 = 0x3;\n    uint256 internal constant X3 = 0x7;\n    uint256 internal constant X5 = 0x1f;\n    uint256 internal constant X7 = 0x7f;\n    uint256 internal constant X8 = 0xff;\n    uint256 internal constant X9 = 0x1ff;\n    uint256 internal constant X10 = 0x3ff;\n    uint256 internal constant X11 = 0x7ff;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X17 = 0x1ffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X20 = 0xfffff;\n    uint256 internal constant X22 = 0x3fffff;\n    uint256 internal constant X23 = 0x7fffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X28 = 0xfffffff;\n    uint256 internal constant X30 = 0x3fffffff;\n    uint256 internal constant X32 = 0xffffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X40 = 0xffffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n    uint256 internal constant X96 = 0xffffffffffffffffffffffff;\n    uint256 internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n\n    uint256 internal constant TWO_DECIMALS = 1e2;\n    uint256 internal constant THREE_DECIMALS = 1e3;\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant FIVE_DECIMALS = 1e5;\n    uint256 internal constant SIX_DECIMALS = 1e6;\n    uint256 internal constant EIGHT_DECIMALS = 1e8;\n    uint256 internal constant NINE_DECIMALS = 1e9;\n\n    uint256 internal constant PRICE_PRECISION = 1e27;\n\n    uint256 internal constant ORACLE_PRECISION = 1e18; // 100%\n    uint256 internal constant ORACLE_LIMIT = 5 * 1e16; // 5%\n\n    /// after swap token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_SWAP\n    /// after swap token1 reserves should not be less than token0InToken1 / MINIMUM_LIQUIDITY_SWAP\n    uint256 internal constant MINIMUM_LIQUIDITY_SWAP = 1e4;\n\n    /// after user operations (deposit, withdraw, borrow, payback) token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    /// after user operations (deposit, withdraw, borrow, payback) token1 reserves should not be less than token0InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    uint256 internal constant MINIMUM_LIQUIDITY_USER_OPERATIONS = 1e6;\n\n    /// To skip transfers in liquidity layer if token in & out is same and liquidity layer is on the winning side\n    bytes32 internal constant SKIP_TRANSFERS = keccak256(bytes(\"SKIP_TRANSFERS\"));\n\n    function _decimals(address token_) internal view returns (uint256) {\n        return (token_ == NATIVE_TOKEN) ? NATIVE_TOKEN_DECIMALS : ITokenDecimals(token_).decimals();\n    }\n}\n","keccak256":"0xab697f39bfede319530bac2bc86e71e663c6b81de2bafea4255f2cc65f2b520b","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/common/variables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Variables {\n    /*//////////////////////////////////////////////////////////////\n                          STORAGE VARIABLES\n    //////////////////////////////////////////////////////////////*/\n\n    /// First 1 bit  => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\n    /// Next 40 bits => 1-40 => last to last stored price. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 41-80 => last stored price of pool. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 81-120 => center price. Center price from where the ranges will be calculated. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 33 bits => 121-153 => last interaction time stamp\n    /// Next 22 bits => 154-175 => max 4194303 seconds (~1165 hrs, ~48.5 days), time difference between last to last and last price stored\n    /// Next 3 bits  => 176-178 => oracle checkpoint, if 0 then first slot, if 7 then last slot\n    /// Next 16 bits => 179-194 => current mapping or oracle, after every 8 transaction it will increase by 1. Max capacity is 65535 but it can be lower than that check dexVariables2\n    /// Next 1 bit  => 195 => is oracle active?\n    uint internal dexVariables;\n\n    /// Next  1 bit  => 0 => is smart collateral enabled?\n    /// Next  1 bit  => 1 => is smart debt enabled?\n    /// Next 17 bits => 2-18 => fee (1% = 10000, max value: 100000 = 10%, fee should not be more than 10%)\n    /// Next  7 bits => 19-25 => revenue cut from fee (1 = 1%, 100 = 100%). If fee is 1000 = 0.1% and revenue cut is 10 = 10% then governance get 0.01% of every swap\n    /// Next  1 bit  => 26 => percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 20 bits => 27-46 => upperPercent (1% = 10000, max value: 104.8575%) upperRange - upperRange * upperPercent = centerPrice. Hence, upperRange = centerPrice / (1 - upperPercent)\n    /// Next 20 bits => 47-66 => lowerPercent. lowerRange = centerPrice - centerPrice * lowerPercent.\n    /// Next  1 bit  => 67 => threshold percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 10 bits => 68-77 => upper shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice > (centerPrice + (upperRange - centerPrice) * (1000 - upperShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 10 bits => 78-87 => lower shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice < (centerPrice - (centerPrice - lowerRange) * (1000 - lowerShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 24 bits => 88-111 => Shifting time (~194 days) (rate = (% up + % down) / time ?)\n    /// Next 30 bits => 112-131 => Address of center price if center price should be fetched externally, for example, for wstETH <> ETH pool, fetch wstETH exchange rate into stETH from wstETH contract.\n    /// Why fetch it externally? Because let's say pool width is 0.1% and wstETH temporarily got depeg of 0.5% then pool will start to shift to newer pricing\n    /// but we don't want pool to shift to 0.5% because we know the depeg will recover so to avoid the loss for users.\n    /// Next 30 bits => 142-171 => Hooks bits, calculate hook address by storing deployment nonce from factory.\n    /// Next 28 bits => 172-199 => max center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 28 bits => 200-227 => min center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 10 bits => 228-237 => utilization limit of token0. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 10 bits => 238-247 => utilization limit of token1. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 1  bit  => 248     => is center price shift active\n    /// Last 1  bit  => 255     => Pause swap & arbitrage (only perfect functions will be usable), if we need to pause entire DEX then that can be done through pausing DEX on Liquidity Layer\n    uint internal dexVariables2;\n\n    /// first 128 bits => 0-127 => total supply shares\n    /// last 128 bits => 128-255 => max supply shares\n    uint internal _totalSupplyShares;\n\n    /// @dev user supply data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userSupplyData. Hence exact same supply & borrow limit library can be used\n    /// First  1 bit  =>       0 => is user allowed to supply? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user supply amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user withdrawal limit; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383).\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (aka shares can be burned); BigMath: 10 | 8\n    /// Next  38 bits => 218-255 => empty for future use\n    mapping(address => uint) internal _userSupplyData;\n\n    /// first 128 bits => 0-127 => total borrow shares\n    /// last 128 bits => 128-255 => max borrow shares\n    uint internal _totalBorrowShares;\n\n    /// @dev user borrow data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userBorrowData. Hence exact same supply & borrow limit library function can be used\n    /// First  1 bit  =>       0 => is user allowed to borrow? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user debt amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user debt ceiling; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand debt ceiling percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base debt ceiling: below this, there's no debt ceiling limits; BigMath: 10 | 8\n    /// Next  18 bits => 218-235 => max debt ceiling: absolute maximum debt ceiling can expand to; BigMath: 10 | 8\n    /// Next  20 bits => 236-255 => empty for future use\n    mapping(address => uint) internal _userBorrowData;\n\n    /// Price difference between last swap of last block & last swap of new block\n    /// If last swap happened at Block B - 4 and next swap happened after 4 blocks at Block B then it will store that difference\n    /// considering time difference between these 4 blocks is 48 seconds, hence time will be stored as 48\n    /// New oracle update:\n    /// time to 9 bits and precision to 22 bits\n    /// if time exceeds 9 bits which is 511 sec or ~8.5 min then we will use 2 oracle slot to store the data\n    /// we will leave the both time slot as 0 and on first sign + precision slot we will store time and\n    /// on second sign + precision slot we will store sign & precision\n    /// First 9 bits =>   0-  8 => time, 511 seconds\n    /// Next   1 bit  =>  9     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  10- 31 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  32- 40 => time, 511 seconds\n    /// Next   1 bit  =>  41     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  42- 63 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  64- 72 => time, 511 seconds\n    /// Next   1 bit  =>  73     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  74- 95 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  96-104 => time, 511 seconds\n    /// Next   1 bit  => 105     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 106-127 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 128-136 => time, 511 seconds\n    /// Next   1 bit  => 137     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 138-159 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 160-168 => time, 511 seconds\n    /// Next   1 bit  => 169     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 170-191 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 192-200 => time, 511 seconds\n    /// Next   1 bit  => 201     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 202-223 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 224-232 => time, 511 seconds\n    /// Next   1 bit  => 233     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 234-255 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    mapping(uint => uint) internal _oracle;\n\n    /// First 20 bits =>  0-19 => old upper shift\n    /// Next  20 bits => 20-39 => old lower shift\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    uint128 internal _rangeShift;\n\n    /// First 10 bits =>  0- 9 => old upper shift\n    /// Next  10 bits => 10-19 => empty so we can use same helper function\n    /// Next  10 bits => 20-29 => old lower shift\n    /// Next  10 bits => 30-39 => empty so we can use same helper function\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    /// Next  24 bits => 93-116 => old threshold time\n    uint128 internal _thresholdShift;\n\n    /// Shifting is fuzzy and with time it'll keep on getting closer and then eventually get over\n    /// First 33 bits => 0 -32 => starting timestamp\n    /// Next  20 bits => 33-52 => % shift\n    /// Next  20 bits => 53-72 => time to shift that percent\n    uint256 internal _centerPriceShift;\n}\n","keccak256":"0x16b4df290f6f0b75669f726435b8d94fe0748c0a06720b694b9cded6832be722","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { CoreHelpers } from \"../helpers/coreHelpers.sol\";\nimport { SafeTransfer } from \"../../../../../libraries/safeTransfer.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IFluidDexT1 } from \"../../../interfaces/iDexT1.sol\";\n\ninterface IDexCallback {\n    function dexCallback(address token_, uint256 amount_) external;\n}\n\n/// @title FluidDexT1\n/// @notice Implements core logics for Fluid Dex protocol.\n/// Note Token transfers happen directly from user to Liquidity contract and vice-versa.\ncontract FluidDexT1 is CoreHelpers {\n    using BigMathMinified for uint256;\n\n    constructor(ConstantViews memory constantViews_) CoreHelpers(constantViews_) {\n        // any implementations should not be zero\n        if (\n            constantViews_.implementations.shift == address(0) ||\n            constantViews_.implementations.admin == address(0) ||\n            constantViews_.implementations.colOperations == address(0) ||\n            constantViews_.implementations.debtOperations == address(0) ||\n            constantViews_.implementations.perfectOperationsAndSwapOut == address(0)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__InvalidImplementation);\n        }\n    }\n\n    struct SwapInExtras {\n        address to;\n        uint amountOutMin;\n        bool isCallback;\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param extras_ Additional parameters for the swap:\n    ///   - to: Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    ///   - amountOutMin: The minimum amount of output tokens the user expects to receive\n    ///   - isCallback: If true, indicates that the input tokens should be transferred via a callback\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function _swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        SwapInExtras memory extras_\n    ) internal returns (uint256 amountOut_) {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);\n\n        _check(dexVariables_, dexVariables2_);\n\n        if (extras_.to == address(0)) extras_.to = msg.sender;\n\n        SwapInMemory memory s_;\n\n        if (swap0to1_) {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION;\n            }\n        } else {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION;\n            }\n        }\n\n        _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);\n\n        if (msg.value > 0) {\n            if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);\n            if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);\n        }\n\n        // is smart collateral pool enabled\n        uint temp_ = dexVariables2_ & 1;\n        // is smart debt pool enabled\n        uint temp2_ = (dexVariables2_ >> 1) & 1;\n\n        uint temp3_;\n        uint temp4_;\n\n        // extracting fee\n        temp3_ = ((dexVariables2_ >> 2) & X17);\n        unchecked {\n            // revenueCut in 6 decimals, to have proper precision\n            // if fee = 1% and revenue cut = 10% then revenueCut = 1e8 - (10000 * 10) = 99900000\n            s_.revenueCut = EIGHT_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_));\n            // fee in 4 decimals\n            // 1 - fee. If fee is 1% then withoutFee will be 1e6 - 1e4\n            // s_.fee => 1 - withdraw fee\n            s_.fee = SIX_DECIMALS - temp3_;\n        }\n\n        CollateralReservesSwap memory cs_;\n        DebtReservesSwap memory ds_;\n        if (temp_ == 1) {\n            // smart collateral is enabled\n            {\n                CollateralReserves memory c_ = _getCollateralReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.supplyToken0ExchangePrice,\n                    pex_.supplyToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token0RealReserves,\n                        c_.token1RealReserves,\n                        c_.token0ImaginaryReserves,\n                        c_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token1RealReserves,\n                        c_.token0RealReserves,\n                        c_.token1ImaginaryReserves,\n                        c_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        if (temp2_ == 1) {\n            // smart debt is enabled\n            {\n                DebtReserves memory d_ = _getDebtReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.borrowToken0ExchangePrice,\n                    pex_.borrowToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token0Debt,\n                        d_.token1Debt,\n                        d_.token0RealReserves,\n                        d_.token1RealReserves,\n                        d_.token0ImaginaryReserves,\n                        d_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token1Debt,\n                        d_.token0Debt,\n                        d_.token1RealReserves,\n                        d_.token0RealReserves,\n                        d_.token1ImaginaryReserves,\n                        d_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        // limiting amtInAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenIn reserves combined\n        // basically, if this throws that means user is trying to swap 0.5x tokenIn if current tokenIn imaginary reserves is x\n        // let's take x as token0 here, that means, initially the pool pricing might be:\n        // token1Reserve / x and new pool pricing will become token1Reserve / 1.5x (token1Reserve will decrease after swap but for simplicity ignoring that)\n        // So pool price is decreased by ~33.33% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand)\n        unchecked {\n            if (s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2))\n                revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);\n        }\n\n        if (temp_ == 1 && temp2_ == 1) {\n            // unless both pools are enabled s_.swapRoutingAmt will be 0\n            s_.swapRoutingAmt = _swapRoutingIn(\n                s_.amtInAdjusted,\n                cs_.tokenOutImaginaryReserves,\n                cs_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves,\n                ds_.tokenInImaginaryReserves\n            );\n        }\n\n        // In below if else statement temps are:\n        // temp_ => deposit amt\n        // temp2_ => withdraw amt\n        // temp3_ => payback amt\n        // temp4_ => borrow amt\n        if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {\n            // swap will route from the both pools\n            // temp_ = amountInCol_\n            temp_ = uint(s_.swapRoutingAmt);\n            unchecked {\n                // temp3_ = amountInDebt_\n                temp3_ = s_.amtInAdjusted - temp_;\n            }\n\n            (temp2_, temp4_) = (0, 0);\n\n            // debt pool price will be the same as collateral pool after the swap\n            s_.withdrawTo = extras_.to;\n            s_.borrowTo = extras_.to;\n        } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {\n            // entire swap will route through collateral pool\n            (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);\n            // price can slightly differ from debt pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.withdrawTo = extras_.to;\n        } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {\n            // entire swap will route through debt pool\n            (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);\n            // price can slightly differ from collateral pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.borrowTo = extras_.to;\n        } else {\n            // swap should never reach this point but if it does then reverting\n            revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);\n        }\n\n        if (temp_ > 0) {\n            // temp2_ = amountOutCol_\n            temp2_ = _getAmountOut(\n                ((temp_ * s_.fee) / SIX_DECIMALS),\n                cs_.tokenInImaginaryReserves,\n                cs_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (cs_.tokenInRealReserves + temp_),\n                    (cs_.tokenOutRealReserves - temp2_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (cs_.tokenOutRealReserves - temp2_),\n                    (cs_.tokenInRealReserves + temp_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n        if (temp3_ > 0) {\n            // temp4_ = amountOutDebt_\n            temp4_ = _getAmountOut(\n                ((temp3_ * s_.fee) / SIX_DECIMALS),\n                ds_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (ds_.tokenInRealReserves + temp3_),\n                    (ds_.tokenOutRealReserves - temp4_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (ds_.tokenOutRealReserves - temp4_),\n                    (ds_.tokenInRealReserves + temp3_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n\n        // (temp_ + temp3_) == amountIn_ == msg.value (for native token), if there is revenue cut then this statement is not true\n        temp_ = (temp_ * s_.revenueCut) / EIGHT_DECIMALS;\n        temp3_ = (temp3_ * s_.revenueCut) / EIGHT_DECIMALS;\n\n        // from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same\n        if (temp_ > temp3_) {\n            // new pool price from col pool\n            s_.price = swap0to1_\n                ? ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_)\n                : ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);\n        } else {\n            // new pool price from debt pool\n            s_.price = swap0to1_\n                ? ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_)\n                : ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);\n        }\n\n        // converting into normal token amounts\n        if (swap0to1_) {\n            temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            }\n        } else {\n            temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            }\n        }\n\n        unchecked {\n            amountOut_ = temp2_ + temp4_;\n        }\n\n        // if address dead then reverting with amountOut\n        if (extras_.to == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);\n\n        if (amountOut_ < extras_.amountOutMin) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);\n\n        // allocating to avoid stack-too-deep error\n        // not setting in the callbackData as last 2nd to avoid SKIP_TRANSFERS clashing\n        s_.data = abi.encode(amountIn_, extras_.isCallback, msg.sender); // true/false is to decide if dex should do callback or directly transfer from user\n        // deposit & payback token in at liquidity\n        LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);\n        // withdraw & borrow token out at liquidity\n        LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));\n\n        // if hook exists then calling hook\n        temp_ = (dexVariables2_ >> 142) & X30;\n        if (temp_ > 0) {\n            s_.swap0to1 = swap0to1_;\n            _hookVerify(temp_, 1, s_.swap0to1, s_.price);\n        }\n\n        swap0to1_\n            ? _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT)\n            : _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);\n\n        dexVariables = _updateOracle(s_.price, pex_.centerPrice, dexVariables_);\n\n        emit Swap(swap0to1_, amountIn_, amountOut_, extras_.to);\n    }\n\n    /// @dev Swap tokens with perfect amount in\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, false));\n    }\n\n    /// @dev Swap tokens with perfect amount in and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapInWithCallback(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, true));\n    }\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Swap tokens with perfect amount out and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOutWithCallback(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) public returns (uint withdrawAmt_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) public payable returns (uint paybackAmt_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev liquidity callback for cheaper token transfers in case of deposit or payback.\n    /// only callable by Liquidity during an operation.\n    function liquidityCallback(address token_, uint amount_, bytes calldata data_) external {\n        if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity);\n        if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn);\n        if (data_.length != 96) revert FluidDexError(ErrorTypes.DexT1__IncorrectDataLength);\n\n        (uint amountToSend_, bool isCallback_, address from_) = abi.decode(data_, (uint, bool, address));\n\n        if (amountToSend_ < amount_) revert FluidDexError(ErrorTypes.DexT1__AmountToSendLessThanAmount);\n\n        if (isCallback_) {\n            IDexCallback(from_).dexCallback(token_, amountToSend_);\n        } else {\n            SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountToSend_);\n        }\n    }\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (Oracle[] memory twaps_, uint currentPrice_) {\n        OraclePriceMemory memory o_;\n\n        uint dexVariables_ = dexVariables;\n\n        if ((dexVariables_ >> 195) & 1 == 0) {\n            revert FluidDexError(ErrorTypes.DexT1__OracleNotActive);\n        }\n\n        twaps_ = new Oracle[](secondsAgos_.length);\n\n        uint totalTime_;\n        uint time_;\n\n        uint i;\n        uint secondsAgo_ = secondsAgos_[0];\n\n        currentPrice_ = (dexVariables_ >> 41) & X40;\n        currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);\n        uint price_ = currentPrice_;\n        o_.lowestPrice1by0 = currentPrice_;\n        o_.highestPrice1by0 = currentPrice_;\n\n        uint twap1by0_;\n        uint twap0by1_;\n\n        uint j;\n\n        o_.oracleSlot = (dexVariables_ >> 176) & X3;\n        o_.oracleMap = (dexVariables_ >> 179) & X16;\n        // if o_.oracleSlot == 7 then it'll enter the if statement in the below while loop\n        o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;\n\n        uint slotData_;\n        uint percentDiff_;\n\n        if (((dexVariables_ >> 121) & X33) < block.timestamp) {\n            // last swap didn't occured in this block.\n            // hence last price is current price of pool & also the last price\n            time_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        } else {\n            // last swap occured in this block, that means current price is active for 0 secs. Hence TWAP for it will be 0.\n            ++j;\n        }\n\n        while (true) {\n            if (j == 2) {\n                if (++o_.oracleSlot == 8) {\n                    o_.oracleSlot = 0;\n                    if (o_.oracleMap == 0) {\n                        o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                    }\n                    o_.oracle = _oracle[--o_.oracleMap];\n                }\n\n                slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                if (slotData_ > 0) {\n                    time_ = slotData_ & X9;\n                    if (time_ == 0) {\n                        // time is in precision & sign bits\n                        time_ = slotData_ >> 9;\n                        // if o_.oracleSlot is 7 then precision & bits and stored in 1 less map\n                        if (o_.oracleSlot == 7) {\n                            o_.oracleSlot = 0;\n                            if (o_.oracleMap == 0) {\n                                o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                            }\n                            o_.oracle = _oracle[--o_.oracleMap];\n                            slotData_ = o_.oracle & X32;\n                        } else {\n                            ++o_.oracleSlot;\n                            slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                        }\n                    }\n                    percentDiff_ = slotData_ >> 10;\n                    percentDiff_ = (ORACLE_LIMIT * percentDiff_) / X22;\n                    if (((slotData_ >> 9) & 1 == 1)) {\n                        // if positive then old price was lower than current hence subtracting\n                        price_ = price_ - (price_ * percentDiff_) / ORACLE_PRECISION;\n                    } else {\n                        // if negative then old price was higher than current hence adding\n                        price_ = price_ + (price_ * percentDiff_) / ORACLE_PRECISION;\n                    }\n                } else {\n                    // oracle data does not exist. Probably due to pool recently got initialized and not have much swaps.\n                    revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);\n                }\n            } else if (j == 1) {\n                // last & last to last price\n                price_ = (dexVariables_ >> 1) & X40;\n                price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);\n                time_ = (dexVariables_ >> 154) & X22;\n                ++j;\n            } else if (j == 0) {\n                ++j;\n            }\n\n            totalTime_ += time_;\n            if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;\n            if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;\n            if (totalTime_ < secondsAgo_) {\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n            } else {\n                time_ = time_ + secondsAgo_ - totalTime_;\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n                // also auto checks that secondsAgos_ should not be == 0\n                twap1by0_ = twap1by0_ / secondsAgo_;\n                twap0by1_ = twap0by1_ / secondsAgo_;\n\n                twaps_[i] = Oracle(\n                    twap1by0_,\n                    o_.lowestPrice1by0,\n                    o_.highestPrice1by0,\n                    twap0by1_,\n                    (1e54 / o_.highestPrice1by0),\n                    (1e54 / o_.lowestPrice1by0)\n                );\n\n                // TWAP for next secondsAgo will start with price_\n                o_.lowestPrice1by0 = price_;\n                o_.highestPrice1by0 = price_;\n\n                while (++i < secondsAgos_.length) {\n                    // secondsAgo_ = [60, 15, 0]\n                    time_ = totalTime_ - secondsAgo_;\n                    // updating total time as new seconds ago started\n                    totalTime_ = time_;\n                    // also auto checks that secondsAgos_[i + 1] > secondsAgos_[i]\n                    secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];\n                    if (totalTime_ < secondsAgo_) {\n                        twap1by0_ = price_ * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        // if time_ comes out as 0 here then lowestPrice & highestPrice should not be price_, it should be next price_ that we will calculate\n                        if (time_ == 0) {\n                            o_.lowestPrice1by0 = type(uint).max;\n                            o_.highestPrice1by0 = 0;\n                        }\n                        break;\n                    } else {\n                        time_ = time_ + secondsAgo_ - totalTime_;\n                        // twap1by0_ = price_ here\n                        twap1by0_ = price_ * time_;\n                        // twap0by1_ = (1e54 / price_) * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        twap1by0_ = twap1by0_ / secondsAgo_;\n                        twap0by1_ = twap0by1_ / secondsAgo_;\n                        twaps_[i] = Oracle(\n                            twap1by0_,\n                            o_.lowestPrice1by0,\n                            o_.highestPrice1by0,\n                            twap0by1_,\n                            (1e54 / o_.highestPrice1by0),\n                            (1e54 / o_.lowestPrice1by0)\n                        );\n                    }\n                }\n                if (i == secondsAgos_.length) return (twaps_, currentPrice_); // oracle fetch over\n            }\n        }\n    }\n\n    function getPricesAndExchangePrices() public {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        _check(dexVariables_, dexVariables2_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables, dexVariables2);\n\n        revert FluidDexPricesAndExchangeRates(pex_);\n    }\n\n    /// @dev Internal fallback function to handle calls to non-existent functions\n    /// @notice This function is called when a transaction is sent to the contract without matching any other function\n    /// @notice It checks if the caller is authorized, enables re-entrancy protection, delegates the call to the admin implementation, and then disables re-entrancy protection\n    /// @notice Only authorized callers (global or dex auth) can trigger this function\n    /// @notice This function uses assembly to perform a delegatecall to the admin implementation to update configs related to DEX\n    function _fallback() private {\n        if (!(DEX_FACTORY.isGlobalAuth(msg.sender) || DEX_FACTORY.isDexAuth(address(this), msg.sender))) {\n            revert FluidDexError(ErrorTypes.DexT1__NotAnAuth);\n        }\n\n        uint dexVariables_ = dexVariables;\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n\n        // Delegate the current call to `ADMIN_IMPLEMENTATION`.\n        _spell(ADMIN_IMPLEMENTATION, msg.data);\n\n        // disabling re-entrancy\n        // directly fetching from storage so updates from Admin module will get auto covered\n        dexVariables = dexVariables & ~uint(1);\n    }\n\n    fallback() external payable {\n        _fallback();\n    }\n\n    receive() external payable {\n        if (msg.sig != 0x00000000) {\n            _fallback();\n        }\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView() external view returns (ConstantViews memory constantsView_) {\n        constantsView_.dexId = DEX_ID;\n        constantsView_.liquidity = address(LIQUIDITY);\n        constantsView_.factory = address(DEX_FACTORY);\n        constantsView_.token0 = TOKEN_0;\n        constantsView_.token1 = TOKEN_1;\n        constantsView_.implementations.shift = SHIFT_IMPLEMENTATION;\n        constantsView_.implementations.admin = ADMIN_IMPLEMENTATION;\n        constantsView_.implementations.colOperations = COL_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.debtOperations = DEBT_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.perfectOperationsAndSwapOut = PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n        constantsView_.deployerContract = DEPLOYER_CONTRACT;\n        constantsView_.supplyToken0Slot = SUPPLY_TOKEN_0_SLOT;\n        constantsView_.borrowToken0Slot = BORROW_TOKEN_0_SLOT;\n        constantsView_.supplyToken1Slot = SUPPLY_TOKEN_1_SLOT;\n        constantsView_.borrowToken1Slot = BORROW_TOKEN_1_SLOT;\n        constantsView_.exchangePriceToken0Slot = EXCHANGE_PRICE_TOKEN_0_SLOT;\n        constantsView_.exchangePriceToken1Slot = EXCHANGE_PRICE_TOKEN_1_SLOT;\n        constantsView_.oracleMapping = TOTAL_ORACLE_MAPPING;\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_) {\n        constantsView2_.token0NumeratorPrecision = TOKEN_0_NUMERATOR_PRECISION;\n        constantsView2_.token0DenominatorPrecision = TOKEN_0_DENOMINATOR_PRECISION;\n        constantsView2_.token1NumeratorPrecision = TOKEN_1_NUMERATOR_PRECISION;\n        constantsView2_.token1DenominatorPrecision = TOKEN_1_DENOMINATOR_PRECISION;\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) public view returns (CollateralReserves memory c_) {\n        return\n            _getCollateralReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0SupplyExchangePrice_,\n                token1SupplyExchangePrice_\n            );\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) public view returns (DebtReserves memory d_) {\n        return\n            _getDebtReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0BorrowExchangePrice_,\n                token1BorrowExchangePrice_\n            );\n    }\n}\n","keccak256":"0xd50c8b8f72d8d9de610e1367e0d400a7eb9dd80a7826d13fffcfab7f50326908","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/events.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n    /// @notice Emitted on token swaps\n    /// @param swap0to1 Indicates whether the swap is from token0 to token1 or vice-versa.\n    /// @param amountIn The amount of tokens to be sent to the vault to swap.\n    /// @param amountOut The amount of tokens user got from the swap.\n    /// @param to Recepient of swapped tokens.\n    event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to);\n\n    /// @notice Emitted when liquidity is added with shares specified.\n    /// @param shares Expected exact shares to be received.\n    /// @param token0Amt Amount of token0 deposited.\n    /// @param token0Amt Amount of token1 deposited.\n    event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is borrowed with shares specified.\n    /// @param shares shares minted\n    /// @param token0Amt Amount of token0 borrowed.\n    /// @param token1Amt Amount of token1 borrowed.\n    event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is deposited with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 deposited.\n    /// @param amount1 Amount of token1 deposited.\n    /// @param shares Amount of shares minted.\n    event LogDepositColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 withdrawn.\n    /// @param amount1 Amount of token1 withdrawn.\n    /// @param shares Amount of shares burned.\n    event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is borrowed with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 borrowed.\n    /// @param amount1 Amount of token1 borrowed.\n    /// @param shares Amount of shares minted.\n    event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is paid back with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 paid back.\n    /// @param amount1 Amount of token1 paid back.\n    /// @param shares Amount of shares burned.\n    event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified into one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified from one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when internal arbitrage between 2 pools happen\n    /// @param routing if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback\n    /// @param amtOut if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow\n    event LogArbitrage(int routing, uint amtOut);\n}\n","keccak256":"0x2ccdd6f07486693ec9abccbba5eaaf21ffe1b5436ed961322e663f78b6f1b998","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\n\nimport { Variables } from \"../../common/variables.sol\";\nimport { ImmutableVariables } from \"../immutableVariables.sol\";\nimport { Events } from \"../events.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IHook, ICenterPrice } from \"../interfaces.sol\";\nimport { LiquiditySlotsLink } from \"../../../../../libraries/liquiditySlotsLink.sol\";\nimport { LiquidityCalcs } from \"../../../../../libraries/liquidityCalcs.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { AddressCalcs } from \"../../../../../libraries/addressCalcs.sol\";\n\ninterface IShifting {\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper threshold, lower threshold, and dexVariables2\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new center price during an active center price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return The updated center price\n    function _calcCenterPrice(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) external payable returns (uint);\n}\n\nabstract contract CoreHelpers is Variables, ImmutableVariables, Events {\n    using BigMathMinified for uint256;\n\n    /// @dev            do any arbitrary call\n    /// @param target_  Address to which the call needs to be delegated\n    /// @param data_    Data to execute at the delegated address\n    function _spell(address target_, bytes memory data_) internal returns (bytes memory response_) {\n        assembly {\n            let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)\n            let size := returndatasize()\n\n            response_ := mload(0x40)\n            mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n            mstore(response_, size)\n            returndatacopy(add(response_, 0x20), 0, size)\n\n            if iszero(succeeded) {\n                // throw if delegatecall failed\n                returndatacopy(0x00, 0x00, size)\n                revert(0x00, size)\n            }\n        }\n    }\n\n    /// @dev Given an input amount of asset and pair reserves, returns the maximum output amount of the other asset\n    /// @param amountIn_ The amount of input asset.\n    /// @param iReserveIn_ Imaginary token reserve with input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountOut(\n        uint256 amountIn_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountOut_) {\n        unchecked {\n            // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n            uint256 numerator_ = amountIn_ * iReserveOut_;\n            uint256 denominator_ = iReserveIn_ + amountIn_;\n\n            // Using the swap formula: (AmountIn * iReserveY) / (iReserveX + AmountIn)\n            amountOut_ = numerator_ / denominator_;\n        }\n    }\n\n    /// @dev Given an output amount of asset and pair reserves, returns the input amount of the other asset\n    /// @param amountOut_ Desired output amount of the asset.\n    /// @param iReserveIn_ Imaginary token reserve of input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountIn(\n        uint256 amountOut_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountIn_) {\n        // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n        uint256 numerator_ = amountOut_ * iReserveIn_;\n        uint256 denominator_ = iReserveOut_ - amountOut_;\n\n        // Using the swap formula: (AmountOut * iReserveX) / (iReserveY - AmountOut)\n        amountIn_ = numerator_ / denominator_;\n    }\n\n    /// @param t total amount in\n    /// @param x imaginary reserves of token out of collateral\n    /// @param y imaginary reserves of token in of collateral\n    /// @param x2 imaginary reserves of token out of debt\n    /// @param y2 imaginary reserves of token in of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingIn(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. out = x * a / (y + a)\n        // 2. out2 = x2 * (t - a) / (y2 + (t - a))\n        // final price should be same\n        // 3. (y + a) / (x - out) = (y2 + (t - a)) / (x2 - out2)\n        // derivation: https://chatgpt.com/share/dce6f381-ee5f-4d5f-b6ea-5996e84d5b57\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    /// @param t total amount out\n    /// @param x imaginary reserves of token in of collateral\n    /// @param y imaginary reserves of token out of collateral\n    /// @param x2 imaginary reserves of token in of debt\n    /// @param y2 imaginary reserves of token out of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingOut(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. in = (x * a) / (y - a)\n        // 2. in2 = (x2 * (t - a)) / (y2 - (t - a))\n        // final price should be same\n        // 3. (y - a) / (x + in) = (y2 - (t - a)) / (x2 + in2)\n        // derivation: https://chatgpt.com/share/6585bc28-841f-49ec-aea2-1e5c5b7f4fa9\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        // 1e18 precision gets cancelled out in division\n        a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view {\n        if (utilizationLimit_ < THREE_DECIMALS) {\n            utilizationLimit_ = utilizationLimit_ * 10;\n            // extracting utilization of token from liquidity layer\n            uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);\n            liquidityLayerUtilization_ =\n                (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) &\n                X14;\n            // Note: this can go slightly above the utilization limit if no update is written to storage at liquidity layer\n            // if swap was not big enough to go far enough above or any other storage update threshold write cause there\n            // so just to keep in mind when configuring the actual limit reachable can be utilizationLimit_ + storageUpdateThreshold at Liquidity\n            if (liquidityLayerUtilization_ > utilizationLimit_)\n                revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);\n        }\n    }\n\n    function _check(uint dexVariables_, uint dexVariables2_) internal {\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        if (dexVariables2_ & 3 == 0) revert FluidDexError(ErrorTypes.DexT1__PoolNotInitialized);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n    }\n\n    /// @dev if token0 reserves are too low w.r.t token1 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken0Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token0Reserves_) < ((token1Reserves_ * 1e27) / (centerPrice_ * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    /// @dev if token1 reserves are too low w.r.t token0 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken1Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token1Reserves_) < ((token0Reserves_ * centerPrice_) / (1e27 * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure {\n        // after shifting amount should not become 0\n        // limiting to six decimals which means in case of USDC, USDT it's 1 wei, for WBTC 100 wei, for ETH 1000 gwei\n        if (amountAdjusted_ < SIX_DECIMALS || amountAdjusted_ > X96 || amount_ < TWO_DECIMALS || amount_ > X128)\n            revert FluidDexError(ErrorTypes.DexT1__LimitingAmountsSwapAndNonPerfectActions);\n    }\n\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    /// @notice This function handles the gradual shifting of range values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcRangeShifting.selector,\n                        upperRange_,\n                        lowerRange_,\n                        dexVariables2_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new upper and lower threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param thresholdTime_ The time passed since shifting started\n    /// @return The updated upper threshold, lower threshold, and threshold time\n    /// @notice This function handles the gradual shifting of threshold values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint thresholdTime_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcThresholdShifting.selector,\n                        upperThreshold_,\n                        lowerThreshold_,\n                        thresholdTime_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new center price during an active price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return newCenterPrice_ The updated center price\n    /// @notice This function gradually shifts the center price towards a new target price over time\n    /// @notice It uses an external price source (via ICenterPrice) to determine the target price\n    /// @notice The shift continues until the current price reaches the target, or the shift duration ends\n    /// @notice Once the shift is complete, it updates the state and clears the shift data\n    /// @notice The shift rate is dynamic and depends on:\n    /// @notice - Time remaining in the shift duration\n    /// @notice - The new center price (fetched externally, which may change)\n    /// @notice - The current (old) center price\n    /// @notice This results in a fuzzy shifting mechanism where the rate can change as these parameters evolve\n    /// @notice The externally fetched new center price is expected to not differ significantly from the last externally fetched center price\n    function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(IShifting._calcCenterPrice.selector, dexVariables_, dexVariables2_)\n                ),\n                (uint)\n            );\n    }\n\n    /// @notice Calculates and returns the current prices and exchange prices for the pool\n    /// @param dexVariables_ The first set of DEX variables containing various pool parameters\n    /// @param dexVariables2_ The second set of DEX variables containing additional pool parameters\n    /// @return pex_ A struct containing the calculated prices and exchange prices:\n    ///         - pex_.lastStoredPrice: The last stored price in 1e27 decimals\n    ///         - pex_.centerPrice: The calculated or fetched center price in 1e27 decimals\n    ///         - pex_.upperRange: The upper range price limit in 1e27 decimals\n    ///         - pex_.lowerRange: The lower range price limit in 1e27 decimals\n    ///         - pex_.geometricMean: The geometric mean of upper range & lower range in 1e27 decimals\n    ///         - pex_.supplyToken0ExchangePrice: The current exchange price for supplying token0\n    ///         - pex_.borrowToken0ExchangePrice: The current exchange price for borrowing token0\n    ///         - pex_.supplyToken1ExchangePrice: The current exchange price for supplying token1\n    ///         - pex_.borrowToken1ExchangePrice: The current exchange price for borrowing token1\n    /// @dev This function performs the following operations:\n    ///      1. Determines the center price (either from storage, external source, or calculated)\n    ///      2. Retrieves the last stored price from dexVariables_\n    ///      3. Calculates the upper and lower range prices based on the center price and range percentages\n    ///      4. Checks if rebalancing is needed based on threshold settings\n    ///      5. Adjusts prices if necessary based on the time elapsed and threshold conditions\n    ///      6. Update the dexVariables2_ if changes were made\n    ///      7. Returns the calculated prices and exchange prices in the PricesAndExchangePrice struct\n    function _getPricesAndExchangePrices(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) internal returns (PricesAndExchangePrice memory pex_) {\n        uint centerPrice_;\n\n        if (((dexVariables2_ >> 248) & 1) == 0) {\n            // centerPrice_ => center price hook\n            centerPrice_ = (dexVariables2_ >> 112) & X30;\n            if (centerPrice_ == 0) {\n                centerPrice_ = (dexVariables_ >> 81) & X40;\n                centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);\n            } else {\n                // center price should be fetched from external source. For exmaple, in case of wstETH <> ETH pool,\n                // we would want the center price to be pegged to wstETH exchange rate into ETH\n                centerPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, centerPrice_)).centerPrice();\n            }\n        } else {\n            // an active centerPrice_ shift is going on\n            centerPrice_ = _calcCenterPrice(dexVariables_, dexVariables2_);\n        }\n\n        uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;\n        lastStoredPrice_ = (lastStoredPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastStoredPrice_ & DEFAULT_EXPONENT_MASK);\n\n        uint upperRange_ = ((dexVariables2_ >> 27) & X20);\n        uint lowerRange_ = ((dexVariables2_ >> 47) & X20);\n        if (((dexVariables2_ >> 26) & 1) == 1) {\n            // an active range shift is going on\n            (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);\n        }\n\n        unchecked {\n            // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n            // 1% = 1e4, 100% = 1e6\n            upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n            // 1% = 1e4, 100% = 1e6\n            lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n        }\n\n        bool changed_;\n        {\n            // goal will be to keep threshold percents 0 if center price is fetched from external source\n            // checking if threshold are set non 0 then only rebalancing is on\n            if (((dexVariables2_ >> 68) & X20) > 0) {\n                uint upperThreshold_ = (dexVariables2_ >> 68) & X10;\n                uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;\n                uint shiftingTime_ = (dexVariables2_ >> 88) & X24;\n                if (((dexVariables2_ >> 67) & 1) == 1) {\n                    // if active shift is going on for threshold then calculate threshold real time\n                    (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(\n                        upperThreshold_,\n                        lowerThreshold_,\n                        shiftingTime_\n                    );\n                }\n\n                unchecked {\n                    if (\n                        lastStoredPrice_ >\n                        (centerPrice_ +\n                            ((upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards upper range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = upperRange_;\n                        }\n                        changed_ = true;\n                    } else if (\n                        lastStoredPrice_ <\n                        (centerPrice_ -\n                            ((centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards lower range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = lowerRange_;\n                        }\n                        changed_ = true;\n                    }\n                }\n            }\n        }\n\n        // temp_ => max center price\n        uint temp_ = (dexVariables2_ >> 172) & X28;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n        if (centerPrice_ > temp_) {\n            // if center price is greater than max center price\n            centerPrice_ = temp_;\n            changed_ = true;\n        } else {\n            // check if center price is less than min center price\n            // temp_ => min center price\n            temp_ = (dexVariables2_ >> 200) & X28;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n            if (centerPrice_ < temp_) {\n                centerPrice_ = temp_;\n                changed_ = true;\n            }\n        }\n\n        // if centerPrice_ is changed then calculating upper and lower range again\n        if (changed_) {\n            upperRange_ = ((dexVariables2_ >> 27) & X20);\n            lowerRange_ = ((dexVariables2_ >> 47) & X20);\n            if (((dexVariables2_ >> 26) & 1) == 1) {\n                (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(\n                    upperRange_,\n                    lowerRange_,\n                    dexVariables2_\n                );\n            }\n\n            unchecked {\n                // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n                // 1% = 1e4, 100% = 1e6\n                upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n                // 1% = 1e4, 100% = 1e6\n                lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n            }\n        }\n\n        pex_.lastStoredPrice = lastStoredPrice_;\n        pex_.centerPrice = centerPrice_;\n        pex_.upperRange = upperRange_;\n        pex_.lowerRange = lowerRange_;\n\n        unchecked {\n            if (upperRange_ < 1e38) {\n                // 1e38 * 1e38 = 1e76 which is less than max uint limit\n                pex_.geometricMean = FixedPointMathLib.sqrt(upperRange_ * lowerRange_);\n            } else {\n                // upperRange_ price is pretty large hence lowerRange_ will also be pretty large\n                pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18;\n            }\n        }\n\n        // Exchange price will remain same as Liquidity Layer\n        (pex_.supplyToken0ExchangePrice, pex_.borrowToken0ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_0_SLOT)\n        );\n\n        (pex_.supplyToken1ExchangePrice, pex_.borrowToken1ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_1_SLOT)\n        );\n    }\n\n    /// @dev getting reserves outside range.\n    /// @param gp_ is geometric mean pricing of upper percent & lower percent\n    /// @param pa_ price of upper range or lower range\n    /// @param rx_ real reserves of token0 or token1\n    /// @param ry_ whatever is rx_ the other will be ry_\n    function _calculateReservesOutsideRange(\n        uint gp_,\n        uint pa_,\n        uint rx_,\n        uint ry_\n    ) internal pure returns (uint xa_, uint yb_) {\n        // equations we have:\n        // 1. x*y = k\n        // 2. xa*ya = k\n        // 3. xb*yb = k\n        // 4. Pa = ya / xa = upperRange_ (known)\n        // 5. Pb = yb / xb = lowerRange_ (known)\n        // 6. x - xa = rx = real reserve of x (known)\n        // 7. y - yb = ry = real reserve of y (known)\n        // With solving we get:\n        // ((Pa*Pb)^(1/2) - Pa)*xa^2 + (rx * (Pa*Pb)^(1/2) + ry)*xa + rx*ry = 0\n        // yb = yb = xa * (Pa * Pb)^(1/2)\n\n        // xa = (GP⋅rx + ry + (-rx⋅ry⋅4⋅(GP - Pa) + (GP⋅rx + ry)^2)^0.5) / (2Pa - 2GP)\n        // multiply entire equation by 1e27 to remove the price decimals precision of 1e27\n        // xa = (GP⋅rx + ry⋅1e27 + (rx⋅ry⋅4⋅(Pa - GP)⋅1e27 + (GP⋅rx + ry⋅1e27)^2)^0.5) / 2*(Pa - GP)\n        // dividing the equation with 2*(Pa - GP). Pa is always > GP so answer will be positive.\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅4⋅(Pa - GP)⋅1e27) / 4*(Pa - GP)^2) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅1e27) / (Pa - GP)) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n\n        // dividing in 3 parts for simplification:\n        // part1 = (Pa - GP)\n        // part2 = (GP⋅rx + ry⋅1e27) / (2*part1)\n        // part3 = rx⋅ry\n        // note: part1 will almost always be < 1e28 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e29\n        uint p1_ = pa_ - gp_;\n        uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);\n        uint p3_ = rx_ * ry_;\n        // to avoid overflowing\n        p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27;\n\n        // xa = part2 + (part3 + (part2 * part2))^(1/2)\n        // yb = xa_ * gp_\n        xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));\n        yb_ = (xa_ * gp_) / 1e27;\n    }\n\n    /// @dev Retrieves collateral amount from liquidity layer for a given token\n    /// @param supplyTokenSlot_ The storage slot for the supply token data\n    /// @param tokenExchangePrice_ The exchange price of the token\n    /// @param isToken0_ Boolean indicating if the token is token0 (true) or token1 (false)\n    /// @return tokenSupply_ The calculated liquidity collateral amount\n    function _getLiquidityCollateral(\n        bytes32 supplyTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenSupply_) {\n        uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);\n        tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;\n        tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);\n\n        if (tokenSupplyData_ & 1 == 1) {\n            // supply with interest is on\n            unchecked {\n                tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenSupply_ = isToken0_\n                ? ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function _getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) internal view returns (CollateralReserves memory c_) {\n        uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);\n        uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);\n\n        if (geometricMean_ < 1e27) {\n            (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(\n                geometricMean_,\n                upperRange_,\n                token0Supply_,\n                token1Supply_\n            );\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange(\n                (1e54 / geometricMean_),\n                (1e54 / lowerRange_),\n                token1Supply_,\n                token0Supply_\n            );\n        }\n\n        c_.token0RealReserves = token0Supply_;\n        c_.token1RealReserves = token1Supply_;\n        unchecked {\n            c_.token0ImaginaryReserves += token0Supply_;\n            c_.token1ImaginaryReserves += token1Supply_;\n        }\n    }\n\n    /// @notice Calculates the real and imaginary debt reserves for both tokens\n    /// @dev This function uses a quadratic equation to determine the debt reserves\n    ///      based on the geometric mean price and the current debt amounts\n    /// @param gp_ The geometric mean price of upper range & lower range\n    /// @param pb_ The price of lower range\n    /// @param dx_ The debt amount of one token\n    /// @param dy_ The debt amount of the other token\n    /// @return rx_ The real debt reserve of the first token\n    /// @return ry_ The real debt reserve of the second token\n    /// @return irx_ The imaginary debt reserve of the first token\n    /// @return iry_ The imaginary debt reserve of the second token\n    function _calculateDebtReserves(\n        uint gp_,\n        uint pb_,\n        uint dx_,\n        uint dy_\n    ) internal pure returns (uint rx_, uint ry_, uint irx_, uint iry_) {\n        // Assigning letter to knowns:\n        // c = debtA\n        // d = debtB\n        // e = upperPrice\n        // f = lowerPrice\n        // g = upperPrice^1/2\n        // h = lowerPrice^1/2\n\n        // c = 1\n        // d = 2000\n        // e = 2222.222222\n        // f = 1800\n        // g = 2222.222222^1/2\n        // h = 1800^1/2\n\n        // Assigning letter to unknowns:\n        // w = realDebtReserveA\n        // x = realDebtReserveB\n        // y = imaginaryDebtReserveA\n        // z = imaginaryDebtReserveB\n        // k = k\n\n        // below quadratic will give answer of realDebtReserveB\n        // A, B, C of quadratic equation:\n        // A = h\n        // B = dh - cfg\n        // C = -cfdh\n\n        // A = lowerPrice^1/2\n        // B = debtB⋅lowerPrice^1/2 - debtA⋅lowerPrice⋅upperPrice^1/2\n        // C = -(debtA⋅lowerPrice⋅debtB⋅lowerPrice^1/2)\n\n        // x = (cfg − dh + (4cdf(h^2)+(cfg−dh)^2))^(1/2)) / 2h\n        // simplifying dividing by h, note h = f^1/2\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((4⋅c⋅d⋅f⋅f) / (4h^2) + ((c⋅f⋅g) / 2h − (d⋅h) / 2h)^2))^(1/2))\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((c⋅d⋅f) + ((c⋅g⋅(f^1/2) − d) / 2)^2))^(1/2))\n\n        // dividing in 3 parts for simplification:\n        // part1 = (c⋅g⋅(f^1/2) − d) / 2\n        // part2 = (c⋅d⋅f)\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        // note: part1 will almost always be < 1e27 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e28\n\n        // part1 = ((debtA * upperPrice^1/2 * lowerPrice^1/2) - debtB) / 2\n        // note: upperPrice^1/2 * lowerPrice^1/2 = geometric mean\n        // part1 = ((debtA * geometricMean) - debtB) / 2\n        // part2 = debtA * debtB * lowerPrice\n\n        // converting decimals properly as price is in 1e27 decimals\n        // part1 = ((debtA * geometricMean) - (debtB * 1e27)) / (2 * 1e27)\n        // part2 = (debtA * debtB * lowerPrice) / 1e27\n        // final x equals:\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);\n        uint p2_ = (dx_ * dy_);\n        p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;\n        ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));\n\n        // finding z:\n        // x^2 - zx + cfz = 0\n        // z*(x - cf) = x^2\n        // z = x^2 / (x - cf)\n        // z = x^2 / (x - debtA * lowerPrice)\n        // converting decimals properly as price is in 1e27 decimals\n        // z = (x^2 * 1e27) / ((x * 1e27) - (debtA * lowerPrice))\n\n        iry_ = ((ry_ * 1e27) - (dx_ * pb_));\n        if (iry_ < SIX_DECIMALS) {\n            // almost impossible situation to ever get here\n            revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);\n        }\n        if (ry_ < 1e25) {\n            iry_ = (ry_ * ry_ * 1e27) / iry_;\n        } else {\n            // note: it can never result in negative as final result will always be in positive\n            iry_ = (ry_ * ry_) / (iry_ / 1e27);\n        }\n\n        // finding y\n        // x = z * c / (y + c)\n        // y + c = z * c / x\n        // y = (z * c / x) - c\n        // y = (z * debtA / x) - debtA\n        irx_ = ((iry_ * dx_) / ry_) - dx_;\n\n        // finding w\n        // w = y * d / (z + d)\n        // w = (y * debtB) / (z + debtB)\n        rx_ = (irx_ * dy_) / (iry_ + dy_);\n    }\n\n    /// @notice Calculates the debt amount for a given token from liquidity layer\n    /// @param borrowTokenSlot_ The storage slot for the token's borrow data\n    /// @param tokenExchangePrice_ The current exchange price of the token\n    /// @param isToken0_ Boolean indicating if this is for token0 (true) or token1 (false)\n    /// @return tokenDebt_ The calculated debt amount for the token\n    function _getLiquidityDebt(\n        bytes32 borrowTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenDebt_) {\n        uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);\n\n        tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;\n        tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);\n\n        if (tokenBorrowData_ & 1 == 1) {\n            // borrow with interest is on\n            unchecked {\n                tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenDebt_ = isToken0_\n                ? ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function _getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) internal view returns (DebtReserves memory d_) {\n        uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);\n        uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);\n\n        d_.token0Debt = token0Debt_;\n        d_.token1Debt = token1Debt_;\n\n        if (geometricMean_ < 1e27) {\n            (\n                d_.token0RealReserves,\n                d_.token1RealReserves,\n                d_.token0ImaginaryReserves,\n                d_.token1ImaginaryReserves\n            ) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (\n                d_.token1RealReserves,\n                d_.token0RealReserves,\n                d_.token1ImaginaryReserves,\n                d_.token0ImaginaryReserves\n            ) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_);\n        }\n    }\n\n    function _priceDiffCheck(uint oldPrice_, uint newPrice_) internal pure returns (int priceDiff_) {\n        // check newPrice_ & oldPrice_ difference should not be more than 5%\n        // old price w.r.t new price\n        priceDiff_ = int(ORACLE_PRECISION) - int((oldPrice_ * ORACLE_PRECISION) / newPrice_);\n\n        unchecked {\n            if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {\n                // if oracle price difference is more than 5% then revert\n                // in 1 swap price should only change by <= 5%\n                // if a total fall by let's say 8% then in current block price can only fall by 5% and\n                // in next block it'll fall the remaining 3%\n                revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);\n            }\n        }\n    }\n\n    function _updateOracle(uint newPrice_, uint centerPrice_, uint dexVariables_) internal returns (uint) {\n        // time difference between last & current swap\n        uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        uint temp_;\n        uint temp2_;\n        uint temp3_;\n\n        if (timeDiff_ == 0) {\n            // doesn't matter if oracle is on or off when timediff = 0 code for both is same\n\n            // temp_ => oldCenterPrice\n            temp_ = (dexVariables_ >> 81) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // Ensure that the center price is within the acceptable range of the old center price if it's not the first swap in the same block\n            unchecked {\n                if (\n                    (centerPrice_ < (((EIGHT_DECIMALS - 1) * temp_) / EIGHT_DECIMALS)) ||\n                    (centerPrice_ > (((EIGHT_DECIMALS + 1) * temp_) / EIGHT_DECIMALS))\n                ) {\n                    revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);\n                }\n            }\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n\n            // 2nd swap in same block no need to update anything around oracle, only need to update last swap price in dexVariables\n            return ((dexVariables_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41));\n        }\n\n        if (((dexVariables_ >> 195) & 1) == 0) {\n            // if oracle is not active then just returning updated DEX variable\n            temp_ = ((dexVariables_ >> 41) & X40);\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n            \n            return ((dexVariables_ & 0xfffffffffffffffffffffffffc00000000000000000000000000000000000001) |\n                (((dexVariables_ >> 41) & X40) << 1) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (centerPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121));\n        } else {\n            // oracle is active hence update oracle\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // oldPrice_ => temp2_\n            temp2_ = (dexVariables_ >> 41) & X40;\n            temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);\n\n            int priceDiff_ = _priceDiffCheck(temp2_, newPrice_);\n\n            unchecked {\n                // older price w.r.t old price\n                priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);\n            }\n\n            // priceDiffInPercentAndSign_ => temp3_\n            // priceDiff_ will always be lower than ORACLE_LIMIT due to above check\n            unchecked {\n                if (priceDiff_ < 0) {\n                    temp3_ = ((uint(-priceDiff_) * X22) / ORACLE_LIMIT) << 1;\n                } else {\n                    // if greater than or equal to 0 then make sign flag 1\n                    temp3_ = (((uint(priceDiff_) * X22) / ORACLE_LIMIT) << 1) | 1;\n                }\n            }\n\n            if (timeDiff_ > X22) {\n                // if time difference is this then that means DEX has been inactive ~45 days\n                // that means oracle price of this DEX should not be used.\n                timeDiff_ = X22;\n            }\n\n            // temp_ => lastTimeDiff_\n            temp_ = (dexVariables_ >> 154) & X22;\n            uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);\n            uint oracleMap_ = (dexVariables_ >> 179) & X16;\n            if (temp_ > X9) {\n                if (nextOracleSlot_ > 0) {\n                    // if greater than 0 then current slot has 2 or more oracle slot empty\n                    // First 9 bits are of time, so not using that\n                    temp3_ = (temp3_ << 41) | (temp_ << 9);\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));\n                    if (nextOracleSlot_ > 0) {\n                        --nextOracleSlot_;\n                    } else {\n                        // if == 0 that means the oracle slots will get filled and shift to next oracle map\n                        nextOracleSlot_ = 7;\n                        unchecked {\n                            oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                        }\n                        _oracle[oracleMap_] = 0;\n                    }\n                } else {\n                    // if == 0\n                    // then seconds will be in last map\n                    // precision will be in last map + 1\n                    // Storing precision & sign slot in first precision & sign slot and leaving time slot empty\n                    temp3_ = temp3_ << 9;\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;\n                    nextOracleSlot_ = 6; // storing 6 here as 7 is going to occupied right now\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    // Storing time in 2nd precision & sign and leaving time slot empty\n                    _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);\n                }\n            } else {\n                temp3_ = (temp3_ << 9) | temp_;\n                unchecked {\n                    if (nextOracleSlot_ < 7) {\n                        _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));\n                    } else {\n                        _oracle[oracleMap_] = temp3_ << ((7 * 32));\n                    }\n                }\n                if (nextOracleSlot_ > 0) {\n                    --nextOracleSlot_;\n                } else {\n                    nextOracleSlot_ = 7;\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    _oracle[oracleMap_] = 0;\n                }\n            }\n\n            // doing this due to stack too deep error when using params memory variables\n            temp_ = newPrice_;\n            temp2_ = centerPrice_;\n            temp3_ = dexVariables_;\n\n            // then update last price\n            return ((temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |\n                (((temp3_ >> 41) & X40) << 1) |\n                (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121) |\n                (timeDiff_ << 154) |\n                (nextOracleSlot_ << 176) |\n                (oracleMap_ << 179));\n        }\n    }\n\n    function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal {\n        try\n            IHook(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, hookAddress_)).dexPrice(\n                mode_,\n                swap0to1_,\n                TOKEN_0,\n                TOKEN_1,\n                price_\n            )\n        returns (bool isOk_) {\n            if (!isOk_) revert FluidDexError(ErrorTypes.DexT1__HookReturnedFalse);\n        } catch (bytes memory /*lowLevelData*/) {\n            // skip checking hook nothing\n        }\n    }\n\n    function _updateSupplyShares(uint newTotalShares_) internal {\n        uint totalSupplyShares_ = _totalSupplyShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max supply shares\n        if (\n            (newTotalShares_ > (totalSupplyShares_ & X128)) && \n            newTotalShares_ > (totalSupplyShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__SupplySharesOverflow);\n        }\n\n        // keeping max supply shares intact\n        _totalSupplyShares = ((totalSupplyShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    function _updateBorrowShares(uint newTotalShares_) internal {\n        uint totalBorrowShares_ = _totalBorrowShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max borrow shares\n        if (\n            (newTotalShares_ > (totalBorrowShares_ & X128)) && \n            newTotalShares_ > (totalBorrowShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__BorrowSharesOverflow);\n        }\n\n        // keeping max borrow shares intact\n        _totalBorrowShares = ((totalBorrowShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    constructor(ConstantViews memory constantViews_) ImmutableVariables(constantViews_) {}\n}\n","keccak256":"0xb9758a62a536b0897d7da4f99ef7e8538ca339022394f757fcda71fc5ae85c80","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { ConstantVariables } from \"../common/constantVariables.sol\";\nimport { IFluidDexFactory } from \"../../interfaces/iDexFactory.sol\";\nimport { Error } from \"../../error.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\n\nabstract contract ImmutableVariables is ConstantVariables, Structs, Error {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public immutable DEX_ID;\n\n    /// @dev Address of token 0\n    address internal immutable TOKEN_0;\n\n    /// @dev Address of token 1\n    address internal immutable TOKEN_1;\n\n    address internal immutable THIS_CONTRACT;\n\n    uint256 internal immutable TOKEN_0_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_0_DENOMINATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_DENOMINATOR_PRECISION;\n\n    /// @dev Address of liquidity contract\n    IFluidLiquidity internal immutable LIQUIDITY;\n\n    /// @dev Address of DEX factory contract\n    IFluidDexFactory internal immutable DEX_FACTORY;\n\n    /// @dev Address of Shift implementation\n    address internal immutable SHIFT_IMPLEMENTATION;\n\n    /// @dev Address of Admin implementation\n    address internal immutable ADMIN_IMPLEMENTATION;\n\n    /// @dev Address of Col Operations implementation\n    address internal immutable COL_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Debt Operations implementation\n    address internal immutable DEBT_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Perfect Operations and Swap Out implementation\n    address internal immutable PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n\n    /// @dev Address of contract used for deploying center price & hook related contract\n    address internal immutable DEPLOYER_CONTRACT;\n\n    /// @dev Liquidity layer slots\n    bytes32 internal immutable SUPPLY_TOKEN_0_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_0_SLOT;\n    bytes32 internal immutable SUPPLY_TOKEN_1_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_1_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_0_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_1_SLOT;\n    uint256 internal immutable TOTAL_ORACLE_MAPPING;\n\n    function _calcNumeratorAndDenominator(\n        address token_\n    ) private view returns (uint256 numerator_, uint256 denominator_) {\n        uint256 decimals_ = _decimals(token_);\n        if (decimals_ > TOKENS_DECIMALS_PRECISION) {\n            numerator_ = 1;\n            denominator_ = 10 ** (decimals_ - TOKENS_DECIMALS_PRECISION);\n        } else {\n            numerator_ = 10 ** (TOKENS_DECIMALS_PRECISION - decimals_);\n            denominator_ = 1;\n        }\n    }\n\n    constructor(ConstantViews memory constants_) {\n        THIS_CONTRACT = address(this);\n\n        DEX_ID = constants_.dexId;\n        LIQUIDITY = IFluidLiquidity(constants_.liquidity);\n        DEX_FACTORY = IFluidDexFactory(constants_.factory);\n\n        TOKEN_0 = constants_.token0;\n        TOKEN_1 = constants_.token1;\n\n        if (TOKEN_0 >= TOKEN_1) revert FluidDexError(ErrorTypes.DexT1__Token0ShouldBeSmallerThanToken1);\n\n        (TOKEN_0_NUMERATOR_PRECISION, TOKEN_0_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_0);\n        (TOKEN_1_NUMERATOR_PRECISION, TOKEN_1_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_1);\n\n        if (constants_.implementations.shift != address(0)) {\n            SHIFT_IMPLEMENTATION = constants_.implementations.shift;\n        } else {\n            SHIFT_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.admin != address(0)) {\n            ADMIN_IMPLEMENTATION = constants_.implementations.admin;\n        } else {\n            ADMIN_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.colOperations != address(0)) {\n            COL_OPERATIONS_IMPLEMENTATION = constants_.implementations.colOperations;\n        } else {\n            COL_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.debtOperations != address(0)) {\n            DEBT_OPERATIONS_IMPLEMENTATION = constants_.implementations.debtOperations;\n        } else {\n            DEBT_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.perfectOperationsAndSwapOut != address(0)) {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = constants_.implementations.perfectOperationsAndSwapOut;\n        } else {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = address(this);\n        }\n\n        DEPLOYER_CONTRACT = constants_.deployerContract;\n\n        SUPPLY_TOKEN_0_SLOT = constants_.supplyToken0Slot;\n        BORROW_TOKEN_0_SLOT = constants_.borrowToken0Slot;\n        SUPPLY_TOKEN_1_SLOT = constants_.supplyToken1Slot;\n        BORROW_TOKEN_1_SLOT = constants_.borrowToken1Slot;\n        EXCHANGE_PRICE_TOKEN_0_SLOT = constants_.exchangePriceToken0Slot;\n        EXCHANGE_PRICE_TOKEN_1_SLOT = constants_.exchangePriceToken1Slot;\n\n        if (constants_.oracleMapping > X16) revert FluidDexError(ErrorTypes.DexT1__OracleMappingOverflow);\n\n        TOTAL_ORACLE_MAPPING = constants_.oracleMapping;\n    }\n}\n","keccak256":"0x03a004dfca351193090a40ea5829311a0bfb33c3c433ab8353a40de9c9448f87","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/interfaces.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface IHook {\n    /// @notice Hook function to check for liquidation opportunities before external swaps\n    /// @dev The primary use of this hook is to check if a particular pair vault has liquidation available.\n    ///      If liquidation is available, it gives priority to the liquidation process before allowing external swaps.\n    ///      In most cases, this hook will not be set.\n    /// @param id_ Identifier for the operation type: 1 for swap, 2 for internal arbitrage\n    /// @param swap0to1_ Direction of the swap: true if swapping token0 for token1, false otherwise\n    /// @param token0_ Address of the first token in the pair\n    /// @param token1_ Address of the second token in the pair\n    /// @param price_ The price ratio of token1 to token0, expressed with 27 decimal places\n    /// @return isOk_ Boolean indicating whether the operation should proceed\n    function dexPrice(\n        uint id_,\n        bool swap0to1_,\n        address token0_,\n        address token1_,\n        uint price_\n    ) external returns (bool isOk_);\n}\n\ninterface ICenterPrice {\n    /// @notice Retrieves the center price for the pool\n    /// @dev This function is marked as non-constant (potentially state-changing) to allow flexibility in price fetching mechanisms.\n    ///      While typically used as a read-only operation, this design permits write operations if needed for certain token pairs\n    ///      (e.g., fetching up-to-date exchange rates that may require state changes).\n    /// @return price The current price ratio of token1 to token0, expressed with 27 decimal places\n    function centerPrice() external returns (uint price);\n}\n","keccak256":"0x6e42130fb15dbcfc2850e69bd7f26a1c709a6711cd00c10d2afb7aa1b97cfcc8","license":"BUSL-1.1"},"contracts/protocols/dex/poolT1/coreModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct ExchangePrices {\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct CollateralReservesSwap {\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReservesSwap {\n        uint tokenInDebt;\n        uint tokenOutDebt;\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct SwapInMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtInAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee; // fee of pool\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n    }\n\n    struct SwapOutMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtOutAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee;\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n        uint msgValue;\n    }\n\n    struct DepositColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n    }\n\n    struct WithdrawColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n        address to;\n    }\n\n    struct BorrowDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n        address to;\n    }\n\n    struct PaybackDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n    }\n\n    struct OraclePriceMemory {\n        uint lowestPrice1by0;\n        uint highestPrice1by0;\n        uint oracleSlot;\n        uint oracleMap;\n        uint oracle;\n    }\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndSwapOut;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n}\n","keccak256":"0x1cccc3a9ff4f07f159ac2aebf969c2a714a6f912ef0e86b76362bf45a5ecb8be","license":"BUSL-1.1"},"solmate/src/utils/FixedPointMathLib.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(\n        uint256 x,\n        uint256 n,\n        uint256 scalar\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\n    }\n}\n","keccak256":"0x1b62af9baf5b8e991ed7531bc87f45550ba9d61e8dbff5caf237ccaf3a3fd843","license":"AGPL-3.0-only"}},"version":1},"storageLayout":{"types":{"t_address":{"label":"address","encoding":"inplace","numberOfBytes":"20"},"t_uint128":{"label":"uint128","encoding":"inplace","numberOfBytes":"16"},"t_uint256":{"label":"uint256","encoding":"inplace","numberOfBytes":"32"},"t_mapping(t_address,t_uint256)":{"key":"t_address","label":"mapping(address => uint256)","value":"t_uint256","encoding":"mapping","numberOfBytes":"32"},"t_mapping(t_uint256,t_uint256)":{"key":"t_uint256","label":"mapping(uint256 => uint256)","value":"t_uint256","encoding":"mapping","numberOfBytes":"32"}},"storage":[{"slot":"0","type":"t_uint256","astId":3893,"label":"dexVariables","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"1","type":"t_uint256","astId":3896,"label":"dexVariables2","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"2","type":"t_uint256","astId":3899,"label":"_totalSupplyShares","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"3","type":"t_mapping(t_address,t_uint256)","astId":3904,"label":"_userSupplyData","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"4","type":"t_uint256","astId":3907,"label":"_totalBorrowShares","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"5","type":"t_mapping(t_address,t_uint256)","astId":3912,"label":"_userBorrowData","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"6","type":"t_mapping(t_uint256,t_uint256)","astId":3917,"label":"_oracle","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"7","type":"t_uint128","astId":3920,"label":"_rangeShift","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"7","type":"t_uint128","astId":3923,"label":"_thresholdShift","offset":16,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"8","type":"t_uint256","astId":3926,"label":"_centerPriceShift","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"}]},"transientStorageLayout":null,"userdoc":{"kind":"user","errors":{"FluidDexSwapResult(uint256)":[{"notice":"used to simulate swap to find the output amount"}]},"events":{"LogArbitrage(int256,uint256)":{"notice":"Emitted when internal arbitrage between 2 pools happen"},"Swap(bool,uint256,uint256,address)":{"notice":"Emitted on token swaps"},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with specified token0 & token1 amount"},"LogDepositColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is deposited with specified token0 & token1 amount"},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with specified token0 & token1 amount"},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with specified token0 & token1 amount"},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified from one token only."},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified into one token only."},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with shares specified."},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is added with shares specified."},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified."},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified."}},"notice":"Implements core logics for Fluid Dex protocol. Note Token transfers happen directly from user to Liquidity contract and vice-versa.","methods":{"constantsView()":{"notice":"returns all Vault constants"},"constantsView2()":{"notice":"returns all Vault constants"},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the debt reserves for both tokens"},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the real and imaginary reserves for collateral tokens"}},"version":1},"devdoc":{"kind":"dev","title":"FluidDexT1","events":{"LogArbitrage(int256,uint256)":{"params":{"amtOut":"if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow","routing":"if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback"}},"Swap(bool,uint256,uint256,address)":{"params":{"to":"Recepient of swapped tokens.","amountIn":"The amount of tokens to be sent to the vault to swap.","swap0to1":"Indicates whether the swap is from token0 to token1 or vice-versa.","amountOut":"The amount of tokens user got from the swap."}},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares minted.","amount0":"Amount of token0 borrowed.","amount1":"Amount of token1 borrowed."}},"LogDepositColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares minted.","amount0":"Amount of token0 deposited.","amount1":"Amount of token1 deposited."}},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares burned.","amount0":"Amount of token0 paid back.","amount1":"Amount of token1 paid back."}},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares burned.","amount0":"Amount of token0 withdrawn.","amount1":"Amount of token1 withdrawn."}},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares minted","token0Amt":"Amount of token0 borrowed.","token1Amt":"Amount of token1 borrowed."}},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Expected exact shares to be received.","token0Amt":"Amount of token1 deposited."}},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}}},"methods":{"oraclePrice(uint256[])":{"params":{"secondsAgos_":"array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]"},"details":"the oracle assumes last set price of pool till the next swap happens. There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration but the difference due to interest will be super low so this difference is ignored For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other. then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%","returns":{"twaps_":"twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints","currentPrice_":"price of pool after the most recent swap"}},"swapIn(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_","amountIn_":"The exact amount of tokens to swap in","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOutMin_":"The minimum amount of tokens to receive after swap"},"details":"Swap tokens with perfect amount in","returns":{"amountOut_":"The amount of output tokens received from the swap"}},"deposit(uint256,uint256,uint256,bool)":{"params":{"estimate_":"If true, function will revert with estimated shares without executing the deposit","token0Amt_":"The amount of token0 to deposit","token1Amt_":"The amount of token1 to deposit","minSharesAmt_":"The minimum amount of shares the user expects to receive"},"details":"This function allows users to deposit tokens in any proportion into the col pool","returns":{"shares_":"The amount of shares minted for the deposit"}},"payback(uint256,uint256,uint256,bool)":{"params":{"estimate_":"If true, function will revert with estimated shares without executing the payback","token0Amt_":"The amount of token0 to payback","token1Amt_":"The amount of token1 to payback","minSharesAmt_":"The minimum amount of shares the user expects to burn"},"details":"This function allows users to payback tokens in any proportion to the debt pool","returns":{"shares_":"The amount of borrow shares burned for the payback"}},"swapOut(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOut_":"The exact amount of tokens to receive after swap","amountInMax_":"Maximum amount of tokens to swap in"},"details":"Swap tokens with perfect amount out","returns":{"amountIn_":"The amount of input tokens used for the swap"}},"borrow(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to borrow","token1Amt_":"The amount of token1 to borrow","maxSharesAmt_":"The maximum amount of shares the user is willing to receive"},"details":"This function allows users to borrow tokens in any proportion from the debt pool","returns":{"shares_":"The amount of borrow shares minted to represent the borrowed amount"}},"liquidityCallback(address,uint256,bytes)":{"details":"liquidity callback for cheaper token transfers in case of deposit or payback. only callable by Liquidity during an operation."},"withdraw(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to withdraw","token1Amt_":"The amount of token1 to withdraw","maxSharesAmt_":"The maximum number of shares the user is willing to burn"},"details":"This function allows users to withdraw tokens in any proportion from the col pool","returns":{"shares_":"The number of shares burned for the withdrawal"}},"depositPerfect(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to mint","estimate_":"If true, function will revert with estimated deposit amounts without executing the deposit","maxToken0Deposit_":"Maximum amount of token0 to deposit","maxToken1Deposit_":"Maximum amount of token1 to deposit"},"details":"Deposit tokens in equal proportion to the current pool ratio","returns":{"token0Amt_":"Amount of token0 deposited","token1Amt_":"Amount of token1 deposited"}},"paybackPerfect(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to pay back","estimate_":"If true, function will revert with estimated payback amounts without executing the payback","maxToken0Payback_":"Maximum amount of token0 to pay back","maxToken1Payback_":"Maximum amount of token1 to pay back"},"details":"This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio","returns":{"token0Amt_":"Amount of token0 paid back","token1Amt_":"Amount of token1 paid back"}},"borrowPerfect(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_","shares_":"The number of shares to borrow","minToken0Borrow_":"Minimum amount of token0 to borrow","minToken1Borrow_":"Minimum amount of token1 to borrow"},"details":"This function allows users to borrow tokens in equal proportion to the current debt pool ratio","returns":{"token0Amt_":"Amount of token0 borrowed","token1Amt_":"Amount of token1 borrowed"}},"swapInWithCallback(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_","amountIn_":"The exact amount of tokens to swap in","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOutMin_":"The minimum amount of tokens to receive after swap"},"details":"Swap tokens with perfect amount in and callback functionality","returns":{"amountOut_":"The amount of output tokens received from the swap"}},"withdrawPerfect(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_","shares_":"The number of shares to withdraw","minToken0Withdraw_":"The minimum amount of token0 the user is willing to accept","minToken1Withdraw_":"The minimum amount of token1 the user is willing to accept"},"details":"This function allows users to withdraw a perfect amount of collateral liquidity","returns":{"token0Amt_":"The amount of token0 withdrawn","token1Amt_":"The amount of token1 withdrawn"}},"swapOutWithCallback(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOut_":"The exact amount of tokens to receive after swap","amountInMax_":"Maximum amount of tokens to swap in"},"details":"Swap tokens with perfect amount out and callback functionality","returns":{"amountIn_":"The amount of input tokens used for the swap"}},"paybackPerfectInOneToken(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to burn for payback","estimate_":"If true, the function will revert with the estimated payback amount without executing the payback","maxToken0_":"The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)","maxToken1_":"The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)"},"details":"This function allows users to payback their debt with perfect shares in one token","returns":{"paybackAmt_":"The amount of tokens paid back in the chosen token"}},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"params":{"lowerRange_":"The lower price range","upperRange_":"The upper price range","geometricMean_":"The geometric mean of the upper and lower price ranges","token0BorrowExchangePrice_":"The exchange price of token0 from liquidity layer","token1BorrowExchangePrice_":"The exchange price of token1 from liquidity layer"},"returns":{"d_":"The calculated debt reserves for both tokens, containing:         - token0Debt: The debt amount of token0         - token1Debt: The debt amount of token1         - token0RealReserves: The real reserves of token0 derived from token1 debt         - token1RealReserves: The real reserves of token1 derived from token0 debt         - token0ImaginaryReserves: The imaginary debt reserves of token0         - token1ImaginaryReserves: The imaginary debt reserves of token1"}},"withdrawPerfectInOneToken(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_","shares_":"The number of shares to burn for withdrawal","minToken0_":"The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)","minToken1_":"The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)"},"details":"This function allows users to withdraw their collateral with perfect shares in one token","returns":{"withdrawAmt_":"The amount of tokens withdrawn in the chosen token"}},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"params":{"lowerRange_":"The lower price range","upperRange_":"The upper price range","geometricMean_":"The geometric mean of the token prices","token0SupplyExchangePrice_":"The exchange price for token0 from liquidity layer","token1SupplyExchangePrice_":"The exchange price for token1 from liquidity layer"},"details":"This function retrieves the supply of both tokens from the liquidity layer,      adjusts them based on exchange prices, and calculates imaginary reserves      based on the geometric mean and price range","returns":{"c_":"A struct containing the calculated real and imaginary reserves for both tokens:         - token0RealReserves: The real reserves of token0         - token1RealReserves: The real reserves of token1         - token0ImaginaryReserves: The imaginary reserves of token0         - token1ImaginaryReserves: The imaginary reserves of token1"}}},"version":1},"sourceIds":{"contracts/libraries/dexCalcs.sol":{"id":3},"contracts/protocols/dex/error.sol":{"id":12},"contracts/libraries/errorTypes.sol":{"id":5},"contracts/libraries/storageRead.sol":{"id":9},"contracts/libraries/addressCalcs.sol":{"id":1},"contracts/libraries/dexSlotsLink.sol":{"id":4},"contracts/libraries/safeTransfer.sol":{"id":8},"contracts/libraries/liquidityCalcs.sol":{"id":6},"contracts/protocols/dex/errorTypes.sol":{"id":13},"contracts/libraries/bigMathMinified.sol":{"id":2},"solmate/src/utils/FixedPointMathLib.sol":{"id":24},"contracts/libraries/liquiditySlotsLink.sol":{"id":7},"contracts/liquidity/adminModule/structs.sol":{"id":10},"contracts/infiniteProxy/interfaces/iProxy.sol":{"id":0},"contracts/liquidity/interfaces/iLiquidity.sol":{"id":11},"contracts/protocols/dex/interfaces/iDexT1.sol":{"id":15},"contracts/protocols/dex/interfaces/iDexFactory.sol":{"id":14},"contracts/protocols/dex/poolT1/common/variables.sol":{"id":17},"contracts/protocols/dex/poolT1/coreModule/events.sol":{"id":19},"contracts/protocols/dex/poolT1/coreModule/structs.sol":{"id":23},"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"id":18},"contracts/protocols/dex/poolT1/coreModule/interfaces.sol":{"id":22},"contracts/protocols/dex/poolT1/common/constantVariables.sol":{"id":16},"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol":{"id":21},"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol":{"id":20}},"additionalInput":null,"stdJsonInput":{"sources":{"contracts/libraries/dexCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\nimport { DexSlotsLink } from \"./dexSlotsLink.sol\";\n\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n// @DEV ATTENTION: ON ANY CHANGES HERE, MAKE SURE THAT LOGIC IN VAULTS WILL STILL BE VALID.\n// SOME CODE THERE ASSUMES DEXCALCS == LIQUIDITYCALCS.\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n/// @notice implements calculation methods used for Fluid Dex such as updated withdrawal / borrow limits.\nlibrary DexCalcs {\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) &\n            X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ = block.timestamp - ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ = block.timestamp - ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n}\n"},"contracts/protocols/dex/error.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { Structs } from \"./poolT1/coreModule/structs.sol\";\n\nabstract contract Error {\n    error FluidDexError(uint256 errorId_);\n\n    error FluidDexFactoryError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares_);\n\n    error FluidDexPricesAndExchangeRates(Structs.PricesAndExchangePrice pex_);\n}\n"},"contracts/libraries/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary LibsErrorTypes {\n    /***********************************|\n    |         LiquidityCalcs            | \n    |__________________________________*/\n\n    /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet)\n    uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001;\n\n    /// @notice thrown when rate data is set to a version that is not implemented\n    uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002;\n\n    /// @notice thrown when the calculated borrow rate turns negative. This should never happen.\n    uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003;\n\n    /***********************************|\n    |           SafeTransfer            | \n    |__________________________________*/\n\n    /// @notice thrown when safe transfer from for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFromFailed = 71001;\n\n    /// @notice thrown when safe transfer for an ERC20 fails\n    uint256 internal constant SafeTransfer__TransferFailed = 71002;\n\n    /***********************************|\n    |           SafeApprove             | \n    |__________________________________*/\n\n    /// @notice thrown when safe approve from for an ERC20 fails\n    uint256 internal constant SafeApprove__ApproveFailed = 81001;\n}\n"},"contracts/libraries/storageRead.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.\ncontract StorageRead {\n    function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {\n        assembly {\n            result_ := sload(slot_) // read value from the storage slot\n        }\n    }\n}\n"},"contracts/libraries/addressCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice implements calculation of address for contracts deployed through CREATE.\n/// Accepts contract deployed from which address & nonce\nlibrary AddressCalcs {\n\n    /// @notice                         Computes the address of a contract based\n    /// @param deployedFrom_            Address from which the contract was deployed\n    /// @param nonce_                   Nonce at which the contract was deployed\n    /// @return contract_               Address of deployed contract\n    function addressCalc(address deployedFrom_, uint nonce_) internal pure returns (address contract_) {\n        // @dev based on https://ethereum.stackexchange.com/a/61413\n\n        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment\n        // hence, nonce of vault deployment starts with 1.\n        bytes memory data;\n        if (nonce_ == 0x00) {\n            return address(0);\n        } else if (nonce_ <= 0x7f) {\n            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployedFrom_, uint8(nonce_));\n        } else if (nonce_ <= 0xff) {\n            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployedFrom_, bytes1(0x81), uint8(nonce_));\n        } else if (nonce_ <= 0xffff) {\n            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployedFrom_, bytes1(0x82), uint16(nonce_));\n        } else if (nonce_ <= 0xffffff) {\n            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployedFrom_, bytes1(0x83), uint24(nonce_));\n        } else {\n            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), deployedFrom_, bytes1(0x84), uint32(nonce_));\n        }\n\n        return address(uint160(uint256(keccak256(data))));\n    }\n\n}"},"contracts/libraries/dexSlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Dex.\n/// @dev as all data for Fluid Dex is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidDexResolver.\nlibrary DexSlotsLink {\n    /// @dev storage slot for variables at Dex\n    uint256 internal constant DEX_VARIABLES_SLOT = 0;\n    /// @dev storage slot for variables2 at Dex\n    uint256 internal constant DEX_VARIABLES2_SLOT = 1;\n    /// @dev storage slot for total supply shares at Dex\n    uint256 internal constant DEX_TOTAL_SUPPLY_SHARES_SLOT = 2;\n    /// @dev storage slot for user supply mapping at Dex\n    uint256 internal constant DEX_USER_SUPPLY_MAPPING_SLOT = 3;\n    /// @dev storage slot for total borrow shares at Dex\n    uint256 internal constant DEX_TOTAL_BORROW_SHARES_SLOT = 4;\n    /// @dev storage slot for user borrow mapping at Dex\n    uint256 internal constant DEX_USER_BORROW_MAPPING_SLOT = 5;\n    /// @dev storage slot for oracle mapping at Dex\n    uint256 internal constant DEX_ORACLE_MAPPING_SLOT = 6;\n    /// @dev storage slot for range and threshold shifts at Dex\n    uint256 internal constant DEX_RANGE_THRESHOLD_SHIFTS_SLOT = 7;\n    /// @dev storage slot for center price shift at Dex\n    uint256 internal constant DEX_CENTER_PRICE_SHIFT_SLOT = 8;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_ALLOWED = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_ALLOWED = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Dex contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Dex contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n"},"contracts/libraries/safeTransfer.sol":{"content":"// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\n\n/// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom\nlibrary SafeTransfer {\n    uint256 internal constant MAX_NATIVE_TRANSFER_GAS = 20000; // pass max. 20k gas for native transfers\n\n    error FluidSafeTransferError(uint256 errorId_);\n\n    /// @dev Transfer `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    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63\n    function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"from_\" argument.\n            mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 68), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of `token_` to `to_`.\n    /// If `token_` returns no value, non-reverting calls are assumed to be successful.\n    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95\n    function safeTransfer(address token_, address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Get a pointer to some free memory.\n            let freeMemoryPointer := mload(0x40)\n\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n            mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \"to_\" argument.\n            mstore(add(freeMemoryPointer, 36), amount_) // Append the \"amount_\" argument. Masking not required as it's a full 32 byte type.\n\n            success_ := and(\n                // Set success to whether the call reverted, if not we check it either\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n                // Counterintuitively, this call must be positioned second to the or() call in the\n                // surrounding and() call or else returndatasize() will be zero during the computation.\n                call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32)\n            )\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n\n    /// @dev Transfer `amount_` of ` native token to `to_`.\n    /// Minimally modified from Solmate SafeTransferLib (Custom Error):\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L15-L25\n    function safeTransferNative(address to_, uint256 amount_) internal {\n        bool success_;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer the ETH and store if it succeeded or not. Pass limited gas\n            success_ := call(MAX_NATIVE_TRANSFER_GAS, to_, amount_, 0, 0, 0, 0)\n        }\n\n        if (!success_) {\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\n        }\n    }\n}\n"},"contracts/libraries/liquidityCalcs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { LibsErrorTypes as ErrorTypes } from \"./errorTypes.sol\";\nimport { LiquiditySlotsLink } from \"./liquiditySlotsLink.sol\";\nimport { BigMathMinified } from \"./bigMathMinified.sol\";\n\n/// @notice implements calculation methods used for Fluid liquidity such as updated exchange prices,\n/// borrow rate, withdrawal / borrow limits, revenue amount.\nlibrary LiquidityCalcs {\n    error FluidLiquidityCalcsError(uint256 errorId_);\n\n    /// @notice emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\n    event BorrowRateMaxCap();\n\n    /// @dev constants as from Liquidity variables.sol\n    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n\n    /// @dev Ignoring leap years\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\n    // constants used for BigMath conversion from and to storage\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant TWELVE_DECIMALS = 1e12;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X15 = 0x7fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                  CALC EXCHANGE PRICES                  /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @return supplyExchangePrice_ updated supplyExchangePrice\n    /// @return borrowExchangePrice_ updated borrowExchangePrice\n    function calcExchangePrices(\n        uint256 exchangePricesAndConfig_\n    ) internal view returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\n        // Extracting exchange prices\n        supplyExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\n            X64;\n        borrowExchangePrice_ =\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\n            X64;\n\n        if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\n        }\n\n        uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\n\n        unchecked {\n            // last timestamp can not be > current timestamp\n            uint256 secondsSinceLastUpdate_ = block.timestamp -\n                ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\n\n            uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\n                X15;\n            if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\n                // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\n                // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // calculate new borrow exchange price.\n            // formula borrowExchangePriceIncrease: previous price * borrow rate * secondsSinceLastUpdate_.\n            // nominator is max uint112 (uint64 * uint16 * uint32). Divisor can not be 0.\n            borrowExchangePrice_ +=\n                (borrowExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS);\n\n            // FOR SUPPLY EXCHANGE PRICE:\n            // all yield paid by borrowers (in mode with interest) goes to suppliers in mode with interest.\n            // formula: previous price * supply rate * secondsSinceLastUpdate_.\n            // where supply rate = (borrow rate  - revenueFee%) * ratioSupplyYield. And\n            // ratioSupplyYield = utilization * supplyRatio * borrowRatio\n            //\n            // Example:\n            // supplyRawInterest is 80, supplyInterestFree is 20. totalSupply is 100. BorrowedRawInterest is 50.\n            // BorrowInterestFree is 10. TotalBorrow is 60. borrow rate 40%, revenueFee 10%.\n            // yield is 10 (so half a year must have passed).\n            // supplyRawInterest must become worth 89. totalSupply must become 109. BorrowedRawInterest must become 60.\n            // borrowInterestFree must still be 10. supplyInterestFree still 20. totalBorrow 70.\n            // supplyExchangePrice would have to go from 1 to 1,125 (+ 0.125). borrowExchangePrice from 1 to 1,2 (+0.2).\n            // utilization is 60%. supplyRatio = 20 / 80 = 25% (only 80% of lenders receiving yield).\n            // borrowRatio = 10 / 50 = 20% (only 83,333% of borrowers paying yield):\n            // x of borrowers paying yield = 100% - (20 / (100 + 20)) = 100% - 16.6666666% = 83,333%.\n            // ratioSupplyYield = 60% * 83,33333% * (100% + 20%) = 62,5%\n            // supplyRate = (40% * (100% - 10%)) * = 36% * 62,5% = 22.5%\n            // increase in supplyExchangePrice, assuming 100 as previous price.\n            // 100 * 22,5% * 1/2 (half a year) = 0,1125.\n            // cross-check supplyRawInterest worth = 80 * 1.1125 = 89. totalSupply worth = 89 + 20.\n\n            // -------------- 1. calculate ratioSupplyYield --------------------------------\n            // step1: utilization * supplyRatio (or actually part of lenders receiving yield)\n\n            // temp_ => supplyRatio (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n            // if first bit 0 then ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n            // else ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n            temp_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) & X15;\n\n            if (temp_ == 1) {\n                // if no raw supply: no exchange price update needed\n                // (if supplyRatio_ == 1 means there is only supplyInterestFree, as first bit is 1 and rest is 0)\n                return (supplyExchangePrice_, borrowExchangePrice_);\n            }\n\n            // ratioSupplyYield precision is 1e27 as 100% for increased precision when supplyInterestFree > supplyWithInterest\n            if (temp_ & 1 == 1) {\n                // ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\n                temp_ = temp_ >> 1;\n\n                // Note: case where temp_ == 0 (only supplyInterestFree, no yield) already covered by early return\n                // in the if statement a little above.\n\n                // based on above example but supplyRawInterest is 20, supplyInterestFree is 80. no fee.\n                // supplyRawInterest must become worth 30. totalSupply must become 110.\n                // supplyExchangePrice would have to go from 1 to 1,5. borrowExchangePrice from 1 to 1,2.\n                // so ratioSupplyYield must come out as 2.5 (250%).\n                // supplyRatio would be (20 * 10_000 / 80) = 2500. but must be inverted.\n                temp_ = (1e27 * FOUR_DECIMALS) / temp_; // e.g. 1e31 / 2500 = 4e27. (* 1e27 for precision)\n                // e.g. 5_000 * (1e27 + 4e27) / 1e27 = 25_000 (=250%).\n                temp_ =\n                    // utilization * (100% + 100% / supplyRatio)\n                    (((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) *\n                        (1e27 + temp_)) / // extract utilization (max 16_383 so there is no way this can overflow).\n                    (FOUR_DECIMALS);\n                // max possible value of temp_ here is 16383 * (1e27 + 1e31) / 1e4 = ~1.64e31\n            } else {\n                // ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\n                temp_ = temp_ >> 1;\n                // if temp_ == 0 then only supplyWithInterest => full yield. temp_ is already 0\n\n                // e.g. 5_000 * 10_000 + (20 * 10_000 / 80) / 10_000 = 5000 * 12500 / 10000 = 6250 (=62.5%).\n                temp_ =\n                    // 1e27 * utilization * (100% + supplyRatio) / 100%\n                    (1e27 *\n                        ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) * // extract utilization (max 16_383 so there is no way this can overflow).\n                        (FOUR_DECIMALS + temp_)) /\n                    (FOUR_DECIMALS * FOUR_DECIMALS);\n                // max possible temp_ value: 1e27 * 16383 * 2e4 / 1e8 = 3.2766e27\n            }\n            // from here temp_ => ratioSupplyYield (utilization * supplyRatio part) scaled by 1e27. max possible value ~1.64e31\n\n            // step2 of ratioSupplyYield: add borrowRatio (only x% of borrowers paying yield)\n            if (borrowRatio_ & 1 == 1) {\n                // ratio is borrowWithInterest / borrowInterestFree (borrowInterestFree is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n\n                // Note: case where borrowRatio_ == 0 (only borrowInterestFree, no yield) already covered\n                // at the beginning of the method by early return if `borrowRatio_ == 1`.\n\n                // based on above example but borrowRawInterest is 10, borrowInterestFree is 50. no fee. borrowRatio = 20%.\n                // so only 16.66% of borrowers are paying yield. so the 100% - part of the formula is not needed.\n                // x of borrowers paying yield = (borrowRatio / (100 + borrowRatio)) = 16.6666666%\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                borrowRatio_ = (borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_);\n                // max value here for borrowRatio_ is (1e31 / (1e4 + 1e4))= 5e26 (= 50% of borrowers paying yield).\n            } else {\n                // ratio is borrowInterestFree / borrowWithInterest (borrowWithInterest is bigger)\n                borrowRatio_ = borrowRatio_ >> 1;\n\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\n                // x of borrowers paying yield = 100% - (borrowRatio / (100 + borrowRatio)) = 100% - 16.6666666% = 83,333%.\n                borrowRatio_ = (1e27 - ((borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_)));\n                // borrowRatio can never be > 100%. so max subtraction can be 100% - 100% / 200%.\n                // or if borrowRatio_ is 0 -> 100% - 0. or if borrowRatio_ is 1 -> 100% - 1 / 101.\n                // max value here for borrowRatio_ is 1e27 - 0 = 1e27 (= 100% of borrowers paying yield).\n            }\n\n            // temp_ => ratioSupplyYield. scaled down from 1e25 = 1% each to normal percent precision 1e2 = 1%.\n            // max nominator value is ~1.64e31 * 1e27 = 1.64e58. max result = 1.64e8\n            temp_ = (FOUR_DECIMALS * temp_ * borrowRatio_) / 1e54;\n\n            // 2. calculate supply rate\n            // temp_ => supply rate (borrow rate  - revenueFee%) * ratioSupplyYield.\n            // division part is done in next step to increase precision. (divided by 2x FOUR_DECIMALS, fee + borrowRate)\n            // Note that all calculation divisions for supplyExchangePrice are rounded down.\n            // Note supply rate can be bigger than the borrowRate, e.g. if there are only few lenders with interest\n            // but more suppliers not earning interest.\n            temp_ = ((exchangePricesAndConfig_ & X16) * // borrow rate\n                temp_ * // ratioSupplyYield\n                (FOUR_DECIMALS - ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14))); // revenueFee\n            // fee can not be > 100%. max possible = 65535 * ~1.64e8 * 1e4 =~1.074774e17.\n\n            // 3. calculate increase in supply exchange price\n            supplyExchangePrice_ += ((supplyExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\n                (SECONDS_PER_YEAR * FOUR_DECIMALS * FOUR_DECIMALS * FOUR_DECIMALS));\n            // max possible nominator = max uint 64 * 1.074774e17 * max uint32 = ~8.52e45. Denominator can not be 0.\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                     CALC REVENUE                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from storage\n    /// and the current balance of the Fluid liquidity contract for the token.\n    /// @param totalAmounts_ total amounts packed uint256 read from storage\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\n    /// @param liquidityTokenBalance_   current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\n    /// @return revenueAmount_ collectable revenue amount\n    function calcRevenue(\n        uint256 totalAmounts_,\n        uint256 exchangePricesAndConfig_,\n        uint256 liquidityTokenBalance_\n    ) internal view returns (uint256 revenueAmount_) {\n        // @dev no need to super-optimize this method as it is only used by admin\n\n        // calculate the new exchange prices based on earned interest\n        (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = calcExchangePrices(exchangePricesAndConfig_);\n\n        // total supply = interest free + with interest converted from raw\n        uint256 totalSupply_ = getTotalSupply(totalAmounts_, supplyExchangePrice_);\n\n        if (totalSupply_ > 0) {\n            // available revenue: balanceOf(token) + totalBorrowings - totalLendings.\n            revenueAmount_ = liquidityTokenBalance_ + getTotalBorrow(totalAmounts_, borrowExchangePrice_);\n            // ensure there is no possible case because of rounding etc. where this would revert,\n            // explicitly check if >\n            revenueAmount_ = revenueAmount_ > totalSupply_ ? revenueAmount_ - totalSupply_ : 0;\n            // Note: if utilization > 100% (totalSupply < totalBorrow), then all the amount above 100% utilization\n            // can only be revenue.\n        } else {\n            // if supply is 0, then rest of balance can be withdrawn as revenue so that no amounts get stuck\n            revenueAmount_ = liquidityTokenBalance_;\n        }\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC LIMITS                       /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev calculates withdrawal limit before an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitBeforeOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\n        // a deposit anyway. Important is that it would not revert.\n\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\n        // is the fully expanded limit immediately.\n\n        // extract last set withdrawal limit\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >>\n            LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) & X64;\n        lastWithdrawalLimit_ =\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\n        if (lastWithdrawalLimit_ == 0) {\n            // withdrawal limit is not activated. Max withdrawal allowed\n            return 0;\n        }\n\n        uint256 maxWithdrawableLimit_;\n        uint256 temp_;\n        unchecked {\n            // extract max withdrawable percent of user supply and\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\n\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxWithdrawableLimit_ =\n                (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\n                FOUR_DECIMALS;\n\n            // time elapsed since last withdrawal limit was set (in seconds)\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\n            // last timestamp can not be > current timestamp\n            temp_ =\n                block.timestamp -\n                ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\n        }\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\n        temp_ =\n            (maxWithdrawableLimit_ * temp_) /\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\n            ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\n        unchecked {\n            // underflow explicitly checked & handled\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - maxWithdrawableLimit_;\n        }\n        // if withdrawal limit is decreased below minimum then set minimum\n        // (e.g. when more than expandDuration time has elapsed)\n        if (temp_ > currentWithdrawalLimit_) {\n            currentWithdrawalLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates withdrawal limit after an operate execution:\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\n    /// @param userSupplyData_ user supply data packed uint256 from storage\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\n    ///                          raw for with interest mode, normal amount for interest free mode!\n    function calcWithdrawalLimitAfterOperate(\n        uint256 userSupplyData_,\n        uint256 userSupply_,\n        uint256 newWithdrawalLimit_\n    ) internal pure returns (uint256) {\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\n        uint256 temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // if user supply is below base limit then max withdrawals are allowed\n        if (userSupply_ < temp_) {\n            return 0;\n        }\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\n        temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\n        unchecked {\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\n        }\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\n        // increased deposit amount outpaces withrawals.\n        if (temp_ > newWithdrawalLimit_) {\n            return temp_;\n        }\n        return newWithdrawalLimit_;\n    }\n\n    /// @dev calculates borrow limit before an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\n    ///                             raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitBeforeOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_\n    ) internal view returns (uint256 currentBorrowLimit_) {\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\n\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\n\n        uint256 maxExpansionLimit_;\n        uint256 maxExpandedBorrowLimit_;\n        unchecked {\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\n\n            // calculate max borrow limit: Max point limit can increase to since last interaction\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\n        }\n\n        // currentBorrowLimit_ = extract base borrow limit\n        currentBorrowLimit_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        currentBorrowLimit_ =\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\n\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\n            return currentBorrowLimit_;\n        }\n        // time elapsed since last borrow limit was set (in seconds)\n        unchecked {\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\n            temp_ =\n                block.timestamp -\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\n        }\n\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\n        currentBorrowLimit_ =\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\n            ((maxExpansionLimit_ * temp_) /\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\n            //  extract last set borrow limit\n            BigMathMinified.fromBigNumber(\n                (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\n                DEFAULT_EXPONENT_SIZE,\n                DEFAULT_EXPONENT_MASK\n            );\n\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\n        // so set to `maxExpandedBorrowLimit_` in that case.\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (currentBorrowLimit_ > temp_) {\n            currentBorrowLimit_ = temp_;\n        }\n    }\n\n    /// @dev calculates borrow limit after an operate execution:\n    /// total amount user borrow can reach (not borrowable amount in current operation).\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\n    function calcBorrowLimitAfterOperate(\n        uint256 userBorrowData_,\n        uint256 userBorrow_,\n        uint256 newBorrowLimit_\n    ) internal pure returns (uint256 borrowLimit_) {\n        // temp_ = extract borrow expand percent\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\n\n        unchecked {\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\n        }\n\n        // temp_ = extract base borrow limit\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        if (borrowLimit_ < temp_) {\n            // below base limit, borrow limit is always base limit\n            return temp_;\n        }\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n        // make sure fully expanded borrow limit is not above hard max borrow limit\n        if (borrowLimit_ > temp_) {\n            borrowLimit_ = temp_;\n        }\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\n        if (newBorrowLimit_ > borrowLimit_) {\n            return borrowLimit_;\n        }\n        return newBorrowLimit_;\n    }\n\n    ///////////////////////////////////////////////////////////////////////////\n    //////////                      CALC RATES                        /////////\n    ///////////////////////////////////////////////////////////////////////////\n\n    /// @dev Calculates new borrow rate from utilization for a token\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_ totalBorrow / totalSupply. 1e4 = 100% utilization\n    /// @return rate_ rate for that particular token in 1e2 precision (e.g. 5% rate = 500)\n    function calcBorrowRateFromUtilization(uint256 rateData_, uint256 utilization_) internal returns (uint256 rate_) {\n        // extract rate version: 4 bits (0xF) starting from bit 0\n        uint256 rateVersion_ = (rateData_ & 0xF);\n\n        if (rateVersion_ == 1) {\n            rate_ = calcRateV1(rateData_, utilization_);\n        } else if (rateVersion_ == 2) {\n            rate_ = calcRateV2(rateData_, utilization_);\n        } else {\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__UnsupportedRateVersion);\n        }\n\n        if (rate_ > X16) {\n            // hard cap for borrow rate at maximum value 16 bits (65535) to make sure it does not overflow storage space.\n            // this is unlikely to ever happen if configs stay within expected levels.\n            rate_ = X16;\n            // emit event to more easily become aware\n            emit BorrowRateMaxCap();\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 1 (with one kink) in 1e2 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e2 precision\n    function calcRateV1(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v1 (one kink) ------------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 188 bits =>  68-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // else utilization is greater than kink\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;\n            x1_ = kink1_;\n            x2_ = FOUR_DECIMALS; // 100%\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev calculates the borrow rate based on utilization for rate data version 2 (with two kinks) in 1e4 precision\n    /// @param rateData_ rate data packed uint256 from storage for the token\n    /// @param utilization_  in 1e2 (100% = 1e4)\n    /// @return rate_ rate in 1e4 precision\n    function calcRateV2(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\n        /// For rate v2 (two kinks) -----------------------------------------------------\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Next 16  bits =>  84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\n        /// Last 156 bits => 100-255 => blank, might come in use in future\n\n        // y = mx + c.\n        // y is borrow rate\n        // x is utilization\n        // m = slope (m can also be negative for declining rates)\n        // c is constant (c can be negative)\n\n        uint256 y1_;\n        uint256 y2_;\n        uint256 x1_;\n        uint256 x2_;\n\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;\n        if (utilization_ < kink1_) {\n            // if utilization is less than kink1\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) & X16;\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n            x1_ = 0; // 0%\n            x2_ = kink1_;\n        } else {\n            // extract kink2: 16 bits (0xFFFF) starting from bit 52\n            uint256 kink2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;\n            if (utilization_ < kink2_) {\n                // if utilization is less than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                x1_ = kink1_;\n                x2_ = kink2_;\n            } else {\n                // else utilization is greater than kink2\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;\n                x1_ = kink2_;\n                x2_ = FOUR_DECIMALS;\n            }\n        }\n\n        int256 constant_;\n        int256 slope_;\n        unchecked {\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\n\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\n\n            // calculating new borrow rate\n            // - slope_ max value is 65535 * 1e12,\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\n            // - constant max value is 65535 * 1e12\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\n            // divisor TWELVE_DECIMALS can not be 0\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\n            if (slope_ < 0) {\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\n            }\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\n        }\n    }\n\n    /// @dev reads the total supply out of Liquidity packed storage `totalAmounts_` for `supplyExchangePrice_`\n    function getTotalSupply(\n        uint256 totalAmounts_,\n        uint256 supplyExchangePrice_\n    ) internal pure returns (uint256 totalSupply_) {\n        // totalSupply_ => supplyInterestFree\n        totalSupply_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\n        totalSupply_ = (totalSupply_ >> DEFAULT_EXPONENT_SIZE) << (totalSupply_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalSupplyRaw_ = totalAmounts_ & X64; // no shifting as supplyRaw is first 64 bits\n        totalSupplyRaw_ = (totalSupplyRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalSupplyRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalSupply = supplyInterestFree + supplyRawInterest normalized from raw\n        totalSupply_ += ((totalSupplyRaw_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n\n    /// @dev reads the total borrow out of Liquidity packed storage `totalAmounts_` for `borrowExchangePrice_`\n    function getTotalBorrow(\n        uint256 totalAmounts_,\n        uint256 borrowExchangePrice_\n    ) internal pure returns (uint256 totalBorrow_) {\n        // totalBorrow_ => borrowInterestFree\n        // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\n        totalBorrow_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\n        totalBorrow_ = (totalBorrow_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrow_ & DEFAULT_EXPONENT_MASK);\n\n        uint256 totalBorrowRaw_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\n        totalBorrowRaw_ = (totalBorrowRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrowRaw_ & DEFAULT_EXPONENT_MASK);\n\n        // totalBorrow = borrowInterestFree + borrowRawInterest normalized from raw\n        totalBorrow_ += ((totalBorrowRaw_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION);\n    }\n}\n"},"contracts/protocols/dex/errorTypes.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n    /***********************************|\n    |             DexT1                 | \n    |__________________________________*/\n\n    /// @notice thrown at reentrancy\n    uint256 internal constant DexT1__AlreadyEntered = 51001;\n\n    uint256 internal constant DexT1__NotAnAuth = 51002;\n\n    uint256 internal constant DexT1__SmartColNotEnabled = 51003;\n\n    uint256 internal constant DexT1__SmartDebtNotEnabled = 51004;\n\n    uint256 internal constant DexT1__PoolNotInitialized = 51005;\n\n    uint256 internal constant DexT1__TokenReservesTooLow = 51006;\n\n    uint256 internal constant DexT1__EthAndAmountInMisMatch = 51007;\n\n    uint256 internal constant DexT1__EthSentForNonNativeSwap = 51008;\n\n    uint256 internal constant DexT1__NoSwapRoute = 51009;\n\n    uint256 internal constant DexT1__NotEnoughAmountOut = 51010;\n\n    uint256 internal constant DexT1__LiquidityLayerTokenUtilizationCapReached = 51011;\n\n    uint256 internal constant DexT1__HookReturnedFalse = 51012;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserSupplyInNotOn = 51013;\n\n    // Either user's config are not set or user is paused\n    uint256 internal constant DexT1__UserDebtInNotOn = 51014;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants to give on deposit\n    uint256 internal constant DexT1__AboveDepositMax = 51015;\n\n    uint256 internal constant DexT1__MsgValueLowOnDepositOrPayback = 51016;\n\n    uint256 internal constant DexT1__WithdrawLimitReached = 51017;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on withdraw\n    uint256 internal constant DexT1__BelowWithdrawMin = 51018;\n\n    uint256 internal constant DexT1__DebtLimitReached = 51019;\n\n    // Thrown when contract gives less token0 or token1 than what user's wants on borrow\n    uint256 internal constant DexT1__BelowBorrowMin = 51020;\n\n    // Thrown when contract asks for more token0 or token1 than what user's wants on payback\n    uint256 internal constant DexT1__AbovePaybackMax = 51021;\n\n    uint256 internal constant DexT1__InvalidDepositAmts = 51022;\n\n    uint256 internal constant DexT1__DepositAmtsZero = 51023;\n\n    uint256 internal constant DexT1__SharesMintedLess = 51024;\n\n    uint256 internal constant DexT1__WithdrawalNotEnough = 51025;\n\n    uint256 internal constant DexT1__InvalidWithdrawAmts = 51026;\n\n    uint256 internal constant DexT1__WithdrawAmtsZero = 51027;\n\n    uint256 internal constant DexT1__WithdrawExcessSharesBurn = 51028;\n\n    uint256 internal constant DexT1__InvalidBorrowAmts = 51029;\n\n    uint256 internal constant DexT1__BorrowAmtsZero = 51030;\n\n    uint256 internal constant DexT1__BorrowExcessSharesMinted = 51031;\n\n    uint256 internal constant DexT1__PaybackAmtTooHigh = 51032;\n\n    uint256 internal constant DexT1__InvalidPaybackAmts = 51033;\n\n    uint256 internal constant DexT1__PaybackAmtsZero = 51034;\n\n    uint256 internal constant DexT1__PaybackSharedBurnedLess = 51035;\n\n    uint256 internal constant DexT1__NothingToArbitrage = 51036;\n\n    uint256 internal constant DexT1__MsgSenderNotLiquidity = 51037;\n\n    // On liquidity callback reentrancy bit should be on\n    uint256 internal constant DexT1__ReentrancyBitShouldBeOn = 51038;\n\n    // Thrown is reentrancy is already on and someone tries to fetch oracle price. Should not be possible to this\n    uint256 internal constant DexT1__OraclePriceFetchAlreadyEntered = 51039;\n\n    // Thrown when swap changes the current price by more than 5%\n    uint256 internal constant DexT1__OracleUpdateHugeSwapDiff = 51040;\n\n    uint256 internal constant DexT1__Token0ShouldBeSmallerThanToken1 = 51041;\n\n    uint256 internal constant DexT1__OracleMappingOverflow = 51042;\n\n    /// @notice thrown if governance has paused the swapping & arbitrage so only perfect functions are usable\n    uint256 internal constant DexT1__SwapAndArbitragePaused = 51043;\n\n    uint256 internal constant DexT1__ExceedsAmountInMax = 51044;\n\n    /// @notice thrown if amount in is too high or too low\n    uint256 internal constant DexT1__SwapInLimitingAmounts = 51045;\n\n    /// @notice thrown if amount out is too high or too low\n    uint256 internal constant DexT1__SwapOutLimitingAmounts = 51046;\n\n    uint256 internal constant DexT1__MintAmtOverflow = 51047;\n\n    uint256 internal constant DexT1__BurnAmtOverflow = 51048;\n\n    uint256 internal constant DexT1__LimitingAmountsSwapAndNonPerfectActions = 51049;\n\n    uint256 internal constant DexT1__InsufficientOracleData = 51050;\n\n    uint256 internal constant DexT1__SharesAmountInsufficient = 51051;\n\n    uint256 internal constant DexT1__CenterPriceOutOfRange = 51052;\n\n    uint256 internal constant DexT1__DebtReservesTooLow = 51053;\n\n    uint256 internal constant DexT1__SwapAndDepositTooLowOrTooHigh = 51054;\n\n    uint256 internal constant DexT1__WithdrawAndSwapTooLowOrTooHigh = 51055;\n\n    uint256 internal constant DexT1__BorrowAndSwapTooLowOrTooHigh = 51056;\n\n    uint256 internal constant DexT1__SwapAndPaybackTooLowOrTooHigh = 51057;\n\n    uint256 internal constant DexT1__InvalidImplementation = 51058;\n\n    uint256 internal constant DexT1__OnlyDelegateCallAllowed = 51059;\n\n    uint256 internal constant DexT1__IncorrectDataLength = 51060;\n\n    uint256 internal constant DexT1__AmountToSendLessThanAmount = 51061;\n\n    uint256 internal constant DexT1__InvalidCollateralReserves = 51062;\n\n    uint256 internal constant DexT1__InvalidDebtReserves = 51063;\n\n    uint256 internal constant DexT1__SupplySharesOverflow = 51064;\n\n    uint256 internal constant DexT1__BorrowSharesOverflow = 51065;\n\n    uint256 internal constant DexT1__OracleNotActive = 51066;\n\n    /***********************************|\n    |            DEX Admin              | \n    |__________________________________*/\n\n    /// @notice thrown when pool is not initialized\n    uint256 internal constant DexT1Admin__PoolNotInitialized = 52001;\n\n    uint256 internal constant DexT1Admin__SmartColIsAlreadyOn = 52002;\n\n    uint256 internal constant DexT1Admin__SmartDebtIsAlreadyOn = 52003;\n\n    /// @notice thrown when any of the configs value overflow the maximum limit\n    uint256 internal constant DexT1Admin__ConfigOverflow = 52004;\n\n    uint256 internal constant DexT1Admin__AddressNotAContract = 52005;\n\n    uint256 internal constant DexT1Admin__InvalidParams = 52006;\n\n    uint256 internal constant DexT1Admin__UserNotDefined = 52007;\n\n    uint256 internal constant DexT1Admin__OnlyDelegateCallAllowed = 52008;\n\n    uint256 internal constant DexT1Admin__UnexpectedPoolState = 52009;\n\n    /// @notice thrown when trying to pause or unpause but user is already in the target pause state\n    uint256 internal constant DexT1Admin__InvalidPauseToggle = 52009;\n\n    /***********************************|\n    |            DEX Factory            | \n    |__________________________________*/\n\n    uint256 internal constant DexFactory__InvalidOperation = 53001;\n    uint256 internal constant DexFactory__Unauthorized = 53002;\n    uint256 internal constant DexFactory__SameTokenNotAllowed = 53003;\n    uint256 internal constant DexFactory__TokenConfigNotProper = 53004;\n    uint256 internal constant DexFactory__InvalidParams = 53005;\n    uint256 internal constant DexFactory__OnlyDelegateCallAllowed = 53006;\n    uint256 internal constant DexFactory__InvalidDexAddress = 53007;\n}\n"},"contracts/libraries/bigMathMinified.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\n/// result in significant gas cost reduction due to storage space reduction.\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\nlibrary BigMathMinified {\n    /// @dev constants to use for `roundUp` input param to increase readability\n    bool internal constant ROUND_DOWN = false;\n    bool internal constant ROUND_UP = true;\n\n    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\n    /// e.g.:\n    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\n    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\n    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\n    ///                                                                        ^-------------------- 51(exponent) -------------- ^\n    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)\n    /// exponent =                                            0011,0011     (51)\n    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)\n    ///\n    /// @param normal number which needs to be converted into Big Number\n    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\n    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\n    /// @param roundUp signals if result should be rounded down or up\n    /// @return bigNumber converted bigNumber (coefficient << exponent)\n    function toBigNumber(\n        uint256 normal,\n        uint256 coefficientSize,\n        uint256 exponentSize,\n        bool roundUp\n    ) internal pure returns (uint256 bigNumber) {\n        assembly {\n            let lastBit_\n            let number_ := normal\n            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit_ := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit_ := add(lastBit_, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit_ := add(lastBit_, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit_ := add(lastBit_, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit_ := add(lastBit_, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit_ := add(lastBit_, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit_ := add(lastBit_, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if gt(number_, 0) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if lt(lastBit_, coefficientSize) {\n                // for throw exception\n                lastBit_ := coefficientSize\n            }\n            let exponent := sub(lastBit_, coefficientSize)\n            let coefficient := shr(exponent, normal)\n            if and(roundUp, gt(exponent, 0)) {\n                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\n                coefficient := add(coefficient, 1)\n                if eq(shl(coefficientSize, 1), coefficient) {\n                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\n                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\n                    coefficient := shl(sub(coefficientSize, 1), 1)\n                    exponent := add(exponent, 1)\n                }\n            }\n            if iszero(lt(exponent, shl(exponentSize, 1))) {\n                // if exponent is >= exponentSize, the normal number is too big to fit within\n                // BigNumber with too small sizes for coefficient and exponent\n                revert(0, 0)\n            }\n            bigNumber := shl(exponentSize, coefficient)\n            bigNumber := add(bigNumber, exponent)\n        }\n    }\n\n    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\n    function fromBigNumber(\n        uint256 bigNumber,\n        uint256 exponentSize,\n        uint256 exponentMask\n    ) internal pure returns (uint256 normal) {\n        assembly {\n            let coefficient := shr(exponentSize, bigNumber)\n            let exponent := and(bigNumber, exponentMask)\n            normal := shl(exponent, coefficient)\n        }\n    }\n\n    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\n    /// e.g.\n    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\n    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^\n    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\n        assembly {\n            let number_ := normal\n            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit := add(lastBit, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit := add(lastBit, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit := add(lastBit, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit := add(lastBit, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit := add(lastBit, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit := add(lastBit, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit := add(lastBit, 1)\n            }\n            if gt(number_, 0) {\n                lastBit := add(lastBit, 1)\n            }\n        }\n    }\n}\n"},"solmate/src/utils/FixedPointMathLib.sol":{"content":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\nlibrary FixedPointMathLib {\n    /*//////////////////////////////////////////////////////////////\n                    SIMPLIFIED FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\n\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n    }\n\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n    }\n\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n    }\n\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    LOW LEVEL FIXED POINT OPERATIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function mulDivDown(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // Divide x * y by the denominator.\n            z := div(mul(x, y), denominator)\n        }\n    }\n\n    function mulDivUp(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\n                revert(0, 0)\n            }\n\n            // If x * y modulo the denominator is strictly greater than 0,\n            // 1 is added to round up the division of x * y by the denominator.\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\n        }\n    }\n\n    function rpow(\n        uint256 x,\n        uint256 n,\n        uint256 scalar\n    ) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 {\n                    // 0 ** 0 = 1\n                    z := scalar\n                }\n                default {\n                    // 0 ** n = 0\n                    z := 0\n                }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 {\n                    // If n is even, store scalar in z for now.\n                    z := scalar\n                }\n                default {\n                    // If n is odd, store x in z for now.\n                    z := x\n                }\n\n                // Shifting right by 1 is like dividing by 2.\n                let half := shr(1, scalar)\n\n                for {\n                    // Shift n right by 1 before looping to halve it.\n                    n := shr(1, n)\n                } n {\n                    // Shift n right by 1 each iteration to halve it.\n                    n := shr(1, n)\n                } {\n                    // Revert immediately if x ** 2 would overflow.\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\n                    if shr(128, x) {\n                        revert(0, 0)\n                    }\n\n                    // Store x squared.\n                    let xx := mul(x, x)\n\n                    // Round to the nearest number.\n                    let xxRound := add(xx, half)\n\n                    // Revert if xx + half overflowed.\n                    if lt(xxRound, xx) {\n                        revert(0, 0)\n                    }\n\n                    // Set x to scaled xxRound.\n                    x := div(xxRound, scalar)\n\n                    // If n is even:\n                    if mod(n, 2) {\n                        // Compute z * x.\n                        let zx := mul(z, x)\n\n                        // If z * x overflowed:\n                        if iszero(eq(div(zx, x), z)) {\n                            // Revert if x is non-zero.\n                            if iszero(iszero(x)) {\n                                revert(0, 0)\n                            }\n                        }\n\n                        // Round to the nearest number.\n                        let zxRound := add(zx, half)\n\n                        // Revert if zx + half overflowed.\n                        if lt(zxRound, zx) {\n                            revert(0, 0)\n                        }\n\n                        // Return properly scaled zxRound.\n                        z := div(zxRound, scalar)\n                    }\n                }\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        GENERAL NUMBER UTILITIES\n    //////////////////////////////////////////////////////////////*/\n\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let y := x // We start y at x, which will help us make our initial estimate.\n\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // We check y >= 2^(k + 8) but shift right by k bits\n            // each branch to ensure that if x >= 256, then y >= 256.\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n                y := shr(128, y)\n                z := shl(64, z)\n            }\n            if iszero(lt(y, 0x1000000000000000000)) {\n                y := shr(64, y)\n                z := shl(32, z)\n            }\n            if iszero(lt(y, 0x10000000000)) {\n                y := shr(32, y)\n                z := shl(16, z)\n            }\n            if iszero(lt(y, 0x1000000)) {\n                y := shr(16, y)\n                z := shl(8, z)\n            }\n\n            // Goal was to get z*z*y within a small factor of x. More iterations could\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n            // There is no overflow risk here since y < 2^136 after the first branch above.\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If x+1 is a perfect square, the Babylonian method cycles between\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Mod x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            z := mod(x, y)\n        }\n    }\n\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Divide x by y. Note this will return\n            // 0 instead of reverting if y is zero.\n            r := div(x, y)\n        }\n    }\n\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Add 1 to x * y if x % y > 0. Note this will\n            // return 0 instead of reverting if y is zero.\n            z := add(gt(mod(x, y), 0), div(x, y))\n        }\n    }\n}\n"},"contracts/libraries/liquiditySlotsLink.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\nlibrary LiquiditySlotsLink {\n    /// @dev storage slot for status at Liquidity\n    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\n    /// @dev storage slot for auths mapping at Liquidity\n    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\n    /// @dev storage slot for guardians mapping at Liquidity\n    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\n    /// @dev storage slot for user class mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\n    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\n    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\n    /// @dev storage slot for rateData mapping at Liquidity\n    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\n    /// @dev storage slot for totalAmounts mapping at Liquidity\n    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\n    /// @dev storage slot for user supply double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\n    /// @dev storage slot for user borrow double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // ExchangePricesAndConfig\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\n    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\n    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\n    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\n\n    // RateData:\n    uint256 internal constant BITS_RATE_DATA_VERSION = 0;\n    // RateData: V1\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\n    // RateData: V2\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\n\n    // TotalAmounts\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_MODE = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\n\n    // Configs2\n    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n"},"contracts/liquidity/adminModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct AddressBool {\n        address addr;\n        bool value;\n    }\n\n    struct AddressUint256 {\n        address addr;\n        uint256 value;\n    }\n\n    /// @notice struct to set borrow rate data for version 1\n    struct RateDataV1Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\n        uint256 kink;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink;\n        ///\n        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set borrow rate data for version 2\n    struct RateDataV2Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\n        uint256 kink1;\n        ///\n        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\n        uint256 kink2;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink1;\n        ///\n        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\n        uint256 rateAtUtilizationKink2;\n        ///\n        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set token config\n    struct TokenConfig {\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\n        uint256 fee;\n        ///\n        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\n        uint256 threshold;\n        ///\n        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\n        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).\n        uint256 maxUtilization;\n    }\n\n    /// @notice struct to set user supply & withdrawal config\n    struct UserSupplyConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which withdrawal limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration withdrawal limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseWithdrawalLimit;\n    }\n\n    /// @notice struct to set user borrow & payback config\n    struct UserBorrowConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which debt limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration debt limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\n        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseDebtCeiling;\n        ///\n        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 maxDebtCeiling;\n    }\n}\n"},"contracts/infiniteProxy/interfaces/iProxy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IProxy {\n    function setAdmin(address newAdmin_) external;\n\n    function setDummyImplementation(address newDummyImplementation_) external;\n\n    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\n\n    function removeImplementation(address implementation_) external;\n\n    function getAdmin() external view returns (address);\n\n    function getDummyImplementation() external view returns (address);\n\n    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\n\n    function getSigsImplementation(bytes4 sig_) external view returns (address);\n\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"},"contracts/liquidity/interfaces/iLiquidity.sol":{"content":"//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IProxy } from \"../../infiniteProxy/interfaces/iProxy.sol\";\nimport { Structs as AdminModuleStructs } from \"../adminModule/structs.sol\";\n\ninterface IFluidLiquidityAdmin {\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\n    /// @param authsStatus_ array of structs setting allowed status for an address.\n    ///                     status true => add auth, false => remove auth\n    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\n\n    /// @notice adds/removes guardians. Only callable by Governance.\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\n    ///                         status true => add guardian, false => remove guardian\n    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\n\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n    /// @param revenueCollector_  new revenue collector address\n    function updateRevenueCollector(address revenueCollector_) external;\n\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n    /// @param newStatus_ new status\n    ///        status = 2 -> pause, status = 1 -> resume.\n    function changeStatus(uint256 newStatus_) external;\n\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\n    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\n\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\n    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\n\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n    ///         Only callable by Auths.\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\n    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\n\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n    ///         Only callable by Auths.\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\n    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\n\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\n\n    /// @notice sets a new withdrawal limit as the current limit for a certain user\n    /// @param user_ user address for which to update the withdrawal limit\n    /// @param token_ token address for which to update the withdrawal limit\n    /// @param newLimit_ new limit until which user supply can decrease to.\n    ///                  Important: input in raw. Must account for exchange price in input param calculation.\n    ///                  Note any limit that is < max expansion or > current user supply will set max expansion limit or\n    ///                  current user supply as limit respectively.\n    ///                  - set 0 to make maximum possible withdrawable: instant full expansion, and if that goes\n    ///                  below base limit then fully down to 0.\n    ///                  - set type(uint256).max to make current withdrawable 0 (sets current user supply as limit).\n    function updateUserWithdrawalLimit(address user_, address token_, uint256 newLimit_) external;\n\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\n\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to pause operations for\n    /// @param supplyTokens_  token addresses to pause withdrawals for\n    /// @param borrowTokens_  token addresses to pause borrowings for\n    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to unpause operations for\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\n    /// @param borrowTokens_  token addresses to unpause borrowings for\n    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\n    /// @param tokens_  array of tokens to collect revenue for\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\n    function collectRevenue(address[] calldata tokens_) external;\n\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\n    /// @param tokens_ tokens to update exchange prices for\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\n    function updateExchangePrices(\n        address[] calldata tokens_\n    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\n}\n\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\n    /// @notice Single function which handles supply, withdraw, borrow & payback\n    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\n    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\n    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\n    /// @param withdrawTo_ if withdrawal then to which address\n    /// @param borrowTo_ if borrow then to which address\n    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\n    /// @return memVar3_ updated supplyExchangePrice\n    /// @return memVar4_ updated borrowExchangePrice\n    /// @dev to trigger skipping in / out transfers (gas optimization):\n    /// -  ` callbackData_` MUST be encoded so that \"from\" address is the last 20 bytes in the last 32 bytes slot,\n    ///     also for native token operations where liquidityCallback is not triggered!\n    ///     from address must come at last position if there is more data. I.e. encode like:\n    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\n    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\n    /// -   this \"from\" address must match withdrawTo_ or borrowTo_ and must be == `msg.sender`\n    /// -   `callbackData_` must in addition to the from address as described above include bytes32 SKIP_TRANSFERS\n    ///     in the slot before (bytes 32 to 63)\n    /// -   `msg.value` must be 0.\n    /// -   Amounts must be either:\n    ///     -  supply(+) == borrow(+), withdraw(-) == payback(-).\n    ///     -  Liquidity must be on the winning side (deposit < borrow OR payback < withdraw).\n    function operate(\n        address token_,\n        int256 supplyAmount_,\n        int256 borrowAmount_,\n        address withdrawTo_,\n        address borrowTo_,\n        bytes calldata callbackData_\n    ) external payable returns (uint256 memVar3_, uint256 memVar4_);\n}\n\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\n"},"contracts/protocols/dex/interfaces/iDexT1.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexT1 {\n    error FluidDexError(uint256 errorId);\n\n    /// @notice used to simulate swap to find the output amount\n    error FluidDexSwapResult(uint256 amountOut);\n\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\n\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\n\n    error FluidDexLiquidityOutput(uint256 shares);\n\n    error FluidDexPricesAndExchangeRates(PricesAndExchangePrice pex_);\n\n    /// @notice returns the dex id\n    function DEX_ID() external view returns (uint256);\n\n    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndOracle;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) external view returns (CollateralReserves memory c_);\n\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) external view returns (DebtReserves memory d_);\n\n    // reverts with FluidDexPricesAndExchangeRates(pex_);\n    function getPricesAndExchangePrices() external;\n\n    function constantsView() external view returns (ConstantViews memory constantsView_);\n\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_);\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param amountOutMin_ The minimum amount of output tokens the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) external payable returns (uint256 amountOut_);\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) external payable returns (uint256 amountIn_);\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) external returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) external returns (uint shares_);\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) external payable returns (uint shares_);\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) external returns (\n        uint withdrawAmt_\n    );\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) external payable returns (\n        uint paybackAmt_\n    );\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (\n        Oracle[] memory twaps_,\n        uint currentPrice_\n    );\n}\n"},"contracts/protocols/dex/interfaces/iDexFactory.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidDexFactory {\n    /// @notice Global auth is auth for all dexes\n    function isGlobalAuth(address auth_) external view returns (bool);\n\n    /// @notice Dex auth is auth for a specific dex\n    function isDexAuth(address vault_, address auth_) external view returns (bool);\n\n    /// @notice Total dexes deployed.\n    function totalDexes() external view returns (uint256);\n\n    /// @notice Compute dexAddress\n    function getDexAddress(uint256 dexId_) external view returns (address);\n\n    /// @notice read uint256 `result_` for a storage `slot_` key\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"},"contracts/protocols/dex/poolT1/common/variables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Variables {\n    /*//////////////////////////////////////////////////////////////\n                          STORAGE VARIABLES\n    //////////////////////////////////////////////////////////////*/\n\n    /// First 1 bit  => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\n    /// Next 40 bits => 1-40 => last to last stored price. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 41-80 => last stored price of pool. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 40 bits => 81-120 => center price. Center price from where the ranges will be calculated. BigNumber (32 bits precision, 8 bits exponent)\n    /// Next 33 bits => 121-153 => last interaction time stamp\n    /// Next 22 bits => 154-175 => max 4194303 seconds (~1165 hrs, ~48.5 days), time difference between last to last and last price stored\n    /// Next 3 bits  => 176-178 => oracle checkpoint, if 0 then first slot, if 7 then last slot\n    /// Next 16 bits => 179-194 => current mapping or oracle, after every 8 transaction it will increase by 1. Max capacity is 65535 but it can be lower than that check dexVariables2\n    /// Next 1 bit  => 195 => is oracle active?\n    uint internal dexVariables;\n\n    /// Next  1 bit  => 0 => is smart collateral enabled?\n    /// Next  1 bit  => 1 => is smart debt enabled?\n    /// Next 17 bits => 2-18 => fee (1% = 10000, max value: 100000 = 10%, fee should not be more than 10%)\n    /// Next  7 bits => 19-25 => revenue cut from fee (1 = 1%, 100 = 100%). If fee is 1000 = 0.1% and revenue cut is 10 = 10% then governance get 0.01% of every swap\n    /// Next  1 bit  => 26 => percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 20 bits => 27-46 => upperPercent (1% = 10000, max value: 104.8575%) upperRange - upperRange * upperPercent = centerPrice. Hence, upperRange = centerPrice / (1 - upperPercent)\n    /// Next 20 bits => 47-66 => lowerPercent. lowerRange = centerPrice - centerPrice * lowerPercent.\n    /// Next  1 bit  => 67 => threshold percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\n    /// Next 10 bits => 68-77 => upper shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice > (centerPrice + (upperRange - centerPrice) * (1000 - upperShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 10 bits => 78-87 => lower shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice < (centerPrice - (centerPrice - lowerRange) * (1000 - lowerShiftThresholdPercent) / 1000) then trigger shift\n    /// Next 24 bits => 88-111 => Shifting time (~194 days) (rate = (% up + % down) / time ?)\n    /// Next 30 bits => 112-131 => Address of center price if center price should be fetched externally, for example, for wstETH <> ETH pool, fetch wstETH exchange rate into stETH from wstETH contract.\n    /// Why fetch it externally? Because let's say pool width is 0.1% and wstETH temporarily got depeg of 0.5% then pool will start to shift to newer pricing\n    /// but we don't want pool to shift to 0.5% because we know the depeg will recover so to avoid the loss for users.\n    /// Next 30 bits => 142-171 => Hooks bits, calculate hook address by storing deployment nonce from factory.\n    /// Next 28 bits => 172-199 => max center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 28 bits => 200-227 => min center price. BigNumber (20 bits precision, 8 bits exponent)\n    /// Next 10 bits => 228-237 => utilization limit of token0. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 10 bits => 238-247 => utilization limit of token1. Max value 1000 = 100%, if 100% then no need to check the utilization.\n    /// Next 1  bit  => 248     => is center price shift active\n    /// Last 1  bit  => 255     => Pause swap & arbitrage (only perfect functions will be usable), if we need to pause entire DEX then that can be done through pausing DEX on Liquidity Layer\n    uint internal dexVariables2;\n\n    /// first 128 bits => 0-127 => total supply shares\n    /// last 128 bits => 128-255 => max supply shares\n    uint internal _totalSupplyShares;\n\n    /// @dev user supply data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userSupplyData. Hence exact same supply & borrow limit library can be used\n    /// First  1 bit  =>       0 => is user allowed to supply? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user supply amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user withdrawal limit; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383).\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (aka shares can be burned); BigMath: 10 | 8\n    /// Next  38 bits => 218-255 => empty for future use\n    mapping(address => uint) internal _userSupplyData;\n\n    /// first 128 bits => 0-127 => total borrow shares\n    /// last 128 bits => 128-255 => max borrow shares\n    uint internal _totalBorrowShares;\n\n    /// @dev user borrow data: user -> data\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userBorrowData. Hence exact same supply & borrow limit library function can be used\n    /// First  1 bit  =>       0 => is user allowed to borrow? 0 = not allowed, 1 = allowed\n    /// Next  64 bits =>   1- 64 => user debt amount/shares; BigMath: 56 | 8\n    /// Next  64 bits =>  65-128 => previous user debt ceiling; BigMath: 56 | 8\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\n    /// Next  14 bits => 162-175 => expand debt ceiling percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\n    ///                             @dev shrinking is instant\n    /// Next  24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days)\n    /// Next  18 bits => 200-217 => base debt ceiling: below this, there's no debt ceiling limits; BigMath: 10 | 8\n    /// Next  18 bits => 218-235 => max debt ceiling: absolute maximum debt ceiling can expand to; BigMath: 10 | 8\n    /// Next  20 bits => 236-255 => empty for future use\n    mapping(address => uint) internal _userBorrowData;\n\n    /// Price difference between last swap of last block & last swap of new block\n    /// If last swap happened at Block B - 4 and next swap happened after 4 blocks at Block B then it will store that difference\n    /// considering time difference between these 4 blocks is 48 seconds, hence time will be stored as 48\n    /// New oracle update:\n    /// time to 9 bits and precision to 22 bits\n    /// if time exceeds 9 bits which is 511 sec or ~8.5 min then we will use 2 oracle slot to store the data\n    /// we will leave the both time slot as 0 and on first sign + precision slot we will store time and\n    /// on second sign + precision slot we will store sign & precision\n    /// First 9 bits =>   0-  8 => time, 511 seconds\n    /// Next   1 bit  =>  9     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  10- 31 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  32- 40 => time, 511 seconds\n    /// Next   1 bit  =>  41     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  42- 63 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  64- 72 => time, 511 seconds\n    /// Next   1 bit  =>  73     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits =>  74- 95 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits =>  96-104 => time, 511 seconds\n    /// Next   1 bit  => 105     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 106-127 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 128-136 => time, 511 seconds\n    /// Next   1 bit  => 137     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 138-159 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 160-168 => time, 511 seconds\n    /// Next   1 bit  => 169     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 170-191 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 192-200 => time, 511 seconds\n    /// Next   1 bit  => 201     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 202-223 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    /// Next  9 bits => 224-232 => time, 511 seconds\n    /// Next   1 bit  => 233     => sign of percent in change, if 1 then 0 or positive, else negative\n    /// Next  22 bits => 234-255 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\n    mapping(uint => uint) internal _oracle;\n\n    /// First 20 bits =>  0-19 => old upper shift\n    /// Next  20 bits => 20-39 => old lower shift\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    uint128 internal _rangeShift;\n\n    /// First 10 bits =>  0- 9 => old upper shift\n    /// Next  10 bits => 10-19 => empty so we can use same helper function\n    /// Next  10 bits => 20-29 => old lower shift\n    /// Next  10 bits => 30-39 => empty so we can use same helper function\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\n    /// Next  24 bits => 93-116 => old threshold time\n    uint128 internal _thresholdShift;\n\n    /// Shifting is fuzzy and with time it'll keep on getting closer and then eventually get over\n    /// First 33 bits => 0 -32 => starting timestamp\n    /// Next  20 bits => 33-52 => % shift\n    /// Next  20 bits => 53-72 => time to shift that percent\n    uint256 internal _centerPriceShift;\n}\n"},"contracts/protocols/dex/poolT1/coreModule/events.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n    /// @notice Emitted on token swaps\n    /// @param swap0to1 Indicates whether the swap is from token0 to token1 or vice-versa.\n    /// @param amountIn The amount of tokens to be sent to the vault to swap.\n    /// @param amountOut The amount of tokens user got from the swap.\n    /// @param to Recepient of swapped tokens.\n    event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to);\n\n    /// @notice Emitted when liquidity is added with shares specified.\n    /// @param shares Expected exact shares to be received.\n    /// @param token0Amt Amount of token0 deposited.\n    /// @param token0Amt Amount of token1 deposited.\n    event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is borrowed with shares specified.\n    /// @param shares shares minted\n    /// @param token0Amt Amount of token0 borrowed.\n    /// @param token1Amt Amount of token1 borrowed.\n    event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is deposited with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 deposited.\n    /// @param amount1 Amount of token1 deposited.\n    /// @param shares Amount of shares minted.\n    event LogDepositColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 withdrawn.\n    /// @param amount1 Amount of token1 withdrawn.\n    /// @param shares Amount of shares burned.\n    event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is borrowed with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 borrowed.\n    /// @param amount1 Amount of token1 borrowed.\n    /// @param shares Amount of shares minted.\n    event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is paid back with specified token0 & token1 amount\n    /// @param amount0 Amount of token0 paid back.\n    /// @param amount1 Amount of token1 paid back.\n    /// @param shares Amount of shares burned.\n    event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares);\n\n    /// @notice Emitted when liquidity is withdrawn with shares specified into one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 withdrawn.\n    /// @param token1Amt Amount of token1 withdrawn.\n    event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when liquidity is paid back with shares specified from one token only.\n    /// @param shares shares burned\n    /// @param token0Amt Amount of token0 paid back.\n    /// @param token1Amt Amount of token1 paid back.\n    event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt);\n\n    /// @notice Emitted when internal arbitrage between 2 pools happen\n    /// @param routing if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback\n    /// @param amtOut if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow\n    event LogArbitrage(int routing, uint amtOut);\n}\n"},"contracts/protocols/dex/poolT1/coreModule/structs.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct PricesAndExchangePrice {\n        uint lastStoredPrice; // last stored price in 1e27 decimals\n        uint centerPrice; // last stored price in 1e27 decimals\n        uint upperRange; // price at upper range in 1e27 decimals\n        uint lowerRange; // price at lower range in 1e27 decimals\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct ExchangePrices {\n        uint supplyToken0ExchangePrice;\n        uint borrowToken0ExchangePrice;\n        uint supplyToken1ExchangePrice;\n        uint borrowToken1ExchangePrice;\n    }\n\n    struct CollateralReserves {\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct CollateralReservesSwap {\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct DebtReserves {\n        uint token0Debt;\n        uint token1Debt;\n        uint token0RealReserves;\n        uint token1RealReserves;\n        uint token0ImaginaryReserves;\n        uint token1ImaginaryReserves;\n    }\n\n    struct DebtReservesSwap {\n        uint tokenInDebt;\n        uint tokenOutDebt;\n        uint tokenInRealReserves;\n        uint tokenOutRealReserves;\n        uint tokenInImaginaryReserves;\n        uint tokenOutImaginaryReserves;\n    }\n\n    struct SwapInMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtInAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee; // fee of pool\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n    }\n\n    struct SwapOutMemory {\n        address tokenIn;\n        address tokenOut;\n        uint256 amtOutAdjusted;\n        address withdrawTo;\n        address borrowTo;\n        uint price; // price of pool after swap\n        uint fee;\n        uint revenueCut; // revenue cut of pool\n        bool swap0to1;\n        int swapRoutingAmt;\n        bytes data; // just added to avoid stack-too-deep error\n        uint msgValue;\n    }\n\n    struct DepositColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n    }\n\n    struct WithdrawColMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0ReservesInitial;\n        uint256 token1ReservesInitial;\n        address to;\n    }\n\n    struct BorrowDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n        address to;\n    }\n\n    struct PaybackDebtMemory {\n        uint256 token0AmtAdjusted;\n        uint256 token1AmtAdjusted;\n        uint256 token0DebtInitial;\n        uint256 token1DebtInitial;\n    }\n\n    struct OraclePriceMemory {\n        uint lowestPrice1by0;\n        uint highestPrice1by0;\n        uint oracleSlot;\n        uint oracleMap;\n        uint oracle;\n    }\n\n    struct Oracle {\n        uint twap1by0; // TWAP price\n        uint lowestPrice1by0; // lowest price point\n        uint highestPrice1by0; // highest price point\n        uint twap0by1; // TWAP price\n        uint lowestPrice0by1; // lowest price point\n        uint highestPrice0by1; // highest price point\n    }\n\n    struct Implementations {\n        address shift;\n        address admin;\n        address colOperations;\n        address debtOperations;\n        address perfectOperationsAndSwapOut;\n    }\n\n    struct ConstantViews {\n        uint256 dexId;\n        address liquidity;\n        address factory;\n        Implementations implementations;\n        address deployerContract;\n        address token0;\n        address token1;\n        bytes32 supplyToken0Slot;\n        bytes32 borrowToken0Slot;\n        bytes32 supplyToken1Slot;\n        bytes32 borrowToken1Slot;\n        bytes32 exchangePriceToken0Slot;\n        bytes32 exchangePriceToken1Slot;\n        uint256 oracleMapping;\n    }\n\n    struct ConstantViews2 {\n        uint token0NumeratorPrecision;\n        uint token0DenominatorPrecision;\n        uint token1NumeratorPrecision;\n        uint token1DenominatorPrecision;\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { CoreHelpers } from \"../helpers/coreHelpers.sol\";\nimport { SafeTransfer } from \"../../../../../libraries/safeTransfer.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IFluidDexT1 } from \"../../../interfaces/iDexT1.sol\";\n\ninterface IDexCallback {\n    function dexCallback(address token_, uint256 amount_) external;\n}\n\n/// @title FluidDexT1\n/// @notice Implements core logics for Fluid Dex protocol.\n/// Note Token transfers happen directly from user to Liquidity contract and vice-versa.\ncontract FluidDexT1 is CoreHelpers {\n    using BigMathMinified for uint256;\n\n    constructor(ConstantViews memory constantViews_) CoreHelpers(constantViews_) {\n        // any implementations should not be zero\n        if (\n            constantViews_.implementations.shift == address(0) ||\n            constantViews_.implementations.admin == address(0) ||\n            constantViews_.implementations.colOperations == address(0) ||\n            constantViews_.implementations.debtOperations == address(0) ||\n            constantViews_.implementations.perfectOperationsAndSwapOut == address(0)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__InvalidImplementation);\n        }\n    }\n\n    struct SwapInExtras {\n        address to;\n        uint amountOutMin;\n        bool isCallback;\n    }\n\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of input tokens to swap\n    /// @param extras_ Additional parameters for the swap:\n    ///   - to: Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    ///   - amountOutMin: The minimum amount of output tokens the user expects to receive\n    ///   - isCallback: If true, indicates that the input tokens should be transferred via a callback\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function _swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        SwapInExtras memory extras_\n    ) internal returns (uint256 amountOut_) {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);\n\n        _check(dexVariables_, dexVariables2_);\n\n        if (extras_.to == address(0)) extras_.to = msg.sender;\n\n        SwapInMemory memory s_;\n\n        if (swap0to1_) {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION;\n            }\n        } else {\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);\n            unchecked {\n                s_.amtInAdjusted = (amountIn_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION;\n            }\n        }\n\n        _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);\n\n        if (msg.value > 0) {\n            if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);\n            if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);\n        }\n\n        // is smart collateral pool enabled\n        uint temp_ = dexVariables2_ & 1;\n        // is smart debt pool enabled\n        uint temp2_ = (dexVariables2_ >> 1) & 1;\n\n        uint temp3_;\n        uint temp4_;\n\n        // extracting fee\n        temp3_ = ((dexVariables2_ >> 2) & X17);\n        unchecked {\n            // revenueCut in 6 decimals, to have proper precision\n            // if fee = 1% and revenue cut = 10% then revenueCut = 1e8 - (10000 * 10) = 99900000\n            s_.revenueCut = EIGHT_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_));\n            // fee in 4 decimals\n            // 1 - fee. If fee is 1% then withoutFee will be 1e6 - 1e4\n            // s_.fee => 1 - withdraw fee\n            s_.fee = SIX_DECIMALS - temp3_;\n        }\n\n        CollateralReservesSwap memory cs_;\n        DebtReservesSwap memory ds_;\n        if (temp_ == 1) {\n            // smart collateral is enabled\n            {\n                CollateralReserves memory c_ = _getCollateralReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.supplyToken0ExchangePrice,\n                    pex_.supplyToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token0RealReserves,\n                        c_.token1RealReserves,\n                        c_.token0ImaginaryReserves,\n                        c_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        cs_.tokenInRealReserves,\n                        cs_.tokenOutRealReserves,\n                        cs_.tokenInImaginaryReserves,\n                        cs_.tokenOutImaginaryReserves\n                    ) = (\n                        c_.token1RealReserves,\n                        c_.token0RealReserves,\n                        c_.token1ImaginaryReserves,\n                        c_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        if (temp2_ == 1) {\n            // smart debt is enabled\n            {\n                DebtReserves memory d_ = _getDebtReserves(\n                    pex_.geometricMean,\n                    pex_.upperRange,\n                    pex_.lowerRange,\n                    pex_.borrowToken0ExchangePrice,\n                    pex_.borrowToken1ExchangePrice\n                );\n                if (swap0to1_) {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token0Debt,\n                        d_.token1Debt,\n                        d_.token0RealReserves,\n                        d_.token1RealReserves,\n                        d_.token0ImaginaryReserves,\n                        d_.token1ImaginaryReserves\n                    );\n                } else {\n                    (\n                        ds_.tokenInDebt,\n                        ds_.tokenOutDebt,\n                        ds_.tokenInRealReserves,\n                        ds_.tokenOutRealReserves,\n                        ds_.tokenInImaginaryReserves,\n                        ds_.tokenOutImaginaryReserves\n                    ) = (\n                        d_.token1Debt,\n                        d_.token0Debt,\n                        d_.token1RealReserves,\n                        d_.token0RealReserves,\n                        d_.token1ImaginaryReserves,\n                        d_.token0ImaginaryReserves\n                    );\n                }\n            }\n        }\n\n        // limiting amtInAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenIn reserves combined\n        // basically, if this throws that means user is trying to swap 0.5x tokenIn if current tokenIn imaginary reserves is x\n        // let's take x as token0 here, that means, initially the pool pricing might be:\n        // token1Reserve / x and new pool pricing will become token1Reserve / 1.5x (token1Reserve will decrease after swap but for simplicity ignoring that)\n        // So pool price is decreased by ~33.33% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand)\n        unchecked {\n            if (s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2))\n                revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);\n        }\n\n        if (temp_ == 1 && temp2_ == 1) {\n            // unless both pools are enabled s_.swapRoutingAmt will be 0\n            s_.swapRoutingAmt = _swapRoutingIn(\n                s_.amtInAdjusted,\n                cs_.tokenOutImaginaryReserves,\n                cs_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves,\n                ds_.tokenInImaginaryReserves\n            );\n        }\n\n        // In below if else statement temps are:\n        // temp_ => deposit amt\n        // temp2_ => withdraw amt\n        // temp3_ => payback amt\n        // temp4_ => borrow amt\n        if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {\n            // swap will route from the both pools\n            // temp_ = amountInCol_\n            temp_ = uint(s_.swapRoutingAmt);\n            unchecked {\n                // temp3_ = amountInDebt_\n                temp3_ = s_.amtInAdjusted - temp_;\n            }\n\n            (temp2_, temp4_) = (0, 0);\n\n            // debt pool price will be the same as collateral pool after the swap\n            s_.withdrawTo = extras_.to;\n            s_.borrowTo = extras_.to;\n        } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {\n            // entire swap will route through collateral pool\n            (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);\n            // price can slightly differ from debt pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.withdrawTo = extras_.to;\n        } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {\n            // entire swap will route through debt pool\n            (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);\n            // price can slightly differ from collateral pool but difference will be very small. Probably <0.01% for active DEX pools.\n            s_.borrowTo = extras_.to;\n        } else {\n            // swap should never reach this point but if it does then reverting\n            revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);\n        }\n\n        if (temp_ > 0) {\n            // temp2_ = amountOutCol_\n            temp2_ = _getAmountOut(\n                ((temp_ * s_.fee) / SIX_DECIMALS),\n                cs_.tokenInImaginaryReserves,\n                cs_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (cs_.tokenInRealReserves + temp_),\n                    (cs_.tokenOutRealReserves - temp2_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (cs_.tokenOutRealReserves - temp2_),\n                    (cs_.tokenInRealReserves + temp_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n        if (temp3_ > 0) {\n            // temp4_ = amountOutDebt_\n            temp4_ = _getAmountOut(\n                ((temp3_ * s_.fee) / SIX_DECIMALS),\n                ds_.tokenInImaginaryReserves,\n                ds_.tokenOutImaginaryReserves\n            );\n            swap0to1_\n                ? _verifyToken1Reserves(\n                    (ds_.tokenInRealReserves + temp3_),\n                    (ds_.tokenOutRealReserves - temp4_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                )\n                : _verifyToken0Reserves(\n                    (ds_.tokenOutRealReserves - temp4_),\n                    (ds_.tokenInRealReserves + temp3_),\n                    pex_.centerPrice,\n                    MINIMUM_LIQUIDITY_SWAP\n                );\n        }\n\n        // (temp_ + temp3_) == amountIn_ == msg.value (for native token), if there is revenue cut then this statement is not true\n        temp_ = (temp_ * s_.revenueCut) / EIGHT_DECIMALS;\n        temp3_ = (temp3_ * s_.revenueCut) / EIGHT_DECIMALS;\n\n        // from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same\n        if (temp_ > temp3_) {\n            // new pool price from col pool\n            s_.price = swap0to1_\n                ? ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_)\n                : ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);\n        } else {\n            // new pool price from debt pool\n            s_.price = swap0to1_\n                ? ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_)\n                : ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);\n        }\n\n        // converting into normal token amounts\n        if (swap0to1_) {\n            temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            }\n        } else {\n            temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\n            // only adding uncheck in out amount\n            unchecked {\n                temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n                temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\n            }\n        }\n\n        unchecked {\n            amountOut_ = temp2_ + temp4_;\n        }\n\n        // if address dead then reverting with amountOut\n        if (extras_.to == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);\n\n        if (amountOut_ < extras_.amountOutMin) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);\n\n        // allocating to avoid stack-too-deep error\n        // not setting in the callbackData as last 2nd to avoid SKIP_TRANSFERS clashing\n        s_.data = abi.encode(amountIn_, extras_.isCallback, msg.sender); // true/false is to decide if dex should do callback or directly transfer from user\n        // deposit & payback token in at liquidity\n        LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);\n        // withdraw & borrow token out at liquidity\n        LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));\n\n        // if hook exists then calling hook\n        temp_ = (dexVariables2_ >> 142) & X30;\n        if (temp_ > 0) {\n            s_.swap0to1 = swap0to1_;\n            _hookVerify(temp_, 1, s_.swap0to1, s_.price);\n        }\n\n        swap0to1_\n            ? _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT)\n            : _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);\n\n        dexVariables = _updateOracle(s_.price, pex_.centerPrice, dexVariables_);\n\n        emit Swap(swap0to1_, amountIn_, amountOut_, extras_.to);\n    }\n\n    /// @dev Swap tokens with perfect amount in\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapIn(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, false));\n    }\n\n    /// @dev Swap tokens with perfect amount in and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountIn_ The exact amount of tokens to swap in\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\n    /// @return amountOut_ The amount of output tokens received from the swap\n    function swapInWithCallback(\n        bool swap0to1_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) public payable returns (uint256 amountOut_) {\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, true));\n    }\n\n    /// @dev Swap tokens with perfect amount out\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOut(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Swap tokens with perfect amount out and callback functionality\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\n    /// @param amountOut_ The exact amount of tokens to receive after swap\n    /// @param amountInMax_ Maximum amount of tokens to swap in\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\n    /// @return amountIn_ The amount of input tokens used for the swap\n    function swapOutWithCallback(\n        bool swap0to1_,\n        uint256 amountOut_,\n        uint256 amountInMax_,\n        address to_\n    ) public payable returns (uint256 amountIn_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\n    /// @param shares_ The number of shares to mint\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\n    /// @return token0Amt_ Amount of token0 deposited\n    /// @return token1Amt_ Amount of token1 deposited\n    function depositPerfect(\n        uint shares_,\n        uint maxToken0Deposit_,\n        uint maxToken1Deposit_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\n    /// @param shares_ The number of shares to withdraw\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ The amount of token0 withdrawn\n    /// @return token1Amt_ The amount of token1 withdrawn\n    function withdrawPerfect(\n        uint shares_,\n        uint minToken0Withdraw_,\n        uint minToken1Withdraw_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to borrow\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\n    /// @return token0Amt_ Amount of token0 borrowed\n    /// @return token1Amt_ Amount of token1 borrowed\n    function borrowPerfect(\n        uint shares_,\n        uint minToken0Borrow_,\n        uint minToken1Borrow_,\n        address to_\n    ) public returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\n    /// @param shares_ The number of shares to pay back\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\n    /// @return token0Amt_ Amount of token0 paid back\n    /// @return token1Amt_ Amount of token1 paid back\n    function paybackPerfect(\n        uint shares_,\n        uint maxToken0Payback_,\n        uint maxToken1Payback_,\n        bool estimate_\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\n    }\n\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\n    /// @param token0Amt_ The amount of token0 to deposit\n    /// @param token1Amt_ The amount of token1 to deposit\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\n    /// @return shares_ The amount of shares minted for the deposit\n    function deposit(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\n    /// @param token0Amt_ The amount of token0 to withdraw\n    /// @param token1Amt_ The amount of token1 to withdraw\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The number of shares burned for the withdrawal\n    function withdraw(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\n    /// @param token0Amt_ The amount of token0 to borrow\n    /// @param token1Amt_ The amount of token1 to borrow\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\n    function borrow(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint maxSharesAmt_,\n        address to_\n    ) public returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\n    /// @param token0Amt_ The amount of token0 to payback\n    /// @param token1Amt_ The amount of token1 to payback\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\n    /// @return shares_ The amount of borrow shares burned for the payback\n    function payback(\n        uint token0Amt_,\n        uint token1Amt_,\n        uint minSharesAmt_,\n        bool estimate_\n    ) public payable returns (uint shares_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\n    /// @param shares_ The number of shares to burn for withdrawal\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\n    function withdrawPerfectInOneToken(\n        uint shares_,\n        uint minToken0_,\n        uint minToken1_,\n        address to_\n    ) public returns (uint withdrawAmt_) {\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev This function allows users to payback their debt with perfect shares in one token\n    /// @param shares_ The number of shares to burn for payback\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\n    function paybackPerfectInOneToken(\n        uint shares_,\n        uint maxToken0_,\n        uint maxToken1_,\n        bool estimate_\n    ) public payable returns (uint paybackAmt_) {\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\n    }\n\n    /// @dev liquidity callback for cheaper token transfers in case of deposit or payback.\n    /// only callable by Liquidity during an operation.\n    function liquidityCallback(address token_, uint amount_, bytes calldata data_) external {\n        if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity);\n        if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn);\n        if (data_.length != 96) revert FluidDexError(ErrorTypes.DexT1__IncorrectDataLength);\n\n        (uint amountToSend_, bool isCallback_, address from_) = abi.decode(data_, (uint, bool, address));\n\n        if (amountToSend_ < amount_) revert FluidDexError(ErrorTypes.DexT1__AmountToSendLessThanAmount);\n\n        if (isCallback_) {\n            IDexCallback(from_).dexCallback(token_, amountToSend_);\n        } else {\n            SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountToSend_);\n        }\n    }\n\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\n    /// but the difference due to interest will be super low so this difference is ignored\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\n    /// @return currentPrice_ price of pool after the most recent swap\n    function oraclePrice(\n        uint[] memory secondsAgos_\n    ) external view returns (Oracle[] memory twaps_, uint currentPrice_) {\n        OraclePriceMemory memory o_;\n\n        uint dexVariables_ = dexVariables;\n\n        if ((dexVariables_ >> 195) & 1 == 0) {\n            revert FluidDexError(ErrorTypes.DexT1__OracleNotActive);\n        }\n\n        twaps_ = new Oracle[](secondsAgos_.length);\n\n        uint totalTime_;\n        uint time_;\n\n        uint i;\n        uint secondsAgo_ = secondsAgos_[0];\n\n        currentPrice_ = (dexVariables_ >> 41) & X40;\n        currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);\n        uint price_ = currentPrice_;\n        o_.lowestPrice1by0 = currentPrice_;\n        o_.highestPrice1by0 = currentPrice_;\n\n        uint twap1by0_;\n        uint twap0by1_;\n\n        uint j;\n\n        o_.oracleSlot = (dexVariables_ >> 176) & X3;\n        o_.oracleMap = (dexVariables_ >> 179) & X16;\n        // if o_.oracleSlot == 7 then it'll enter the if statement in the below while loop\n        o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;\n\n        uint slotData_;\n        uint percentDiff_;\n\n        if (((dexVariables_ >> 121) & X33) < block.timestamp) {\n            // last swap didn't occured in this block.\n            // hence last price is current price of pool & also the last price\n            time_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        } else {\n            // last swap occured in this block, that means current price is active for 0 secs. Hence TWAP for it will be 0.\n            ++j;\n        }\n\n        while (true) {\n            if (j == 2) {\n                if (++o_.oracleSlot == 8) {\n                    o_.oracleSlot = 0;\n                    if (o_.oracleMap == 0) {\n                        o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                    }\n                    o_.oracle = _oracle[--o_.oracleMap];\n                }\n\n                slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                if (slotData_ > 0) {\n                    time_ = slotData_ & X9;\n                    if (time_ == 0) {\n                        // time is in precision & sign bits\n                        time_ = slotData_ >> 9;\n                        // if o_.oracleSlot is 7 then precision & bits and stored in 1 less map\n                        if (o_.oracleSlot == 7) {\n                            o_.oracleSlot = 0;\n                            if (o_.oracleMap == 0) {\n                                o_.oracleMap = TOTAL_ORACLE_MAPPING;\n                            }\n                            o_.oracle = _oracle[--o_.oracleMap];\n                            slotData_ = o_.oracle & X32;\n                        } else {\n                            ++o_.oracleSlot;\n                            slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\n                        }\n                    }\n                    percentDiff_ = slotData_ >> 10;\n                    percentDiff_ = (ORACLE_LIMIT * percentDiff_) / X22;\n                    if (((slotData_ >> 9) & 1 == 1)) {\n                        // if positive then old price was lower than current hence subtracting\n                        price_ = price_ - (price_ * percentDiff_) / ORACLE_PRECISION;\n                    } else {\n                        // if negative then old price was higher than current hence adding\n                        price_ = price_ + (price_ * percentDiff_) / ORACLE_PRECISION;\n                    }\n                } else {\n                    // oracle data does not exist. Probably due to pool recently got initialized and not have much swaps.\n                    revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);\n                }\n            } else if (j == 1) {\n                // last & last to last price\n                price_ = (dexVariables_ >> 1) & X40;\n                price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);\n                time_ = (dexVariables_ >> 154) & X22;\n                ++j;\n            } else if (j == 0) {\n                ++j;\n            }\n\n            totalTime_ += time_;\n            if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;\n            if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;\n            if (totalTime_ < secondsAgo_) {\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n            } else {\n                time_ = time_ + secondsAgo_ - totalTime_;\n                twap1by0_ += price_ * time_;\n                twap0by1_ += (1e54 / price_) * time_;\n                // also auto checks that secondsAgos_ should not be == 0\n                twap1by0_ = twap1by0_ / secondsAgo_;\n                twap0by1_ = twap0by1_ / secondsAgo_;\n\n                twaps_[i] = Oracle(\n                    twap1by0_,\n                    o_.lowestPrice1by0,\n                    o_.highestPrice1by0,\n                    twap0by1_,\n                    (1e54 / o_.highestPrice1by0),\n                    (1e54 / o_.lowestPrice1by0)\n                );\n\n                // TWAP for next secondsAgo will start with price_\n                o_.lowestPrice1by0 = price_;\n                o_.highestPrice1by0 = price_;\n\n                while (++i < secondsAgos_.length) {\n                    // secondsAgo_ = [60, 15, 0]\n                    time_ = totalTime_ - secondsAgo_;\n                    // updating total time as new seconds ago started\n                    totalTime_ = time_;\n                    // also auto checks that secondsAgos_[i + 1] > secondsAgos_[i]\n                    secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];\n                    if (totalTime_ < secondsAgo_) {\n                        twap1by0_ = price_ * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        // if time_ comes out as 0 here then lowestPrice & highestPrice should not be price_, it should be next price_ that we will calculate\n                        if (time_ == 0) {\n                            o_.lowestPrice1by0 = type(uint).max;\n                            o_.highestPrice1by0 = 0;\n                        }\n                        break;\n                    } else {\n                        time_ = time_ + secondsAgo_ - totalTime_;\n                        // twap1by0_ = price_ here\n                        twap1by0_ = price_ * time_;\n                        // twap0by1_ = (1e54 / price_) * time_;\n                        twap0by1_ = (1e54 / price_) * time_;\n                        twap1by0_ = twap1by0_ / secondsAgo_;\n                        twap0by1_ = twap0by1_ / secondsAgo_;\n                        twaps_[i] = Oracle(\n                            twap1by0_,\n                            o_.lowestPrice1by0,\n                            o_.highestPrice1by0,\n                            twap0by1_,\n                            (1e54 / o_.highestPrice1by0),\n                            (1e54 / o_.lowestPrice1by0)\n                        );\n                    }\n                }\n                if (i == secondsAgos_.length) return (twaps_, currentPrice_); // oracle fetch over\n            }\n        }\n    }\n\n    function getPricesAndExchangePrices() public {\n        uint dexVariables_ = dexVariables;\n        uint dexVariables2_ = dexVariables2;\n\n        _check(dexVariables_, dexVariables2_);\n\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables, dexVariables2);\n\n        revert FluidDexPricesAndExchangeRates(pex_);\n    }\n\n    /// @dev Internal fallback function to handle calls to non-existent functions\n    /// @notice This function is called when a transaction is sent to the contract without matching any other function\n    /// @notice It checks if the caller is authorized, enables re-entrancy protection, delegates the call to the admin implementation, and then disables re-entrancy protection\n    /// @notice Only authorized callers (global or dex auth) can trigger this function\n    /// @notice This function uses assembly to perform a delegatecall to the admin implementation to update configs related to DEX\n    function _fallback() private {\n        if (!(DEX_FACTORY.isGlobalAuth(msg.sender) || DEX_FACTORY.isDexAuth(address(this), msg.sender))) {\n            revert FluidDexError(ErrorTypes.DexT1__NotAnAuth);\n        }\n\n        uint dexVariables_ = dexVariables;\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n\n        // Delegate the current call to `ADMIN_IMPLEMENTATION`.\n        _spell(ADMIN_IMPLEMENTATION, msg.data);\n\n        // disabling re-entrancy\n        // directly fetching from storage so updates from Admin module will get auto covered\n        dexVariables = dexVariables & ~uint(1);\n    }\n\n    fallback() external payable {\n        _fallback();\n    }\n\n    receive() external payable {\n        if (msg.sig != 0x00000000) {\n            _fallback();\n        }\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView() external view returns (ConstantViews memory constantsView_) {\n        constantsView_.dexId = DEX_ID;\n        constantsView_.liquidity = address(LIQUIDITY);\n        constantsView_.factory = address(DEX_FACTORY);\n        constantsView_.token0 = TOKEN_0;\n        constantsView_.token1 = TOKEN_1;\n        constantsView_.implementations.shift = SHIFT_IMPLEMENTATION;\n        constantsView_.implementations.admin = ADMIN_IMPLEMENTATION;\n        constantsView_.implementations.colOperations = COL_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.debtOperations = DEBT_OPERATIONS_IMPLEMENTATION;\n        constantsView_.implementations.perfectOperationsAndSwapOut = PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n        constantsView_.deployerContract = DEPLOYER_CONTRACT;\n        constantsView_.supplyToken0Slot = SUPPLY_TOKEN_0_SLOT;\n        constantsView_.borrowToken0Slot = BORROW_TOKEN_0_SLOT;\n        constantsView_.supplyToken1Slot = SUPPLY_TOKEN_1_SLOT;\n        constantsView_.borrowToken1Slot = BORROW_TOKEN_1_SLOT;\n        constantsView_.exchangePriceToken0Slot = EXCHANGE_PRICE_TOKEN_0_SLOT;\n        constantsView_.exchangePriceToken1Slot = EXCHANGE_PRICE_TOKEN_1_SLOT;\n        constantsView_.oracleMapping = TOTAL_ORACLE_MAPPING;\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_) {\n        constantsView2_.token0NumeratorPrecision = TOKEN_0_NUMERATOR_PRECISION;\n        constantsView2_.token0DenominatorPrecision = TOKEN_0_DENOMINATOR_PRECISION;\n        constantsView2_.token1NumeratorPrecision = TOKEN_1_NUMERATOR_PRECISION;\n        constantsView2_.token1DenominatorPrecision = TOKEN_1_DENOMINATOR_PRECISION;\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) public view returns (CollateralReserves memory c_) {\n        return\n            _getCollateralReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0SupplyExchangePrice_,\n                token1SupplyExchangePrice_\n            );\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) public view returns (DebtReserves memory d_) {\n        return\n            _getDebtReserves(\n                geometricMean_,\n                upperRange_,\n                lowerRange_,\n                token0BorrowExchangePrice_,\n                token1BorrowExchangePrice_\n            );\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/interfaces.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface IHook {\n    /// @notice Hook function to check for liquidation opportunities before external swaps\n    /// @dev The primary use of this hook is to check if a particular pair vault has liquidation available.\n    ///      If liquidation is available, it gives priority to the liquidation process before allowing external swaps.\n    ///      In most cases, this hook will not be set.\n    /// @param id_ Identifier for the operation type: 1 for swap, 2 for internal arbitrage\n    /// @param swap0to1_ Direction of the swap: true if swapping token0 for token1, false otherwise\n    /// @param token0_ Address of the first token in the pair\n    /// @param token1_ Address of the second token in the pair\n    /// @param price_ The price ratio of token1 to token0, expressed with 27 decimal places\n    /// @return isOk_ Boolean indicating whether the operation should proceed\n    function dexPrice(\n        uint id_,\n        bool swap0to1_,\n        address token0_,\n        address token1_,\n        uint price_\n    ) external returns (bool isOk_);\n}\n\ninterface ICenterPrice {\n    /// @notice Retrieves the center price for the pool\n    /// @dev This function is marked as non-constant (potentially state-changing) to allow flexibility in price fetching mechanisms.\n    ///      While typically used as a read-only operation, this design permits write operations if needed for certain token pairs\n    ///      (e.g., fetching up-to-date exchange rates that may require state changes).\n    /// @return price The current price ratio of token1 to token0, expressed with 27 decimal places\n    function centerPrice() external returns (uint price);\n}\n"},"contracts/protocols/dex/poolT1/common/constantVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { StorageRead } from \"../../../../libraries/storageRead.sol\";\n\ninterface ITokenDecimals {\n    function decimals() external view returns (uint8);\n}\n\nabstract contract ConstantVariables is StorageRead {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    address internal constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;\n\n    address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n    uint256 internal constant NATIVE_TOKEN_DECIMALS = 18;\n    address internal constant ADDRESS_DEAD = 0x000000000000000000000000000000000000dEaD;\n    uint256 internal constant TOKENS_DECIMALS_PRECISION = 12;\n    uint256 internal constant TOKENS_DECIMALS = 1e12;\n\n    uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\n    uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\n\n    uint256 internal constant X2 = 0x3;\n    uint256 internal constant X3 = 0x7;\n    uint256 internal constant X5 = 0x1f;\n    uint256 internal constant X7 = 0x7f;\n    uint256 internal constant X8 = 0xff;\n    uint256 internal constant X9 = 0x1ff;\n    uint256 internal constant X10 = 0x3ff;\n    uint256 internal constant X11 = 0x7ff;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X17 = 0x1ffff;\n    uint256 internal constant X18 = 0x3ffff;\n    uint256 internal constant X20 = 0xfffff;\n    uint256 internal constant X22 = 0x3fffff;\n    uint256 internal constant X23 = 0x7fffff;\n    uint256 internal constant X24 = 0xffffff;\n    uint256 internal constant X28 = 0xfffffff;\n    uint256 internal constant X30 = 0x3fffffff;\n    uint256 internal constant X32 = 0xffffffff;\n    uint256 internal constant X33 = 0x1ffffffff;\n    uint256 internal constant X40 = 0xffffffffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n    uint256 internal constant X96 = 0xffffffffffffffffffffffff;\n    uint256 internal constant X128 = 0xffffffffffffffffffffffffffffffff;\n\n    uint256 internal constant TWO_DECIMALS = 1e2;\n    uint256 internal constant THREE_DECIMALS = 1e3;\n    uint256 internal constant FOUR_DECIMALS = 1e4;\n    uint256 internal constant FIVE_DECIMALS = 1e5;\n    uint256 internal constant SIX_DECIMALS = 1e6;\n    uint256 internal constant EIGHT_DECIMALS = 1e8;\n    uint256 internal constant NINE_DECIMALS = 1e9;\n\n    uint256 internal constant PRICE_PRECISION = 1e27;\n\n    uint256 internal constant ORACLE_PRECISION = 1e18; // 100%\n    uint256 internal constant ORACLE_LIMIT = 5 * 1e16; // 5%\n\n    /// after swap token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_SWAP\n    /// after swap token1 reserves should not be less than token0InToken1 / MINIMUM_LIQUIDITY_SWAP\n    uint256 internal constant MINIMUM_LIQUIDITY_SWAP = 1e4;\n\n    /// after user operations (deposit, withdraw, borrow, payback) token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    /// after user operations (deposit, withdraw, borrow, payback) token1 reserves should not be less than token0InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\n    uint256 internal constant MINIMUM_LIQUIDITY_USER_OPERATIONS = 1e6;\n\n    /// To skip transfers in liquidity layer if token in & out is same and liquidity layer is on the winning side\n    bytes32 internal constant SKIP_TRANSFERS = keccak256(bytes(\"SKIP_TRANSFERS\"));\n\n    function _decimals(address token_) internal view returns (uint256) {\n        return (token_ == NATIVE_TOKEN) ? NATIVE_TOKEN_DECIMALS : ITokenDecimals(token_).decimals();\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../../../liquidity/interfaces/iLiquidity.sol\";\nimport { Structs } from \"./structs.sol\";\nimport { ConstantVariables } from \"../common/constantVariables.sol\";\nimport { IFluidDexFactory } from \"../../interfaces/iDexFactory.sol\";\nimport { Error } from \"../../error.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\n\nabstract contract ImmutableVariables is ConstantVariables, Structs, Error {\n    /*//////////////////////////////////////////////////////////////\n                          CONSTANTS / IMMUTABLES\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public immutable DEX_ID;\n\n    /// @dev Address of token 0\n    address internal immutable TOKEN_0;\n\n    /// @dev Address of token 1\n    address internal immutable TOKEN_1;\n\n    address internal immutable THIS_CONTRACT;\n\n    uint256 internal immutable TOKEN_0_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_0_DENOMINATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_NUMERATOR_PRECISION;\n    uint256 internal immutable TOKEN_1_DENOMINATOR_PRECISION;\n\n    /// @dev Address of liquidity contract\n    IFluidLiquidity internal immutable LIQUIDITY;\n\n    /// @dev Address of DEX factory contract\n    IFluidDexFactory internal immutable DEX_FACTORY;\n\n    /// @dev Address of Shift implementation\n    address internal immutable SHIFT_IMPLEMENTATION;\n\n    /// @dev Address of Admin implementation\n    address internal immutable ADMIN_IMPLEMENTATION;\n\n    /// @dev Address of Col Operations implementation\n    address internal immutable COL_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Debt Operations implementation\n    address internal immutable DEBT_OPERATIONS_IMPLEMENTATION;\n\n    /// @dev Address of Perfect Operations and Swap Out implementation\n    address internal immutable PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\n\n    /// @dev Address of contract used for deploying center price & hook related contract\n    address internal immutable DEPLOYER_CONTRACT;\n\n    /// @dev Liquidity layer slots\n    bytes32 internal immutable SUPPLY_TOKEN_0_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_0_SLOT;\n    bytes32 internal immutable SUPPLY_TOKEN_1_SLOT;\n    bytes32 internal immutable BORROW_TOKEN_1_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_0_SLOT;\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_1_SLOT;\n    uint256 internal immutable TOTAL_ORACLE_MAPPING;\n\n    function _calcNumeratorAndDenominator(\n        address token_\n    ) private view returns (uint256 numerator_, uint256 denominator_) {\n        uint256 decimals_ = _decimals(token_);\n        if (decimals_ > TOKENS_DECIMALS_PRECISION) {\n            numerator_ = 1;\n            denominator_ = 10 ** (decimals_ - TOKENS_DECIMALS_PRECISION);\n        } else {\n            numerator_ = 10 ** (TOKENS_DECIMALS_PRECISION - decimals_);\n            denominator_ = 1;\n        }\n    }\n\n    constructor(ConstantViews memory constants_) {\n        THIS_CONTRACT = address(this);\n\n        DEX_ID = constants_.dexId;\n        LIQUIDITY = IFluidLiquidity(constants_.liquidity);\n        DEX_FACTORY = IFluidDexFactory(constants_.factory);\n\n        TOKEN_0 = constants_.token0;\n        TOKEN_1 = constants_.token1;\n\n        if (TOKEN_0 >= TOKEN_1) revert FluidDexError(ErrorTypes.DexT1__Token0ShouldBeSmallerThanToken1);\n\n        (TOKEN_0_NUMERATOR_PRECISION, TOKEN_0_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_0);\n        (TOKEN_1_NUMERATOR_PRECISION, TOKEN_1_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_1);\n\n        if (constants_.implementations.shift != address(0)) {\n            SHIFT_IMPLEMENTATION = constants_.implementations.shift;\n        } else {\n            SHIFT_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.admin != address(0)) {\n            ADMIN_IMPLEMENTATION = constants_.implementations.admin;\n        } else {\n            ADMIN_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.colOperations != address(0)) {\n            COL_OPERATIONS_IMPLEMENTATION = constants_.implementations.colOperations;\n        } else {\n            COL_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.debtOperations != address(0)) {\n            DEBT_OPERATIONS_IMPLEMENTATION = constants_.implementations.debtOperations;\n        } else {\n            DEBT_OPERATIONS_IMPLEMENTATION = address(this);\n        }\n        if (constants_.implementations.perfectOperationsAndSwapOut != address(0)) {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = constants_.implementations.perfectOperationsAndSwapOut;\n        } else {\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = address(this);\n        }\n\n        DEPLOYER_CONTRACT = constants_.deployerContract;\n\n        SUPPLY_TOKEN_0_SLOT = constants_.supplyToken0Slot;\n        BORROW_TOKEN_0_SLOT = constants_.borrowToken0Slot;\n        SUPPLY_TOKEN_1_SLOT = constants_.supplyToken1Slot;\n        BORROW_TOKEN_1_SLOT = constants_.borrowToken1Slot;\n        EXCHANGE_PRICE_TOKEN_0_SLOT = constants_.exchangePriceToken0Slot;\n        EXCHANGE_PRICE_TOKEN_1_SLOT = constants_.exchangePriceToken1Slot;\n\n        if (constants_.oracleMapping > X16) revert FluidDexError(ErrorTypes.DexT1__OracleMappingOverflow);\n\n        TOTAL_ORACLE_MAPPING = constants_.oracleMapping;\n    }\n}\n"},"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol":{"content":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FixedPointMathLib } from \"solmate/src/utils/FixedPointMathLib.sol\";\n\nimport { Variables } from \"../../common/variables.sol\";\nimport { ImmutableVariables } from \"../immutableVariables.sol\";\nimport { Events } from \"../events.sol\";\nimport { ErrorTypes } from \"../../../errorTypes.sol\";\nimport { IHook, ICenterPrice } from \"../interfaces.sol\";\nimport { LiquiditySlotsLink } from \"../../../../../libraries/liquiditySlotsLink.sol\";\nimport { LiquidityCalcs } from \"../../../../../libraries/liquidityCalcs.sol\";\nimport { DexSlotsLink } from \"../../../../../libraries/dexSlotsLink.sol\";\nimport { DexCalcs } from \"../../../../../libraries/dexCalcs.sol\";\nimport { BigMathMinified } from \"../../../../../libraries/bigMathMinified.sol\";\nimport { AddressCalcs } from \"../../../../../libraries/addressCalcs.sol\";\n\ninterface IShifting {\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper threshold, lower threshold, and dexVariables2\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint dexVariables2_\n    ) external payable returns (uint, uint, uint);\n\n    /// @dev Calculates the new center price during an active center price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return The updated center price\n    function _calcCenterPrice(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) external payable returns (uint);\n}\n\nabstract contract CoreHelpers is Variables, ImmutableVariables, Events {\n    using BigMathMinified for uint256;\n\n    /// @dev            do any arbitrary call\n    /// @param target_  Address to which the call needs to be delegated\n    /// @param data_    Data to execute at the delegated address\n    function _spell(address target_, bytes memory data_) internal returns (bytes memory response_) {\n        assembly {\n            let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)\n            let size := returndatasize()\n\n            response_ := mload(0x40)\n            mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n            mstore(response_, size)\n            returndatacopy(add(response_, 0x20), 0, size)\n\n            if iszero(succeeded) {\n                // throw if delegatecall failed\n                returndatacopy(0x00, 0x00, size)\n                revert(0x00, size)\n            }\n        }\n    }\n\n    /// @dev Given an input amount of asset and pair reserves, returns the maximum output amount of the other asset\n    /// @param amountIn_ The amount of input asset.\n    /// @param iReserveIn_ Imaginary token reserve with input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountOut(\n        uint256 amountIn_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountOut_) {\n        unchecked {\n            // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n            uint256 numerator_ = amountIn_ * iReserveOut_;\n            uint256 denominator_ = iReserveIn_ + amountIn_;\n\n            // Using the swap formula: (AmountIn * iReserveY) / (iReserveX + AmountIn)\n            amountOut_ = numerator_ / denominator_;\n        }\n    }\n\n    /// @dev Given an output amount of asset and pair reserves, returns the input amount of the other asset\n    /// @param amountOut_ Desired output amount of the asset.\n    /// @param iReserveIn_ Imaginary token reserve of input amount.\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\n    function _getAmountIn(\n        uint256 amountOut_,\n        uint iReserveIn_,\n        uint iReserveOut_\n    ) internal pure returns (uint256 amountIn_) {\n        // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\n        uint256 numerator_ = amountOut_ * iReserveIn_;\n        uint256 denominator_ = iReserveOut_ - amountOut_;\n\n        // Using the swap formula: (AmountOut * iReserveX) / (iReserveY - AmountOut)\n        amountIn_ = numerator_ / denominator_;\n    }\n\n    /// @param t total amount in\n    /// @param x imaginary reserves of token out of collateral\n    /// @param y imaginary reserves of token in of collateral\n    /// @param x2 imaginary reserves of token out of debt\n    /// @param y2 imaginary reserves of token in of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingIn(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. out = x * a / (y + a)\n        // 2. out2 = x2 * (t - a) / (y2 + (t - a))\n        // final price should be same\n        // 3. (y + a) / (x - out) = (y2 + (t - a)) / (x2 - out2)\n        // derivation: https://chatgpt.com/share/dce6f381-ee5f-4d5f-b6ea-5996e84d5b57\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    /// @param t total amount out\n    /// @param x imaginary reserves of token in of collateral\n    /// @param y imaginary reserves of token out of collateral\n    /// @param x2 imaginary reserves of token in of debt\n    /// @param y2 imaginary reserves of token out of debt\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\n    /// note if a > 0 & a < t then swap will route through both pools\n    function _swapRoutingOut(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\n        // Main equations:\n        // 1. in = (x * a) / (y - a)\n        // 2. in2 = (x2 * (t - a)) / (y2 - (t - a))\n        // final price should be same\n        // 3. (y - a) / (x + in) = (y2 - (t - a)) / (x2 + in2)\n        // derivation: https://chatgpt.com/share/6585bc28-841f-49ec-aea2-1e5c5b7f4fa9\n\n        // adding 1e18 precision\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\n\n        // 1e18 precision gets cancelled out in division\n        a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_);\n    }\n\n    function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view {\n        if (utilizationLimit_ < THREE_DECIMALS) {\n            utilizationLimit_ = utilizationLimit_ * 10;\n            // extracting utilization of token from liquidity layer\n            uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);\n            liquidityLayerUtilization_ =\n                (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) &\n                X14;\n            // Note: this can go slightly above the utilization limit if no update is written to storage at liquidity layer\n            // if swap was not big enough to go far enough above or any other storage update threshold write cause there\n            // so just to keep in mind when configuring the actual limit reachable can be utilizationLimit_ + storageUpdateThreshold at Liquidity\n            if (liquidityLayerUtilization_ > utilizationLimit_)\n                revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);\n        }\n    }\n\n    function _check(uint dexVariables_, uint dexVariables2_) internal {\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\n        if (dexVariables2_ & 3 == 0) revert FluidDexError(ErrorTypes.DexT1__PoolNotInitialized);\n        // enabling re-entrancy\n        dexVariables = dexVariables_ | 1;\n    }\n\n    /// @dev if token0 reserves are too low w.r.t token1 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken0Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token0Reserves_) < ((token1Reserves_ * 1e27) / (centerPrice_ * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    /// @dev if token1 reserves are too low w.r.t token0 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\n    function _verifyToken1Reserves(\n        uint token0Reserves_,\n        uint token1Reserves_,\n        uint centerPrice_,\n        uint minLiquidity_\n    ) internal pure {\n        if (((token1Reserves_) < ((token0Reserves_ * centerPrice_) / (1e27 * minLiquidity_)))) {\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\n        }\n    }\n\n    function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure {\n        // after shifting amount should not become 0\n        // limiting to six decimals which means in case of USDC, USDT it's 1 wei, for WBTC 100 wei, for ETH 1000 gwei\n        if (amountAdjusted_ < SIX_DECIMALS || amountAdjusted_ > X96 || amount_ < TWO_DECIMALS || amount_ > X128)\n            revert FluidDexError(ErrorTypes.DexT1__LimitingAmountsSwapAndNonPerfectActions);\n    }\n\n    /// @dev Calculates the new upper and lower range values during an active range shift\n    /// @param upperRange_ The target upper range value\n    /// @param lowerRange_ The target lower range value\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\n    /// @return The updated upper range, lower range, and dexVariables2\n    /// @notice This function handles the gradual shifting of range values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcRangeShifting(\n        uint upperRange_,\n        uint lowerRange_,\n        uint dexVariables2_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcRangeShifting.selector,\n                        upperRange_,\n                        lowerRange_,\n                        dexVariables2_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new upper and lower threshold values during an active threshold shift\n    /// @param upperThreshold_ The target upper threshold value\n    /// @param lowerThreshold_ The target lower threshold value\n    /// @param thresholdTime_ The time passed since shifting started\n    /// @return The updated upper threshold, lower threshold, and threshold time\n    /// @notice This function handles the gradual shifting of threshold values over time\n    /// @notice If the shift is complete, it updates the state and clears the shift data\n    function _calcThresholdShifting(\n        uint upperThreshold_,\n        uint lowerThreshold_,\n        uint thresholdTime_\n    ) internal returns (uint, uint, uint) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(\n                        IShifting._calcThresholdShifting.selector,\n                        upperThreshold_,\n                        lowerThreshold_,\n                        thresholdTime_\n                    )\n                ),\n                (uint, uint, uint)\n            );\n    }\n\n    /// @dev Calculates the new center price during an active price shift\n    /// @param dexVariables_ The current state of dex variables\n    /// @param dexVariables2_ Additional dex variables\n    /// @return newCenterPrice_ The updated center price\n    /// @notice This function gradually shifts the center price towards a new target price over time\n    /// @notice It uses an external price source (via ICenterPrice) to determine the target price\n    /// @notice The shift continues until the current price reaches the target, or the shift duration ends\n    /// @notice Once the shift is complete, it updates the state and clears the shift data\n    /// @notice The shift rate is dynamic and depends on:\n    /// @notice - Time remaining in the shift duration\n    /// @notice - The new center price (fetched externally, which may change)\n    /// @notice - The current (old) center price\n    /// @notice This results in a fuzzy shifting mechanism where the rate can change as these parameters evolve\n    /// @notice The externally fetched new center price is expected to not differ significantly from the last externally fetched center price\n    function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) {\n        return\n            abi.decode(\n                _spell(\n                    SHIFT_IMPLEMENTATION,\n                    abi.encodeWithSelector(IShifting._calcCenterPrice.selector, dexVariables_, dexVariables2_)\n                ),\n                (uint)\n            );\n    }\n\n    /// @notice Calculates and returns the current prices and exchange prices for the pool\n    /// @param dexVariables_ The first set of DEX variables containing various pool parameters\n    /// @param dexVariables2_ The second set of DEX variables containing additional pool parameters\n    /// @return pex_ A struct containing the calculated prices and exchange prices:\n    ///         - pex_.lastStoredPrice: The last stored price in 1e27 decimals\n    ///         - pex_.centerPrice: The calculated or fetched center price in 1e27 decimals\n    ///         - pex_.upperRange: The upper range price limit in 1e27 decimals\n    ///         - pex_.lowerRange: The lower range price limit in 1e27 decimals\n    ///         - pex_.geometricMean: The geometric mean of upper range & lower range in 1e27 decimals\n    ///         - pex_.supplyToken0ExchangePrice: The current exchange price for supplying token0\n    ///         - pex_.borrowToken0ExchangePrice: The current exchange price for borrowing token0\n    ///         - pex_.supplyToken1ExchangePrice: The current exchange price for supplying token1\n    ///         - pex_.borrowToken1ExchangePrice: The current exchange price for borrowing token1\n    /// @dev This function performs the following operations:\n    ///      1. Determines the center price (either from storage, external source, or calculated)\n    ///      2. Retrieves the last stored price from dexVariables_\n    ///      3. Calculates the upper and lower range prices based on the center price and range percentages\n    ///      4. Checks if rebalancing is needed based on threshold settings\n    ///      5. Adjusts prices if necessary based on the time elapsed and threshold conditions\n    ///      6. Update the dexVariables2_ if changes were made\n    ///      7. Returns the calculated prices and exchange prices in the PricesAndExchangePrice struct\n    function _getPricesAndExchangePrices(\n        uint dexVariables_,\n        uint dexVariables2_\n    ) internal returns (PricesAndExchangePrice memory pex_) {\n        uint centerPrice_;\n\n        if (((dexVariables2_ >> 248) & 1) == 0) {\n            // centerPrice_ => center price hook\n            centerPrice_ = (dexVariables2_ >> 112) & X30;\n            if (centerPrice_ == 0) {\n                centerPrice_ = (dexVariables_ >> 81) & X40;\n                centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);\n            } else {\n                // center price should be fetched from external source. For exmaple, in case of wstETH <> ETH pool,\n                // we would want the center price to be pegged to wstETH exchange rate into ETH\n                centerPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, centerPrice_)).centerPrice();\n            }\n        } else {\n            // an active centerPrice_ shift is going on\n            centerPrice_ = _calcCenterPrice(dexVariables_, dexVariables2_);\n        }\n\n        uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;\n        lastStoredPrice_ = (lastStoredPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastStoredPrice_ & DEFAULT_EXPONENT_MASK);\n\n        uint upperRange_ = ((dexVariables2_ >> 27) & X20);\n        uint lowerRange_ = ((dexVariables2_ >> 47) & X20);\n        if (((dexVariables2_ >> 26) & 1) == 1) {\n            // an active range shift is going on\n            (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);\n        }\n\n        unchecked {\n            // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n            // 1% = 1e4, 100% = 1e6\n            upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n            // 1% = 1e4, 100% = 1e6\n            lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n        }\n\n        bool changed_;\n        {\n            // goal will be to keep threshold percents 0 if center price is fetched from external source\n            // checking if threshold are set non 0 then only rebalancing is on\n            if (((dexVariables2_ >> 68) & X20) > 0) {\n                uint upperThreshold_ = (dexVariables2_ >> 68) & X10;\n                uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;\n                uint shiftingTime_ = (dexVariables2_ >> 88) & X24;\n                if (((dexVariables2_ >> 67) & 1) == 1) {\n                    // if active shift is going on for threshold then calculate threshold real time\n                    (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(\n                        upperThreshold_,\n                        lowerThreshold_,\n                        shiftingTime_\n                    );\n                }\n\n                unchecked {\n                    if (\n                        lastStoredPrice_ >\n                        (centerPrice_ +\n                            ((upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards upper range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = upperRange_;\n                        }\n                        changed_ = true;\n                    } else if (\n                        lastStoredPrice_ <\n                        (centerPrice_ -\n                            ((centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_)) /\n                            THREE_DECIMALS)\n                    ) {\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n                        // price shifting towards lower range\n                        if (timeElapsed_ < shiftingTime_) {\n                            centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_;\n                        } else {\n                            // 100% price shifted\n                            centerPrice_ = lowerRange_;\n                        }\n                        changed_ = true;\n                    }\n                }\n            }\n        }\n\n        // temp_ => max center price\n        uint temp_ = (dexVariables2_ >> 172) & X28;\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n        if (centerPrice_ > temp_) {\n            // if center price is greater than max center price\n            centerPrice_ = temp_;\n            changed_ = true;\n        } else {\n            // check if center price is less than min center price\n            // temp_ => min center price\n            temp_ = (dexVariables2_ >> 200) & X28;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n            if (centerPrice_ < temp_) {\n                centerPrice_ = temp_;\n                changed_ = true;\n            }\n        }\n\n        // if centerPrice_ is changed then calculating upper and lower range again\n        if (changed_) {\n            upperRange_ = ((dexVariables2_ >> 27) & X20);\n            lowerRange_ = ((dexVariables2_ >> 47) & X20);\n            if (((dexVariables2_ >> 26) & 1) == 1) {\n                (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(\n                    upperRange_,\n                    lowerRange_,\n                    dexVariables2_\n                );\n            }\n\n            unchecked {\n                // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\n                // 1% = 1e4, 100% = 1e6\n                upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\n                // 1% = 1e4, 100% = 1e6\n                lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\n            }\n        }\n\n        pex_.lastStoredPrice = lastStoredPrice_;\n        pex_.centerPrice = centerPrice_;\n        pex_.upperRange = upperRange_;\n        pex_.lowerRange = lowerRange_;\n\n        unchecked {\n            if (upperRange_ < 1e38) {\n                // 1e38 * 1e38 = 1e76 which is less than max uint limit\n                pex_.geometricMean = FixedPointMathLib.sqrt(upperRange_ * lowerRange_);\n            } else {\n                // upperRange_ price is pretty large hence lowerRange_ will also be pretty large\n                pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18;\n            }\n        }\n\n        // Exchange price will remain same as Liquidity Layer\n        (pex_.supplyToken0ExchangePrice, pex_.borrowToken0ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_0_SLOT)\n        );\n\n        (pex_.supplyToken1ExchangePrice, pex_.borrowToken1ExchangePrice) = LiquidityCalcs.calcExchangePrices(\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_1_SLOT)\n        );\n    }\n\n    /// @dev getting reserves outside range.\n    /// @param gp_ is geometric mean pricing of upper percent & lower percent\n    /// @param pa_ price of upper range or lower range\n    /// @param rx_ real reserves of token0 or token1\n    /// @param ry_ whatever is rx_ the other will be ry_\n    function _calculateReservesOutsideRange(\n        uint gp_,\n        uint pa_,\n        uint rx_,\n        uint ry_\n    ) internal pure returns (uint xa_, uint yb_) {\n        // equations we have:\n        // 1. x*y = k\n        // 2. xa*ya = k\n        // 3. xb*yb = k\n        // 4. Pa = ya / xa = upperRange_ (known)\n        // 5. Pb = yb / xb = lowerRange_ (known)\n        // 6. x - xa = rx = real reserve of x (known)\n        // 7. y - yb = ry = real reserve of y (known)\n        // With solving we get:\n        // ((Pa*Pb)^(1/2) - Pa)*xa^2 + (rx * (Pa*Pb)^(1/2) + ry)*xa + rx*ry = 0\n        // yb = yb = xa * (Pa * Pb)^(1/2)\n\n        // xa = (GP⋅rx + ry + (-rx⋅ry⋅4⋅(GP - Pa) + (GP⋅rx + ry)^2)^0.5) / (2Pa - 2GP)\n        // multiply entire equation by 1e27 to remove the price decimals precision of 1e27\n        // xa = (GP⋅rx + ry⋅1e27 + (rx⋅ry⋅4⋅(Pa - GP)⋅1e27 + (GP⋅rx + ry⋅1e27)^2)^0.5) / 2*(Pa - GP)\n        // dividing the equation with 2*(Pa - GP). Pa is always > GP so answer will be positive.\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅4⋅(Pa - GP)⋅1e27) / 4*(Pa - GP)^2) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅1e27) / (Pa - GP)) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\n\n        // dividing in 3 parts for simplification:\n        // part1 = (Pa - GP)\n        // part2 = (GP⋅rx + ry⋅1e27) / (2*part1)\n        // part3 = rx⋅ry\n        // note: part1 will almost always be < 1e28 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e29\n        uint p1_ = pa_ - gp_;\n        uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);\n        uint p3_ = rx_ * ry_;\n        // to avoid overflowing\n        p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27;\n\n        // xa = part2 + (part3 + (part2 * part2))^(1/2)\n        // yb = xa_ * gp_\n        xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));\n        yb_ = (xa_ * gp_) / 1e27;\n    }\n\n    /// @dev Retrieves collateral amount from liquidity layer for a given token\n    /// @param supplyTokenSlot_ The storage slot for the supply token data\n    /// @param tokenExchangePrice_ The exchange price of the token\n    /// @param isToken0_ Boolean indicating if the token is token0 (true) or token1 (false)\n    /// @return tokenSupply_ The calculated liquidity collateral amount\n    function _getLiquidityCollateral(\n        bytes32 supplyTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenSupply_) {\n        uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);\n        tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;\n        tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);\n\n        if (tokenSupplyData_ & 1 == 1) {\n            // supply with interest is on\n            unchecked {\n                tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenSupply_ = isToken0_\n                ? ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\n    ///      based on the geometric mean and price range\n    /// @param geometricMean_ The geometric mean of the token prices\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\n    ///         - token0RealReserves: The real reserves of token0\n    ///         - token1RealReserves: The real reserves of token1\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\n    function _getCollateralReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0SupplyExchangePrice_,\n        uint token1SupplyExchangePrice_\n    ) internal view returns (CollateralReserves memory c_) {\n        uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);\n        uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);\n\n        if (geometricMean_ < 1e27) {\n            (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(\n                geometricMean_,\n                upperRange_,\n                token0Supply_,\n                token1Supply_\n            );\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange(\n                (1e54 / geometricMean_),\n                (1e54 / lowerRange_),\n                token1Supply_,\n                token0Supply_\n            );\n        }\n\n        c_.token0RealReserves = token0Supply_;\n        c_.token1RealReserves = token1Supply_;\n        unchecked {\n            c_.token0ImaginaryReserves += token0Supply_;\n            c_.token1ImaginaryReserves += token1Supply_;\n        }\n    }\n\n    /// @notice Calculates the real and imaginary debt reserves for both tokens\n    /// @dev This function uses a quadratic equation to determine the debt reserves\n    ///      based on the geometric mean price and the current debt amounts\n    /// @param gp_ The geometric mean price of upper range & lower range\n    /// @param pb_ The price of lower range\n    /// @param dx_ The debt amount of one token\n    /// @param dy_ The debt amount of the other token\n    /// @return rx_ The real debt reserve of the first token\n    /// @return ry_ The real debt reserve of the second token\n    /// @return irx_ The imaginary debt reserve of the first token\n    /// @return iry_ The imaginary debt reserve of the second token\n    function _calculateDebtReserves(\n        uint gp_,\n        uint pb_,\n        uint dx_,\n        uint dy_\n    ) internal pure returns (uint rx_, uint ry_, uint irx_, uint iry_) {\n        // Assigning letter to knowns:\n        // c = debtA\n        // d = debtB\n        // e = upperPrice\n        // f = lowerPrice\n        // g = upperPrice^1/2\n        // h = lowerPrice^1/2\n\n        // c = 1\n        // d = 2000\n        // e = 2222.222222\n        // f = 1800\n        // g = 2222.222222^1/2\n        // h = 1800^1/2\n\n        // Assigning letter to unknowns:\n        // w = realDebtReserveA\n        // x = realDebtReserveB\n        // y = imaginaryDebtReserveA\n        // z = imaginaryDebtReserveB\n        // k = k\n\n        // below quadratic will give answer of realDebtReserveB\n        // A, B, C of quadratic equation:\n        // A = h\n        // B = dh - cfg\n        // C = -cfdh\n\n        // A = lowerPrice^1/2\n        // B = debtB⋅lowerPrice^1/2 - debtA⋅lowerPrice⋅upperPrice^1/2\n        // C = -(debtA⋅lowerPrice⋅debtB⋅lowerPrice^1/2)\n\n        // x = (cfg − dh + (4cdf(h^2)+(cfg−dh)^2))^(1/2)) / 2h\n        // simplifying dividing by h, note h = f^1/2\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((4⋅c⋅d⋅f⋅f) / (4h^2) + ((c⋅f⋅g) / 2h − (d⋅h) / 2h)^2))^(1/2))\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((c⋅d⋅f) + ((c⋅g⋅(f^1/2) − d) / 2)^2))^(1/2))\n\n        // dividing in 3 parts for simplification:\n        // part1 = (c⋅g⋅(f^1/2) − d) / 2\n        // part2 = (c⋅d⋅f)\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        // note: part1 will almost always be < 1e27 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e28\n\n        // part1 = ((debtA * upperPrice^1/2 * lowerPrice^1/2) - debtB) / 2\n        // note: upperPrice^1/2 * lowerPrice^1/2 = geometric mean\n        // part1 = ((debtA * geometricMean) - debtB) / 2\n        // part2 = debtA * debtB * lowerPrice\n\n        // converting decimals properly as price is in 1e27 decimals\n        // part1 = ((debtA * geometricMean) - (debtB * 1e27)) / (2 * 1e27)\n        // part2 = (debtA * debtB * lowerPrice) / 1e27\n        // final x equals:\n        // x = (part1 + (part2 + part1^2)^(1/2))\n        int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);\n        uint p2_ = (dx_ * dy_);\n        p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;\n        ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));\n\n        // finding z:\n        // x^2 - zx + cfz = 0\n        // z*(x - cf) = x^2\n        // z = x^2 / (x - cf)\n        // z = x^2 / (x - debtA * lowerPrice)\n        // converting decimals properly as price is in 1e27 decimals\n        // z = (x^2 * 1e27) / ((x * 1e27) - (debtA * lowerPrice))\n\n        iry_ = ((ry_ * 1e27) - (dx_ * pb_));\n        if (iry_ < SIX_DECIMALS) {\n            // almost impossible situation to ever get here\n            revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);\n        }\n        if (ry_ < 1e25) {\n            iry_ = (ry_ * ry_ * 1e27) / iry_;\n        } else {\n            // note: it can never result in negative as final result will always be in positive\n            iry_ = (ry_ * ry_) / (iry_ / 1e27);\n        }\n\n        // finding y\n        // x = z * c / (y + c)\n        // y + c = z * c / x\n        // y = (z * c / x) - c\n        // y = (z * debtA / x) - debtA\n        irx_ = ((iry_ * dx_) / ry_) - dx_;\n\n        // finding w\n        // w = y * d / (z + d)\n        // w = (y * debtB) / (z + debtB)\n        rx_ = (irx_ * dy_) / (iry_ + dy_);\n    }\n\n    /// @notice Calculates the debt amount for a given token from liquidity layer\n    /// @param borrowTokenSlot_ The storage slot for the token's borrow data\n    /// @param tokenExchangePrice_ The current exchange price of the token\n    /// @param isToken0_ Boolean indicating if this is for token0 (true) or token1 (false)\n    /// @return tokenDebt_ The calculated debt amount for the token\n    function _getLiquidityDebt(\n        bytes32 borrowTokenSlot_,\n        uint tokenExchangePrice_,\n        bool isToken0_\n    ) internal view returns (uint tokenDebt_) {\n        uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);\n\n        tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;\n        tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);\n\n        if (tokenBorrowData_ & 1 == 1) {\n            // borrow with interest is on\n            unchecked {\n                tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\n            }\n        }\n\n        unchecked {\n            tokenDebt_ = isToken0_\n                ? ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\n                : ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\n        }\n    }\n\n    /// @notice Calculates the debt reserves for both tokens\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\n    /// @param upperRange_ The upper price range\n    /// @param lowerRange_ The lower price range\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\n    /// @return d_ The calculated debt reserves for both tokens, containing:\n    ///         - token0Debt: The debt amount of token0\n    ///         - token1Debt: The debt amount of token1\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\n    function _getDebtReserves(\n        uint geometricMean_,\n        uint upperRange_,\n        uint lowerRange_,\n        uint token0BorrowExchangePrice_,\n        uint token1BorrowExchangePrice_\n    ) internal view returns (DebtReserves memory d_) {\n        uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);\n        uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);\n\n        d_.token0Debt = token0Debt_;\n        d_.token1Debt = token1Debt_;\n\n        if (geometricMean_ < 1e27) {\n            (\n                d_.token0RealReserves,\n                d_.token1RealReserves,\n                d_.token0ImaginaryReserves,\n                d_.token1ImaginaryReserves\n            ) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);\n        } else {\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\n            // 1 / geometricMean for new geometricMean\n            // 1 / lowerRange will become upper range\n            // 1 / upperRange will become lower range\n            (\n                d_.token1RealReserves,\n                d_.token0RealReserves,\n                d_.token1ImaginaryReserves,\n                d_.token0ImaginaryReserves\n            ) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_);\n        }\n    }\n\n    function _priceDiffCheck(uint oldPrice_, uint newPrice_) internal pure returns (int priceDiff_) {\n        // check newPrice_ & oldPrice_ difference should not be more than 5%\n        // old price w.r.t new price\n        priceDiff_ = int(ORACLE_PRECISION) - int((oldPrice_ * ORACLE_PRECISION) / newPrice_);\n\n        unchecked {\n            if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {\n                // if oracle price difference is more than 5% then revert\n                // in 1 swap price should only change by <= 5%\n                // if a total fall by let's say 8% then in current block price can only fall by 5% and\n                // in next block it'll fall the remaining 3%\n                revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);\n            }\n        }\n    }\n\n    function _updateOracle(uint newPrice_, uint centerPrice_, uint dexVariables_) internal returns (uint) {\n        // time difference between last & current swap\n        uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);\n        uint temp_;\n        uint temp2_;\n        uint temp3_;\n\n        if (timeDiff_ == 0) {\n            // doesn't matter if oracle is on or off when timediff = 0 code for both is same\n\n            // temp_ => oldCenterPrice\n            temp_ = (dexVariables_ >> 81) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // Ensure that the center price is within the acceptable range of the old center price if it's not the first swap in the same block\n            unchecked {\n                if (\n                    (centerPrice_ < (((EIGHT_DECIMALS - 1) * temp_) / EIGHT_DECIMALS)) ||\n                    (centerPrice_ > (((EIGHT_DECIMALS + 1) * temp_) / EIGHT_DECIMALS))\n                ) {\n                    revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);\n                }\n            }\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n\n            // 2nd swap in same block no need to update anything around oracle, only need to update last swap price in dexVariables\n            return ((dexVariables_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41));\n        }\n\n        if (((dexVariables_ >> 195) & 1) == 0) {\n            // if oracle is not active then just returning updated DEX variable\n            temp_ = ((dexVariables_ >> 41) & X40);\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            _priceDiffCheck(temp_, newPrice_);\n            \n            return ((dexVariables_ & 0xfffffffffffffffffffffffffc00000000000000000000000000000000000001) |\n                (((dexVariables_ >> 41) & X40) << 1) |\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (centerPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121));\n        } else {\n            // oracle is active hence update oracle\n\n            // olderPrice_ => temp_\n            temp_ = (dexVariables_ >> 1) & X40;\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\n\n            // oldPrice_ => temp2_\n            temp2_ = (dexVariables_ >> 41) & X40;\n            temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);\n\n            int priceDiff_ = _priceDiffCheck(temp2_, newPrice_);\n\n            unchecked {\n                // older price w.r.t old price\n                priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);\n            }\n\n            // priceDiffInPercentAndSign_ => temp3_\n            // priceDiff_ will always be lower than ORACLE_LIMIT due to above check\n            unchecked {\n                if (priceDiff_ < 0) {\n                    temp3_ = ((uint(-priceDiff_) * X22) / ORACLE_LIMIT) << 1;\n                } else {\n                    // if greater than or equal to 0 then make sign flag 1\n                    temp3_ = (((uint(priceDiff_) * X22) / ORACLE_LIMIT) << 1) | 1;\n                }\n            }\n\n            if (timeDiff_ > X22) {\n                // if time difference is this then that means DEX has been inactive ~45 days\n                // that means oracle price of this DEX should not be used.\n                timeDiff_ = X22;\n            }\n\n            // temp_ => lastTimeDiff_\n            temp_ = (dexVariables_ >> 154) & X22;\n            uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);\n            uint oracleMap_ = (dexVariables_ >> 179) & X16;\n            if (temp_ > X9) {\n                if (nextOracleSlot_ > 0) {\n                    // if greater than 0 then current slot has 2 or more oracle slot empty\n                    // First 9 bits are of time, so not using that\n                    temp3_ = (temp3_ << 41) | (temp_ << 9);\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));\n                    if (nextOracleSlot_ > 0) {\n                        --nextOracleSlot_;\n                    } else {\n                        // if == 0 that means the oracle slots will get filled and shift to next oracle map\n                        nextOracleSlot_ = 7;\n                        unchecked {\n                            oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                        }\n                        _oracle[oracleMap_] = 0;\n                    }\n                } else {\n                    // if == 0\n                    // then seconds will be in last map\n                    // precision will be in last map + 1\n                    // Storing precision & sign slot in first precision & sign slot and leaving time slot empty\n                    temp3_ = temp3_ << 9;\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;\n                    nextOracleSlot_ = 6; // storing 6 here as 7 is going to occupied right now\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    // Storing time in 2nd precision & sign and leaving time slot empty\n                    _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);\n                }\n            } else {\n                temp3_ = (temp3_ << 9) | temp_;\n                unchecked {\n                    if (nextOracleSlot_ < 7) {\n                        _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));\n                    } else {\n                        _oracle[oracleMap_] = temp3_ << ((7 * 32));\n                    }\n                }\n                if (nextOracleSlot_ > 0) {\n                    --nextOracleSlot_;\n                } else {\n                    nextOracleSlot_ = 7;\n                    unchecked {\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\n                    }\n                    _oracle[oracleMap_] = 0;\n                }\n            }\n\n            // doing this due to stack too deep error when using params memory variables\n            temp_ = newPrice_;\n            temp2_ = centerPrice_;\n            temp3_ = dexVariables_;\n\n            // then update last price\n            return ((temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |\n                (((temp3_ >> 41) & X40) << 1) |\n                (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\n                (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\n                (block.timestamp << 121) |\n                (timeDiff_ << 154) |\n                (nextOracleSlot_ << 176) |\n                (oracleMap_ << 179));\n        }\n    }\n\n    function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal {\n        try\n            IHook(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, hookAddress_)).dexPrice(\n                mode_,\n                swap0to1_,\n                TOKEN_0,\n                TOKEN_1,\n                price_\n            )\n        returns (bool isOk_) {\n            if (!isOk_) revert FluidDexError(ErrorTypes.DexT1__HookReturnedFalse);\n        } catch (bytes memory /*lowLevelData*/) {\n            // skip checking hook nothing\n        }\n    }\n\n    function _updateSupplyShares(uint newTotalShares_) internal {\n        uint totalSupplyShares_ = _totalSupplyShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max supply shares\n        if (\n            (newTotalShares_ > (totalSupplyShares_ & X128)) && \n            newTotalShares_ > (totalSupplyShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__SupplySharesOverflow);\n        }\n\n        // keeping max supply shares intact\n        _totalSupplyShares = ((totalSupplyShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    function _updateBorrowShares(uint newTotalShares_) internal {\n        uint totalBorrowShares_ = _totalBorrowShares;\n\n        // new total shares are greater than old total shares && new total shares are greater than max borrow shares\n        if (\n            (newTotalShares_ > (totalBorrowShares_ & X128)) && \n            newTotalShares_ > (totalBorrowShares_ >> 128)\n        ) {\n            revert FluidDexError(ErrorTypes.DexT1__BorrowSharesOverflow);\n        }\n\n        // keeping max borrow shares intact\n        _totalBorrowShares = ((totalBorrowShares_ >> 128) << 128) | newTotalShares_;\n    }\n\n    constructor(ConstantViews memory constantViews_) ImmutableVariables(constantViews_) {}\n}\n"}},"language":"Solidity","settings":{"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"libraries":{},"optimizer":{"runs":10000000,"enabled":true},"evmVersion":"paris","remappings":[]}},"stdJsonOutput":{"sources":{"contracts/libraries/dexCalcs.sol":{"id":3},"contracts/protocols/dex/error.sol":{"id":12},"contracts/libraries/errorTypes.sol":{"id":5},"contracts/libraries/storageRead.sol":{"id":9},"contracts/libraries/addressCalcs.sol":{"id":1},"contracts/libraries/dexSlotsLink.sol":{"id":4},"contracts/libraries/safeTransfer.sol":{"id":8},"contracts/libraries/liquidityCalcs.sol":{"id":6},"contracts/protocols/dex/errorTypes.sol":{"id":13},"contracts/libraries/bigMathMinified.sol":{"id":2},"solmate/src/utils/FixedPointMathLib.sol":{"id":24},"contracts/libraries/liquiditySlotsLink.sol":{"id":7},"contracts/liquidity/adminModule/structs.sol":{"id":10},"contracts/infiniteProxy/interfaces/iProxy.sol":{"id":0},"contracts/liquidity/interfaces/iLiquidity.sol":{"id":11},"contracts/protocols/dex/interfaces/iDexT1.sol":{"id":15},"contracts/protocols/dex/interfaces/iDexFactory.sol":{"id":14},"contracts/protocols/dex/poolT1/common/variables.sol":{"id":17},"contracts/protocols/dex/poolT1/coreModule/events.sol":{"id":19},"contracts/protocols/dex/poolT1/coreModule/structs.sol":{"id":23},"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"id":18},"contracts/protocols/dex/poolT1/coreModule/interfaces.sol":{"id":22},"contracts/protocols/dex/poolT1/common/constantVariables.sol":{"id":16},"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol":{"id":21},"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol":{"id":20}},"contracts":{"contracts/protocols/dex/poolT1/coreModule/core/main.sol":{"FluidDexT1":{"abi":[{"type":"constructor","inputs":[{"name":"constantViews_","type":"tuple","components":[{"name":"dexId","type":"uint256","internalType":"uint256"},{"name":"liquidity","type":"address","internalType":"address"},{"name":"factory","type":"address","internalType":"address"},{"name":"implementations","type":"tuple","components":[{"name":"shift","type":"address","internalType":"address"},{"name":"admin","type":"address","internalType":"address"},{"name":"colOperations","type":"address","internalType":"address"},{"name":"debtOperations","type":"address","internalType":"address"},{"name":"perfectOperationsAndSwapOut","type":"address","internalType":"address"}],"internalType":"struct Structs.Implementations"},{"name":"deployerContract","type":"address","internalType":"address"},{"name":"token0","type":"address","internalType":"address"},{"name":"token1","type":"address","internalType":"address"},{"name":"supplyToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"supplyToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"oracleMapping","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews"}],"stateMutability":"nonpayable"},{"name":"FluidDexError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexFactoryError","type":"error","inputs":[{"name":"errorId","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexLiquidityOutput","type":"error","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexPerfectLiquidityOutput","type":"error","inputs":[{"name":"token0Amt","type":"uint256","internalType":"uint256"},{"name":"token1Amt","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexPricesAndExchangeRates","type":"error","inputs":[{"name":"pex_","type":"tuple","components":[{"name":"lastStoredPrice","type":"uint256","internalType":"uint256"},{"name":"centerPrice","type":"uint256","internalType":"uint256"},{"name":"upperRange","type":"uint256","internalType":"uint256"},{"name":"lowerRange","type":"uint256","internalType":"uint256"},{"name":"geometricMean","type":"uint256","internalType":"uint256"},{"name":"supplyToken0ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"borrowToken0ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"supplyToken1ExchangePrice","type":"uint256","internalType":"uint256"},{"name":"borrowToken1ExchangePrice","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.PricesAndExchangePrice"}]},{"name":"FluidDexSingleTokenOutput","type":"error","inputs":[{"name":"tokenAmt","type":"uint256","internalType":"uint256"}]},{"name":"FluidDexSwapResult","type":"error","inputs":[{"name":"amountOut","type":"uint256","internalType":"uint256"}]},{"name":"FluidLiquidityCalcsError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"FluidSafeTransferError","type":"error","inputs":[{"name":"errorId_","type":"uint256","internalType":"uint256"}]},{"name":"LogArbitrage","type":"event","inputs":[{"name":"routing","type":"int256","indexed":false,"internalType":"int256"},{"name":"amtOut","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogBorrowDebtLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogBorrowPerfectDebtLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogDepositColLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogDepositPerfectColLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackDebtInOneToken","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackDebtLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogPaybackPerfectDebtLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawColInOneToken","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawColLiquidity","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"LogWithdrawPerfectColLiquidity","type":"event","inputs":[{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token0Amt","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"token1Amt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Swap","type":"event","inputs":[{"name":"swap0to1","type":"bool","indexed":false,"internalType":"bool"},{"name":"amountIn","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amountOut","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"to","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"name":"DEX_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"borrow","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"maxSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"borrowPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0Borrow_","type":"uint256","internalType":"uint256"},{"name":"minToken1Borrow_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"constantsView","type":"function","inputs":[],"outputs":[{"name":"constantsView_","type":"tuple","components":[{"name":"dexId","type":"uint256","internalType":"uint256"},{"name":"liquidity","type":"address","internalType":"address"},{"name":"factory","type":"address","internalType":"address"},{"name":"implementations","type":"tuple","components":[{"name":"shift","type":"address","internalType":"address"},{"name":"admin","type":"address","internalType":"address"},{"name":"colOperations","type":"address","internalType":"address"},{"name":"debtOperations","type":"address","internalType":"address"},{"name":"perfectOperationsAndSwapOut","type":"address","internalType":"address"}],"internalType":"struct Structs.Implementations"},{"name":"deployerContract","type":"address","internalType":"address"},{"name":"token0","type":"address","internalType":"address"},{"name":"token1","type":"address","internalType":"address"},{"name":"supplyToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"supplyToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"borrowToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken0Slot","type":"bytes32","internalType":"bytes32"},{"name":"exchangePriceToken1Slot","type":"bytes32","internalType":"bytes32"},{"name":"oracleMapping","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews"}],"stateMutability":"view"},{"name":"constantsView2","type":"function","inputs":[],"outputs":[{"name":"constantsView2_","type":"tuple","components":[{"name":"token0NumeratorPrecision","type":"uint256","internalType":"uint256"},{"name":"token0DenominatorPrecision","type":"uint256","internalType":"uint256"},{"name":"token1NumeratorPrecision","type":"uint256","internalType":"uint256"},{"name":"token1DenominatorPrecision","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.ConstantViews2"}],"stateMutability":"view"},{"name":"deposit","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"minSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"depositPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0Deposit_","type":"uint256","internalType":"uint256"},{"name":"maxToken1Deposit_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"getCollateralReserves","type":"function","inputs":[{"name":"geometricMean_","type":"uint256","internalType":"uint256"},{"name":"upperRange_","type":"uint256","internalType":"uint256"},{"name":"lowerRange_","type":"uint256","internalType":"uint256"},{"name":"token0SupplyExchangePrice_","type":"uint256","internalType":"uint256"},{"name":"token1SupplyExchangePrice_","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"c_","type":"tuple","components":[{"name":"token0RealReserves","type":"uint256","internalType":"uint256"},{"name":"token1RealReserves","type":"uint256","internalType":"uint256"},{"name":"token0ImaginaryReserves","type":"uint256","internalType":"uint256"},{"name":"token1ImaginaryReserves","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.CollateralReserves"}],"stateMutability":"view"},{"name":"getDebtReserves","type":"function","inputs":[{"name":"geometricMean_","type":"uint256","internalType":"uint256"},{"name":"upperRange_","type":"uint256","internalType":"uint256"},{"name":"lowerRange_","type":"uint256","internalType":"uint256"},{"name":"token0BorrowExchangePrice_","type":"uint256","internalType":"uint256"},{"name":"token1BorrowExchangePrice_","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"d_","type":"tuple","components":[{"name":"token0Debt","type":"uint256","internalType":"uint256"},{"name":"token1Debt","type":"uint256","internalType":"uint256"},{"name":"token0RealReserves","type":"uint256","internalType":"uint256"},{"name":"token1RealReserves","type":"uint256","internalType":"uint256"},{"name":"token0ImaginaryReserves","type":"uint256","internalType":"uint256"},{"name":"token1ImaginaryReserves","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.DebtReserves"}],"stateMutability":"view"},{"name":"getPricesAndExchangePrices","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"liquidityCallback","type":"function","inputs":[{"name":"token_","type":"address","internalType":"address"},{"name":"amount_","type":"uint256","internalType":"uint256"},{"name":"data_","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"oraclePrice","type":"function","inputs":[{"name":"secondsAgos_","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"twaps_","type":"tuple[]","components":[{"name":"twap1by0","type":"uint256","internalType":"uint256"},{"name":"lowestPrice1by0","type":"uint256","internalType":"uint256"},{"name":"highestPrice1by0","type":"uint256","internalType":"uint256"},{"name":"twap0by1","type":"uint256","internalType":"uint256"},{"name":"lowestPrice0by1","type":"uint256","internalType":"uint256"},{"name":"highestPrice0by1","type":"uint256","internalType":"uint256"}],"internalType":"struct Structs.Oracle[]"},{"name":"currentPrice_","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"payback","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"minSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"paybackPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0Payback_","type":"uint256","internalType":"uint256"},{"name":"maxToken1Payback_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"paybackPerfectInOneToken","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"maxToken0_","type":"uint256","internalType":"uint256"},{"name":"maxToken1_","type":"uint256","internalType":"uint256"},{"name":"estimate_","type":"bool","internalType":"bool"}],"outputs":[{"name":"paybackAmt_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"readFromStorage","type":"function","inputs":[{"name":"slot_","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"result_","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"swapIn","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountIn_","type":"uint256","internalType":"uint256"},{"name":"amountOutMin_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountOut_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapInWithCallback","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountIn_","type":"uint256","internalType":"uint256"},{"name":"amountOutMin_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountOut_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapOut","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountOut_","type":"uint256","internalType":"uint256"},{"name":"amountInMax_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountIn_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"swapOutWithCallback","type":"function","inputs":[{"name":"swap0to1_","type":"bool","internalType":"bool"},{"name":"amountOut_","type":"uint256","internalType":"uint256"},{"name":"amountInMax_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"amountIn_","type":"uint256","internalType":"uint256"}],"stateMutability":"payable"},{"name":"withdraw","type":"function","inputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"},{"name":"maxSharesAmt_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"shares_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"withdrawPerfect","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0Withdraw_","type":"uint256","internalType":"uint256"},{"name":"minToken1Withdraw_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"token0Amt_","type":"uint256","internalType":"uint256"},{"name":"token1Amt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"withdrawPerfectInOneToken","type":"function","inputs":[{"name":"shares_","type":"uint256","internalType":"uint256"},{"name":"minToken0_","type":"uint256","internalType":"uint256"},{"name":"minToken1_","type":"uint256","internalType":"uint256"},{"name":"to_","type":"address","internalType":"address"}],"outputs":[{"name":"withdrawAmt_","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"receive","stateMutability":"payable"}],"metadata":"{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"dexId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"liquidity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"shift\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"colOperations\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"debtOperations\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"perfectOperationsAndSwapOut\",\"type\":\"address\"}],\"internalType\":\"struct Structs.Implementations\",\"name\":\"implementations\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"deployerContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"supplyToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"borrowToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"supplyToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"borrowToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"exchangePriceToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"exchangePriceToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"oracleMapping\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.ConstantViews\",\"name\":\"constantViews_\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidDexError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId\",\"type\":\"uint256\"}],\"name\":\"FluidDexFactoryError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"}],\"name\":\"FluidDexLiquidityOutput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"FluidDexPerfectLiquidityOutput\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"lastStoredPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"centerPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"upperRange\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lowerRange\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"geometricMean\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyToken0ExchangePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowToken0ExchangePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyToken1ExchangePrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowToken1ExchangePrice\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.PricesAndExchangePrice\",\"name\":\"pex_\",\"type\":\"tuple\"}],\"name\":\"FluidDexPricesAndExchangeRates\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenAmt\",\"type\":\"uint256\"}],\"name\":\"FluidDexSingleTokenOutput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"FluidDexSwapResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidLiquidityCalcsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorId_\",\"type\":\"uint256\"}],\"name\":\"FluidSafeTransferError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"routing\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amtOut\",\"type\":\"uint256\"}],\"name\":\"LogArbitrage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"LogBorrowDebtLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogBorrowPerfectDebtLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"LogDepositColLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogDepositPerfectColLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogPaybackDebtInOneToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"LogPaybackDebtLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogPaybackPerfectDebtLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogWithdrawColInOneToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"LogWithdrawColLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token0Amt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"token1Amt\",\"type\":\"uint256\"}],\"name\":\"LogWithdrawPerfectColLiquidity\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"swap0to1\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Swap\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"DEX_ID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSharesAmt_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"borrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken0Borrow_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken1Borrow_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"borrowPerfect\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"constantsView\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"dexId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"liquidity\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"shift\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"colOperations\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"debtOperations\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"perfectOperationsAndSwapOut\",\"type\":\"address\"}],\"internalType\":\"struct Structs.Implementations\",\"name\":\"implementations\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"deployerContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"supplyToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"borrowToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"supplyToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"borrowToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"exchangePriceToken0Slot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"exchangePriceToken1Slot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"oracleMapping\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.ConstantViews\",\"name\":\"constantsView_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"constantsView2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"token0NumeratorPrecision\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0DenominatorPrecision\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1NumeratorPrecision\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1DenominatorPrecision\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.ConstantViews2\",\"name\":\"constantsView2_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSharesAmt_\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"estimate_\",\"type\":\"bool\"}],\"name\":\"deposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken0Deposit_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken1Deposit_\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"estimate_\",\"type\":\"bool\"}],\"name\":\"depositPerfect\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"geometricMean_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"upperRange_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lowerRange_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0SupplyExchangePrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1SupplyExchangePrice_\",\"type\":\"uint256\"}],\"name\":\"getCollateralReserves\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"token0RealReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1RealReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0ImaginaryReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1ImaginaryReserves\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.CollateralReserves\",\"name\":\"c_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"geometricMean_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"upperRange_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lowerRange_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0BorrowExchangePrice_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1BorrowExchangePrice_\",\"type\":\"uint256\"}],\"name\":\"getDebtReserves\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"token0Debt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Debt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0RealReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1RealReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token0ImaginaryReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1ImaginaryReserves\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.DebtReserves\",\"name\":\"d_\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPricesAndExchangePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount_\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data_\",\"type\":\"bytes\"}],\"name\":\"liquidityCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"secondsAgos_\",\"type\":\"uint256[]\"}],\"name\":\"oraclePrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"twap1by0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lowestPrice1by0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"highestPrice1by0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"twap0by1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lowestPrice0by1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"highestPrice0by1\",\"type\":\"uint256\"}],\"internalType\":\"struct Structs.Oracle[]\",\"name\":\"twaps_\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"currentPrice_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSharesAmt_\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"estimate_\",\"type\":\"bool\"}],\"name\":\"payback\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken0Payback_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken1Payback_\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"estimate_\",\"type\":\"bool\"}],\"name\":\"paybackPerfect\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken0_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxToken1_\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"estimate_\",\"type\":\"bool\"}],\"name\":\"paybackPerfectInOneToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"paybackAmt_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot_\",\"type\":\"bytes32\"}],\"name\":\"readFromStorage\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"result_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"swap0to1_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountIn_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"swapIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"swap0to1_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountIn_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"swapInWithCallback\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"swap0to1_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountOut_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMax_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"swapOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"swap0to1_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"amountOut_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMax_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"swapOutWithCallback\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn_\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSharesAmt_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken0Withdraw_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken1Withdraw_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"withdrawPerfect\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"token0Amt_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Amt_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"shares_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken0_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minToken1_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to_\",\"type\":\"address\"}],\"name\":\"withdrawPerfectInOneToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawAmt_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"LogArbitrage(int256,uint256)\":{\"params\":{\"amtOut\":\"if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow\",\"routing\":\"if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback\"}},\"LogBorrowDebtLiquidity(uint256,uint256,uint256)\":{\"params\":{\"amount0\":\"Amount of token0 borrowed.\",\"amount1\":\"Amount of token1 borrowed.\",\"shares\":\"Amount of shares minted.\"}},\"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"shares minted\",\"token0Amt\":\"Amount of token0 borrowed.\",\"token1Amt\":\"Amount of token1 borrowed.\"}},\"LogDepositColLiquidity(uint256,uint256,uint256)\":{\"params\":{\"amount0\":\"Amount of token0 deposited.\",\"amount1\":\"Amount of token1 deposited.\",\"shares\":\"Amount of shares minted.\"}},\"LogDepositPerfectColLiquidity(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"Expected exact shares to be received.\",\"token0Amt\":\"Amount of token1 deposited.\"}},\"LogPaybackDebtInOneToken(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"shares burned\",\"token0Amt\":\"Amount of token0 paid back.\",\"token1Amt\":\"Amount of token1 paid back.\"}},\"LogPaybackDebtLiquidity(uint256,uint256,uint256)\":{\"params\":{\"amount0\":\"Amount of token0 paid back.\",\"amount1\":\"Amount of token1 paid back.\",\"shares\":\"Amount of shares burned.\"}},\"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"shares burned\",\"token0Amt\":\"Amount of token0 paid back.\",\"token1Amt\":\"Amount of token1 paid back.\"}},\"LogWithdrawColInOneToken(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"shares burned\",\"token0Amt\":\"Amount of token0 withdrawn.\",\"token1Amt\":\"Amount of token1 withdrawn.\"}},\"LogWithdrawColLiquidity(uint256,uint256,uint256)\":{\"params\":{\"amount0\":\"Amount of token0 withdrawn.\",\"amount1\":\"Amount of token1 withdrawn.\",\"shares\":\"Amount of shares burned.\"}},\"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)\":{\"params\":{\"shares\":\"shares burned\",\"token0Amt\":\"Amount of token0 withdrawn.\",\"token1Amt\":\"Amount of token1 withdrawn.\"}},\"Swap(bool,uint256,uint256,address)\":{\"params\":{\"amountIn\":\"The amount of tokens to be sent to the vault to swap.\",\"amountOut\":\"The amount of tokens user got from the swap.\",\"swap0to1\":\"Indicates whether the swap is from token0 to token1 or vice-versa.\",\"to\":\"Recepient of swapped tokens.\"}}},\"kind\":\"dev\",\"methods\":{\"borrow(uint256,uint256,uint256,address)\":{\"details\":\"This function allows users to borrow tokens in any proportion from the debt pool\",\"params\":{\"maxSharesAmt_\":\"The maximum amount of shares the user is willing to receive\",\"to_\":\"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\",\"token0Amt_\":\"The amount of token0 to borrow\",\"token1Amt_\":\"The amount of token1 to borrow\"},\"returns\":{\"shares_\":\"The amount of borrow shares minted to represent the borrowed amount\"}},\"borrowPerfect(uint256,uint256,uint256,address)\":{\"details\":\"This function allows users to borrow tokens in equal proportion to the current debt pool ratio\",\"params\":{\"minToken0Borrow_\":\"Minimum amount of token0 to borrow\",\"minToken1Borrow_\":\"Minimum amount of token1 to borrow\",\"shares_\":\"The number of shares to borrow\",\"to_\":\"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\"},\"returns\":{\"token0Amt_\":\"Amount of token0 borrowed\",\"token1Amt_\":\"Amount of token1 borrowed\"}},\"deposit(uint256,uint256,uint256,bool)\":{\"details\":\"This function allows users to deposit tokens in any proportion into the col pool\",\"params\":{\"estimate_\":\"If true, function will revert with estimated shares without executing the deposit\",\"minSharesAmt_\":\"The minimum amount of shares the user expects to receive\",\"token0Amt_\":\"The amount of token0 to deposit\",\"token1Amt_\":\"The amount of token1 to deposit\"},\"returns\":{\"shares_\":\"The amount of shares minted for the deposit\"}},\"depositPerfect(uint256,uint256,uint256,bool)\":{\"details\":\"Deposit tokens in equal proportion to the current pool ratio\",\"params\":{\"estimate_\":\"If true, function will revert with estimated deposit amounts without executing the deposit\",\"maxToken0Deposit_\":\"Maximum amount of token0 to deposit\",\"maxToken1Deposit_\":\"Maximum amount of token1 to deposit\",\"shares_\":\"The number of shares to mint\"},\"returns\":{\"token0Amt_\":\"Amount of token0 deposited\",\"token1Amt_\":\"Amount of token1 deposited\"}},\"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)\":{\"details\":\"This function retrieves the supply of both tokens from the liquidity layer,      adjusts them based on exchange prices, and calculates imaginary reserves      based on the geometric mean and price range\",\"params\":{\"geometricMean_\":\"The geometric mean of the token prices\",\"lowerRange_\":\"The lower price range\",\"token0SupplyExchangePrice_\":\"The exchange price for token0 from liquidity layer\",\"token1SupplyExchangePrice_\":\"The exchange price for token1 from liquidity layer\",\"upperRange_\":\"The upper price range\"},\"returns\":{\"c_\":\"A struct containing the calculated real and imaginary reserves for both tokens:         - token0RealReserves: The real reserves of token0         - token1RealReserves: The real reserves of token1         - token0ImaginaryReserves: The imaginary reserves of token0         - token1ImaginaryReserves: The imaginary reserves of token1\"}},\"getDebtReserves(uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"geometricMean_\":\"The geometric mean of the upper and lower price ranges\",\"lowerRange_\":\"The lower price range\",\"token0BorrowExchangePrice_\":\"The exchange price of token0 from liquidity layer\",\"token1BorrowExchangePrice_\":\"The exchange price of token1 from liquidity layer\",\"upperRange_\":\"The upper price range\"},\"returns\":{\"d_\":\"The calculated debt reserves for both tokens, containing:         - token0Debt: The debt amount of token0         - token1Debt: The debt amount of token1         - token0RealReserves: The real reserves of token0 derived from token1 debt         - token1RealReserves: The real reserves of token1 derived from token0 debt         - token0ImaginaryReserves: The imaginary debt reserves of token0         - token1ImaginaryReserves: The imaginary debt reserves of token1\"}},\"liquidityCallback(address,uint256,bytes)\":{\"details\":\"liquidity callback for cheaper token transfers in case of deposit or payback. only callable by Liquidity during an operation.\"},\"oraclePrice(uint256[])\":{\"details\":\"the oracle assumes last set price of pool till the next swap happens. There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration but the difference due to interest will be super low so this difference is ignored For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other. then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\",\"params\":{\"secondsAgos_\":\"array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\"},\"returns\":{\"currentPrice_\":\"price of pool after the most recent swap\",\"twaps_\":\"twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\"}},\"payback(uint256,uint256,uint256,bool)\":{\"details\":\"This function allows users to payback tokens in any proportion to the debt pool\",\"params\":{\"estimate_\":\"If true, function will revert with estimated shares without executing the payback\",\"minSharesAmt_\":\"The minimum amount of shares the user expects to burn\",\"token0Amt_\":\"The amount of token0 to payback\",\"token1Amt_\":\"The amount of token1 to payback\"},\"returns\":{\"shares_\":\"The amount of borrow shares burned for the payback\"}},\"paybackPerfect(uint256,uint256,uint256,bool)\":{\"details\":\"This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\",\"params\":{\"estimate_\":\"If true, function will revert with estimated payback amounts without executing the payback\",\"maxToken0Payback_\":\"Maximum amount of token0 to pay back\",\"maxToken1Payback_\":\"Maximum amount of token1 to pay back\",\"shares_\":\"The number of shares to pay back\"},\"returns\":{\"token0Amt_\":\"Amount of token0 paid back\",\"token1Amt_\":\"Amount of token1 paid back\"}},\"paybackPerfectInOneToken(uint256,uint256,uint256,bool)\":{\"details\":\"This function allows users to payback their debt with perfect shares in one token\",\"params\":{\"estimate_\":\"If true, the function will revert with the estimated payback amount without executing the payback\",\"maxToken0_\":\"The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\",\"maxToken1_\":\"The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\",\"shares_\":\"The number of shares to burn for payback\"},\"returns\":{\"paybackAmt_\":\"The amount of tokens paid back in the chosen token\"}},\"swapIn(bool,uint256,uint256,address)\":{\"details\":\"Swap tokens with perfect amount in\",\"params\":{\"amountIn_\":\"The exact amount of tokens to swap in\",\"amountOutMin_\":\"The minimum amount of tokens to receive after swap\",\"swap0to1_\":\"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\",\"to_\":\"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\"},\"returns\":{\"amountOut_\":\"The amount of output tokens received from the swap\"}},\"swapInWithCallback(bool,uint256,uint256,address)\":{\"details\":\"Swap tokens with perfect amount in and callback functionality\",\"params\":{\"amountIn_\":\"The exact amount of tokens to swap in\",\"amountOutMin_\":\"The minimum amount of tokens to receive after swap\",\"swap0to1_\":\"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\",\"to_\":\"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\"},\"returns\":{\"amountOut_\":\"The amount of output tokens received from the swap\"}},\"swapOut(bool,uint256,uint256,address)\":{\"details\":\"Swap tokens with perfect amount out\",\"params\":{\"amountInMax_\":\"Maximum amount of tokens to swap in\",\"amountOut_\":\"The exact amount of tokens to receive after swap\",\"swap0to1_\":\"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\",\"to_\":\"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\"},\"returns\":{\"amountIn_\":\"The amount of input tokens used for the swap\"}},\"swapOutWithCallback(bool,uint256,uint256,address)\":{\"details\":\"Swap tokens with perfect amount out and callback functionality\",\"params\":{\"amountInMax_\":\"Maximum amount of tokens to swap in\",\"amountOut_\":\"The exact amount of tokens to receive after swap\",\"swap0to1_\":\"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\",\"to_\":\"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\"},\"returns\":{\"amountIn_\":\"The amount of input tokens used for the swap\"}},\"withdraw(uint256,uint256,uint256,address)\":{\"details\":\"This function allows users to withdraw tokens in any proportion from the col pool\",\"params\":{\"maxSharesAmt_\":\"The maximum number of shares the user is willing to burn\",\"to_\":\"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\",\"token0Amt_\":\"The amount of token0 to withdraw\",\"token1Amt_\":\"The amount of token1 to withdraw\"},\"returns\":{\"shares_\":\"The number of shares burned for the withdrawal\"}},\"withdrawPerfect(uint256,uint256,uint256,address)\":{\"details\":\"This function allows users to withdraw a perfect amount of collateral liquidity\",\"params\":{\"minToken0Withdraw_\":\"The minimum amount of token0 the user is willing to accept\",\"minToken1Withdraw_\":\"The minimum amount of token1 the user is willing to accept\",\"shares_\":\"The number of shares to withdraw\",\"to_\":\"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\"},\"returns\":{\"token0Amt_\":\"The amount of token0 withdrawn\",\"token1Amt_\":\"The amount of token1 withdrawn\"}},\"withdrawPerfectInOneToken(uint256,uint256,uint256,address)\":{\"details\":\"This function allows users to withdraw their collateral with perfect shares in one token\",\"params\":{\"minToken0_\":\"The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\",\"minToken1_\":\"The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\",\"shares_\":\"The number of shares to burn for withdrawal\",\"to_\":\"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\"},\"returns\":{\"withdrawAmt_\":\"The amount of tokens withdrawn in the chosen token\"}}},\"title\":\"FluidDexT1\",\"version\":1},\"userdoc\":{\"errors\":{\"FluidDexSwapResult(uint256)\":[{\"notice\":\"used to simulate swap to find the output amount\"}]},\"events\":{\"LogArbitrage(int256,uint256)\":{\"notice\":\"Emitted when internal arbitrage between 2 pools happen\"},\"LogBorrowDebtLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is borrowed with specified token0 & token1 amount\"},\"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is borrowed with shares specified.\"},\"LogDepositColLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is deposited with specified token0 & token1 amount\"},\"LogDepositPerfectColLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is added with shares specified.\"},\"LogPaybackDebtInOneToken(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is paid back with shares specified from one token only.\"},\"LogPaybackDebtLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is paid back with specified token0 & token1 amount\"},\"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is paid back with shares specified.\"},\"LogWithdrawColInOneToken(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is withdrawn with shares specified into one token only.\"},\"LogWithdrawColLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is withdrawn with specified token0 & token1 amount\"},\"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)\":{\"notice\":\"Emitted when liquidity is withdrawn with shares specified.\"},\"Swap(bool,uint256,uint256,address)\":{\"notice\":\"Emitted on token swaps\"}},\"kind\":\"user\",\"methods\":{\"constantsView()\":{\"notice\":\"returns all Vault constants\"},\"constantsView2()\":{\"notice\":\"returns all Vault constants\"},\"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the real and imaginary reserves for collateral tokens\"},\"getDebtReserves(uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Calculates the debt reserves for both tokens\"}},\"notice\":\"Implements core logics for Fluid Dex protocol. Note Token transfers happen directly from user to Liquidity contract and vice-versa.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/protocols/dex/poolT1/coreModule/core/main.sol\":\"FluidDexT1\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"contracts/infiniteProxy/interfaces/iProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\ninterface IProxy {\\n    function setAdmin(address newAdmin_) external;\\n\\n    function setDummyImplementation(address newDummyImplementation_) external;\\n\\n    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\\n\\n    function removeImplementation(address implementation_) external;\\n\\n    function getAdmin() external view returns (address);\\n\\n    function getDummyImplementation() external view returns (address);\\n\\n    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\\n\\n    function getSigsImplementation(bytes4 sig_) external view returns (address);\\n\\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\\n}\\n\",\"keccak256\":\"0xbb605491d4bac08e816248feecae7dd17cfc1877c88b2e555abece2970f5ea00\",\"license\":\"MIT\"},\"contracts/libraries/addressCalcs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\n/// @notice implements calculation of address for contracts deployed through CREATE.\\n/// Accepts contract deployed from which address & nonce\\nlibrary AddressCalcs {\\n\\n    /// @notice                         Computes the address of a contract based\\n    /// @param deployedFrom_            Address from which the contract was deployed\\n    /// @param nonce_                   Nonce at which the contract was deployed\\n    /// @return contract_               Address of deployed contract\\n    function addressCalc(address deployedFrom_, uint nonce_) internal pure returns (address contract_) {\\n        // @dev based on https://ethereum.stackexchange.com/a/61413\\n\\n        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment\\n        // hence, nonce of vault deployment starts with 1.\\n        bytes memory data;\\n        if (nonce_ == 0x00) {\\n            return address(0);\\n        } else if (nonce_ <= 0x7f) {\\n            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployedFrom_, uint8(nonce_));\\n        } else if (nonce_ <= 0xff) {\\n            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployedFrom_, bytes1(0x81), uint8(nonce_));\\n        } else if (nonce_ <= 0xffff) {\\n            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployedFrom_, bytes1(0x82), uint16(nonce_));\\n        } else if (nonce_ <= 0xffffff) {\\n            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployedFrom_, bytes1(0x83), uint24(nonce_));\\n        } else {\\n            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), deployedFrom_, bytes1(0x84), uint32(nonce_));\\n        }\\n\\n        return address(uint160(uint256(keccak256(data))));\\n    }\\n\\n}\",\"keccak256\":\"0xca389bcfef035463ff43939ac5eccab07ab74cbb053e201541f9bcd846b3105a\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/bigMathMinified.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\\n/// result in significant gas cost reduction due to storage space reduction.\\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\\nlibrary BigMathMinified {\\n    /// @dev constants to use for `roundUp` input param to increase readability\\n    bool internal constant ROUND_DOWN = false;\\n    bool internal constant ROUND_UP = true;\\n\\n    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\\n    /// e.g.:\\n    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\\n    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\\n    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\\n    ///                                                                        ^-------------------- 51(exponent) -------------- ^\\n    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)\\n    /// exponent =                                            0011,0011     (51)\\n    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)\\n    ///\\n    /// @param normal number which needs to be converted into Big Number\\n    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\\n    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\\n    /// @param roundUp signals if result should be rounded down or up\\n    /// @return bigNumber converted bigNumber (coefficient << exponent)\\n    function toBigNumber(\\n        uint256 normal,\\n        uint256 coefficientSize,\\n        uint256 exponentSize,\\n        bool roundUp\\n    ) internal pure returns (uint256 bigNumber) {\\n        assembly {\\n            let lastBit_\\n            let number_ := normal\\n            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\\n                number_ := shr(0x80, number_)\\n                lastBit_ := 0x80\\n            }\\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\\n                number_ := shr(0x40, number_)\\n                lastBit_ := add(lastBit_, 0x40)\\n            }\\n            if gt(number_, 0xFFFFFFFF) {\\n                number_ := shr(0x20, number_)\\n                lastBit_ := add(lastBit_, 0x20)\\n            }\\n            if gt(number_, 0xFFFF) {\\n                number_ := shr(0x10, number_)\\n                lastBit_ := add(lastBit_, 0x10)\\n            }\\n            if gt(number_, 0xFF) {\\n                number_ := shr(0x8, number_)\\n                lastBit_ := add(lastBit_, 0x8)\\n            }\\n            if gt(number_, 0xF) {\\n                number_ := shr(0x4, number_)\\n                lastBit_ := add(lastBit_, 0x4)\\n            }\\n            if gt(number_, 0x3) {\\n                number_ := shr(0x2, number_)\\n                lastBit_ := add(lastBit_, 0x2)\\n            }\\n            if gt(number_, 0x1) {\\n                lastBit_ := add(lastBit_, 1)\\n            }\\n            if gt(number_, 0) {\\n                lastBit_ := add(lastBit_, 1)\\n            }\\n            if lt(lastBit_, coefficientSize) {\\n                // for throw exception\\n                lastBit_ := coefficientSize\\n            }\\n            let exponent := sub(lastBit_, coefficientSize)\\n            let coefficient := shr(exponent, normal)\\n            if and(roundUp, gt(exponent, 0)) {\\n                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\\n                coefficient := add(coefficient, 1)\\n                if eq(shl(coefficientSize, 1), coefficient) {\\n                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\\n                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\\n                    coefficient := shl(sub(coefficientSize, 1), 1)\\n                    exponent := add(exponent, 1)\\n                }\\n            }\\n            if iszero(lt(exponent, shl(exponentSize, 1))) {\\n                // if exponent is >= exponentSize, the normal number is too big to fit within\\n                // BigNumber with too small sizes for coefficient and exponent\\n                revert(0, 0)\\n            }\\n            bigNumber := shl(exponentSize, coefficient)\\n            bigNumber := add(bigNumber, exponent)\\n        }\\n    }\\n\\n    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\\n    function fromBigNumber(\\n        uint256 bigNumber,\\n        uint256 exponentSize,\\n        uint256 exponentMask\\n    ) internal pure returns (uint256 normal) {\\n        assembly {\\n            let coefficient := shr(exponentSize, bigNumber)\\n            let exponent := and(bigNumber, exponentMask)\\n            normal := shl(exponent, coefficient)\\n        }\\n    }\\n\\n    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\\n    /// e.g.\\n    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\\n    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^\\n    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\\n        assembly {\\n            let number_ := normal\\n            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\\n                number_ := shr(0x80, number_)\\n                lastBit := 0x80\\n            }\\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\\n                number_ := shr(0x40, number_)\\n                lastBit := add(lastBit, 0x40)\\n            }\\n            if gt(number_, 0xFFFFFFFF) {\\n                number_ := shr(0x20, number_)\\n                lastBit := add(lastBit, 0x20)\\n            }\\n            if gt(number_, 0xFFFF) {\\n                number_ := shr(0x10, number_)\\n                lastBit := add(lastBit, 0x10)\\n            }\\n            if gt(number_, 0xFF) {\\n                number_ := shr(0x8, number_)\\n                lastBit := add(lastBit, 0x8)\\n            }\\n            if gt(number_, 0xF) {\\n                number_ := shr(0x4, number_)\\n                lastBit := add(lastBit, 0x4)\\n            }\\n            if gt(number_, 0x3) {\\n                number_ := shr(0x2, number_)\\n                lastBit := add(lastBit, 0x2)\\n            }\\n            if gt(number_, 0x1) {\\n                lastBit := add(lastBit, 1)\\n            }\\n            if gt(number_, 0) {\\n                lastBit := add(lastBit, 1)\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xf0be1002909edf30aec3dc6623c2bd2407ed94064b62674c01032b844dec206a\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/dexCalcs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { BigMathMinified } from \\\"./bigMathMinified.sol\\\";\\nimport { DexSlotsLink } from \\\"./dexSlotsLink.sol\\\";\\n\\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n// @DEV ATTENTION: ON ANY CHANGES HERE, MAKE SURE THAT LOGIC IN VAULTS WILL STILL BE VALID.\\n// SOME CODE THERE ASSUMES DEXCALCS == LIQUIDITYCALCS.\\n// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n/// @notice implements calculation methods used for Fluid Dex such as updated withdrawal / borrow limits.\\nlibrary DexCalcs {\\n    // constants used for BigMath conversion from and to storage\\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\\n\\n    uint256 internal constant FOUR_DECIMALS = 1e4;\\n    uint256 internal constant X14 = 0x3fff;\\n    uint256 internal constant X18 = 0x3ffff;\\n    uint256 internal constant X24 = 0xffffff;\\n    uint256 internal constant X33 = 0x1ffffffff;\\n    uint256 internal constant X64 = 0xffffffffffffffff;\\n\\n    ///////////////////////////////////////////////////////////////////////////\\n    //////////                      CALC LIMITS                       /////////\\n    ///////////////////////////////////////////////////////////////////////////\\n\\n    /// @dev calculates withdrawal limit before an operate execution:\\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n    /// @param userSupplyData_ user supply data packed uint256 from storage\\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\\n    function calcWithdrawalLimitBeforeOperate(\\n        uint256 userSupplyData_,\\n        uint256 userSupply_\\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\\n        // a deposit anyway. Important is that it would not revert.\\n\\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\\n        // is the fully expanded limit immediately.\\n\\n        // extract last set withdrawal limit\\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) &\\n            X64;\\n        lastWithdrawalLimit_ =\\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\\n        if (lastWithdrawalLimit_ == 0) {\\n            // withdrawal limit is not activated. Max withdrawal allowed\\n            return 0;\\n        }\\n\\n        uint256 maxWithdrawableLimit_;\\n        uint256 temp_;\\n        unchecked {\\n            // extract max withdrawable percent of user supply and\\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\\n\\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            maxWithdrawableLimit_ =\\n                (((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\\n                FOUR_DECIMALS;\\n\\n            // time elapsed since last withdrawal limit was set (in seconds)\\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\\n            // last timestamp can not be > current timestamp\\n            temp_ = block.timestamp - ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\\n        }\\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\\n        temp_ =\\n            (maxWithdrawableLimit_ * temp_) /\\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\\n            ((userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\\n        unchecked {\\n            // underflow explicitly checked & handled\\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n            temp_ = userSupply_ - maxWithdrawableLimit_;\\n        }\\n        // if withdrawal limit is decreased below minimum then set minimum\\n        // (e.g. when more than expandDuration time has elapsed)\\n        if (temp_ > currentWithdrawalLimit_) {\\n            currentWithdrawalLimit_ = temp_;\\n        }\\n    }\\n\\n    /// @dev calculates withdrawal limit after an operate execution:\\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n    /// @param userSupplyData_ user supply data packed uint256 from storage\\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\\n    ///                          raw for with interest mode, normal amount for interest free mode!\\n    function calcWithdrawalLimitAfterOperate(\\n        uint256 userSupplyData_,\\n        uint256 userSupply_,\\n        uint256 newWithdrawalLimit_\\n    ) internal pure returns (uint256) {\\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\\n        uint256 temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        // if user supply is below base limit then max withdrawals are allowed\\n        if (userSupply_ < temp_) {\\n            return 0;\\n        }\\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\\n        temp_ = (userSupplyData_ >> DexSlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\\n        unchecked {\\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\\n        }\\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\\n        // increased deposit amount outpaces withrawals.\\n        if (temp_ > newWithdrawalLimit_) {\\n            return temp_;\\n        }\\n        return newWithdrawalLimit_;\\n    }\\n\\n    /// @dev calculates borrow limit before an operate execution:\\n    /// total amount user borrow can reach (not borrowable amount in current operation).\\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\\n    ///                             raw for with interest mode, normal amount for interest free mode!\\n    function calcBorrowLimitBeforeOperate(\\n        uint256 userBorrowData_,\\n        uint256 userBorrow_\\n    ) internal view returns (uint256 currentBorrowLimit_) {\\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\\n\\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\\n\\n        uint256 maxExpansionLimit_;\\n        uint256 maxExpandedBorrowLimit_;\\n        unchecked {\\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n\\n            // calculate max borrow limit: Max point limit can increase to since last interaction\\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\\n        }\\n\\n        // currentBorrowLimit_ = extract base borrow limit\\n        currentBorrowLimit_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n        currentBorrowLimit_ =\\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\\n            return currentBorrowLimit_;\\n        }\\n        // time elapsed since last borrow limit was set (in seconds)\\n        unchecked {\\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\\n            temp_ = block.timestamp - ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\\n        }\\n\\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\\n        currentBorrowLimit_ =\\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\\n            ((maxExpansionLimit_ * temp_) /\\n                ((userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\\n            //  extract last set borrow limit\\n            BigMathMinified.fromBigNumber(\\n                (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\\n                DEFAULT_EXPONENT_SIZE,\\n                DEFAULT_EXPONENT_MASK\\n            );\\n\\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\\n        // so set to `maxExpandedBorrowLimit_` in that case.\\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\\n        }\\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (currentBorrowLimit_ > temp_) {\\n            currentBorrowLimit_ = temp_;\\n        }\\n    }\\n\\n    /// @dev calculates borrow limit after an operate execution:\\n    /// total amount user borrow can reach (not borrowable amount in current operation).\\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\\n    function calcBorrowLimitAfterOperate(\\n        uint256 userBorrowData_,\\n        uint256 userBorrow_,\\n        uint256 newBorrowLimit_\\n    ) internal pure returns (uint256 borrowLimit_) {\\n        // temp_ = extract borrow expand percent\\n        uint256 temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\\n\\n        unchecked {\\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n        }\\n\\n        // temp_ = extract base borrow limit\\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (borrowLimit_ < temp_) {\\n            // below base limit, borrow limit is always base limit\\n            return temp_;\\n        }\\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n        temp_ = (userBorrowData_ >> DexSlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        // make sure fully expanded borrow limit is not above hard max borrow limit\\n        if (borrowLimit_ > temp_) {\\n            borrowLimit_ = temp_;\\n        }\\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\\n        if (newBorrowLimit_ > borrowLimit_) {\\n            return borrowLimit_;\\n        }\\n        return newBorrowLimit_;\\n    }\\n}\\n\",\"keccak256\":\"0xd033a77bd57f4a608e693fdf6147ddd3bbfa0d80d86c1097d24e428c886c0d5e\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/dexSlotsLink.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\n/// @notice library that helps in reading / working with storage slot data of Fluid Dex.\\n/// @dev as all data for Fluid Dex is internal, any data must be fetched directly through manual\\n/// slot reading through this library or, if gas usage is less important, through the FluidDexResolver.\\nlibrary DexSlotsLink {\\n    /// @dev storage slot for variables at Dex\\n    uint256 internal constant DEX_VARIABLES_SLOT = 0;\\n    /// @dev storage slot for variables2 at Dex\\n    uint256 internal constant DEX_VARIABLES2_SLOT = 1;\\n    /// @dev storage slot for total supply shares at Dex\\n    uint256 internal constant DEX_TOTAL_SUPPLY_SHARES_SLOT = 2;\\n    /// @dev storage slot for user supply mapping at Dex\\n    uint256 internal constant DEX_USER_SUPPLY_MAPPING_SLOT = 3;\\n    /// @dev storage slot for total borrow shares at Dex\\n    uint256 internal constant DEX_TOTAL_BORROW_SHARES_SLOT = 4;\\n    /// @dev storage slot for user borrow mapping at Dex\\n    uint256 internal constant DEX_USER_BORROW_MAPPING_SLOT = 5;\\n    /// @dev storage slot for oracle mapping at Dex\\n    uint256 internal constant DEX_ORACLE_MAPPING_SLOT = 6;\\n    /// @dev storage slot for range and threshold shifts at Dex\\n    uint256 internal constant DEX_RANGE_THRESHOLD_SHIFTS_SLOT = 7;\\n    /// @dev storage slot for center price shift at Dex\\n    uint256 internal constant DEX_CENTER_PRICE_SHIFT_SLOT = 8;\\n\\n    // --------------------------------\\n    // @dev stacked uint256 storage slots bits position data for each:\\n\\n    // UserSupplyData\\n    uint256 internal constant BITS_USER_SUPPLY_ALLOWED = 0;\\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\\n\\n    // UserBorrowData\\n    uint256 internal constant BITS_USER_BORROW_ALLOWED = 0;\\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\\n\\n    // --------------------------------\\n\\n    /// @notice Calculating the slot ID for Dex contract for single mapping at `slot_` for `key_`\\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\\n        return keccak256(abi.encode(key_, slot_));\\n    }\\n\\n    /// @notice Calculating the slot ID for Dex contract for double mapping at `slot_` for `key1_` and `key2_`\\n    function calculateDoubleMappingStorageSlot(\\n        uint256 slot_,\\n        address key1_,\\n        address key2_\\n    ) internal pure returns (bytes32) {\\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\\n        return keccak256(abi.encode(key2_, intermediateSlot_));\\n    }\\n}\\n\",\"keccak256\":\"0xf1d6550d83fb0155a26655234922c9bdf4a1bbcf7a3ca767e9123d367a795307\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/errorTypes.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nlibrary LibsErrorTypes {\\n    /***********************************|\\n    |         LiquidityCalcs            | \\n    |__________________________________*/\\n\\n    /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet)\\n    uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001;\\n\\n    /// @notice thrown when rate data is set to a version that is not implemented\\n    uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002;\\n\\n    /// @notice thrown when the calculated borrow rate turns negative. This should never happen.\\n    uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003;\\n\\n    /***********************************|\\n    |           SafeTransfer            | \\n    |__________________________________*/\\n\\n    /// @notice thrown when safe transfer from for an ERC20 fails\\n    uint256 internal constant SafeTransfer__TransferFromFailed = 71001;\\n\\n    /// @notice thrown when safe transfer for an ERC20 fails\\n    uint256 internal constant SafeTransfer__TransferFailed = 71002;\\n\\n    /***********************************|\\n    |           SafeApprove             | \\n    |__________________________________*/\\n\\n    /// @notice thrown when safe approve from for an ERC20 fails\\n    uint256 internal constant SafeApprove__ApproveFailed = 81001;\\n}\\n\",\"keccak256\":\"0x4057f500fd44ce9e89049512d06d5f72c46f91938ed37312fb044c204451009b\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/liquidityCalcs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { LibsErrorTypes as ErrorTypes } from \\\"./errorTypes.sol\\\";\\nimport { LiquiditySlotsLink } from \\\"./liquiditySlotsLink.sol\\\";\\nimport { BigMathMinified } from \\\"./bigMathMinified.sol\\\";\\n\\n/// @notice implements calculation methods used for Fluid liquidity such as updated exchange prices,\\n/// borrow rate, withdrawal / borrow limits, revenue amount.\\nlibrary LiquidityCalcs {\\n    error FluidLiquidityCalcsError(uint256 errorId_);\\n\\n    /// @notice emitted if the calculated borrow rate surpassed max borrow rate (16 bits) and was capped at maximum value 65535\\n    event BorrowRateMaxCap();\\n\\n    /// @dev constants as from Liquidity variables.sol\\n    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\\n\\n    /// @dev Ignoring leap years\\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\\n    // constants used for BigMath conversion from and to storage\\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\\n\\n    uint256 internal constant FOUR_DECIMALS = 1e4;\\n    uint256 internal constant TWELVE_DECIMALS = 1e12;\\n    uint256 internal constant X14 = 0x3fff;\\n    uint256 internal constant X15 = 0x7fff;\\n    uint256 internal constant X16 = 0xffff;\\n    uint256 internal constant X18 = 0x3ffff;\\n    uint256 internal constant X24 = 0xffffff;\\n    uint256 internal constant X33 = 0x1ffffffff;\\n    uint256 internal constant X64 = 0xffffffffffffffff;\\n\\n    ///////////////////////////////////////////////////////////////////////////\\n    //////////                  CALC EXCHANGE PRICES                  /////////\\n    ///////////////////////////////////////////////////////////////////////////\\n\\n    /// @dev calculates interest (exchange prices) for a token given its' exchangePricesAndConfig from storage.\\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\\n    /// @return supplyExchangePrice_ updated supplyExchangePrice\\n    /// @return borrowExchangePrice_ updated borrowExchangePrice\\n    function calcExchangePrices(\\n        uint256 exchangePricesAndConfig_\\n    ) internal view returns (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) {\\n        // Extracting exchange prices\\n        supplyExchangePrice_ =\\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) &\\n            X64;\\n        borrowExchangePrice_ =\\n            (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) &\\n            X64;\\n\\n        if (supplyExchangePrice_ == 0 || borrowExchangePrice_ == 0) {\\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__ExchangePriceZero);\\n        }\\n\\n        uint256 temp_ = exchangePricesAndConfig_ & X16; // temp_ = borrowRate\\n\\n        unchecked {\\n            // last timestamp can not be > current timestamp\\n            uint256 secondsSinceLastUpdate_ = block.timestamp -\\n                ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_LAST_TIMESTAMP) & X33);\\n\\n            uint256 borrowRatio_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_RATIO) &\\n                X15;\\n            if (secondsSinceLastUpdate_ == 0 || temp_ == 0 || borrowRatio_ == 1) {\\n                // if no time passed, borrow rate is 0, or no raw borrowings: no exchange price update needed\\n                // (if borrowRatio_ == 1 means there is only borrowInterestFree, as first bit is 1 and rest is 0)\\n                return (supplyExchangePrice_, borrowExchangePrice_);\\n            }\\n\\n            // calculate new borrow exchange price.\\n            // formula borrowExchangePriceIncrease: previous price * borrow rate * secondsSinceLastUpdate_.\\n            // nominator is max uint112 (uint64 * uint16 * uint32). Divisor can not be 0.\\n            borrowExchangePrice_ +=\\n                (borrowExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\\n                (SECONDS_PER_YEAR * FOUR_DECIMALS);\\n\\n            // FOR SUPPLY EXCHANGE PRICE:\\n            // all yield paid by borrowers (in mode with interest) goes to suppliers in mode with interest.\\n            // formula: previous price * supply rate * secondsSinceLastUpdate_.\\n            // where supply rate = (borrow rate  - revenueFee%) * ratioSupplyYield. And\\n            // ratioSupplyYield = utilization * supplyRatio * borrowRatio\\n            //\\n            // Example:\\n            // supplyRawInterest is 80, supplyInterestFree is 20. totalSupply is 100. BorrowedRawInterest is 50.\\n            // BorrowInterestFree is 10. TotalBorrow is 60. borrow rate 40%, revenueFee 10%.\\n            // yield is 10 (so half a year must have passed).\\n            // supplyRawInterest must become worth 89. totalSupply must become 109. BorrowedRawInterest must become 60.\\n            // borrowInterestFree must still be 10. supplyInterestFree still 20. totalBorrow 70.\\n            // supplyExchangePrice would have to go from 1 to 1,125 (+ 0.125). borrowExchangePrice from 1 to 1,2 (+0.2).\\n            // utilization is 60%. supplyRatio = 20 / 80 = 25% (only 80% of lenders receiving yield).\\n            // borrowRatio = 10 / 50 = 20% (only 83,333% of borrowers paying yield):\\n            // x of borrowers paying yield = 100% - (20 / (100 + 20)) = 100% - 16.6666666% = 83,333%.\\n            // ratioSupplyYield = 60% * 83,33333% * (100% + 20%) = 62,5%\\n            // supplyRate = (40% * (100% - 10%)) * = 36% * 62,5% = 22.5%\\n            // increase in supplyExchangePrice, assuming 100 as previous price.\\n            // 100 * 22,5% * 1/2 (half a year) = 0,1125.\\n            // cross-check supplyRawInterest worth = 80 * 1.1125 = 89. totalSupply worth = 89 + 20.\\n\\n            // -------------- 1. calculate ratioSupplyYield --------------------------------\\n            // step1: utilization * supplyRatio (or actually part of lenders receiving yield)\\n\\n            // temp_ => supplyRatio (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\\n            // if first bit 0 then ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\\n            // else ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\\n            temp_ = (exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_RATIO) & X15;\\n\\n            if (temp_ == 1) {\\n                // if no raw supply: no exchange price update needed\\n                // (if supplyRatio_ == 1 means there is only supplyInterestFree, as first bit is 1 and rest is 0)\\n                return (supplyExchangePrice_, borrowExchangePrice_);\\n            }\\n\\n            // ratioSupplyYield precision is 1e27 as 100% for increased precision when supplyInterestFree > supplyWithInterest\\n            if (temp_ & 1 == 1) {\\n                // ratio is supplyWithInterest / supplyInterestFree (supplyInterestFree is bigger)\\n                temp_ = temp_ >> 1;\\n\\n                // Note: case where temp_ == 0 (only supplyInterestFree, no yield) already covered by early return\\n                // in the if statement a little above.\\n\\n                // based on above example but supplyRawInterest is 20, supplyInterestFree is 80. no fee.\\n                // supplyRawInterest must become worth 30. totalSupply must become 110.\\n                // supplyExchangePrice would have to go from 1 to 1,5. borrowExchangePrice from 1 to 1,2.\\n                // so ratioSupplyYield must come out as 2.5 (250%).\\n                // supplyRatio would be (20 * 10_000 / 80) = 2500. but must be inverted.\\n                temp_ = (1e27 * FOUR_DECIMALS) / temp_; // e.g. 1e31 / 2500 = 4e27. (* 1e27 for precision)\\n                // e.g. 5_000 * (1e27 + 4e27) / 1e27 = 25_000 (=250%).\\n                temp_ =\\n                    // utilization * (100% + 100% / supplyRatio)\\n                    (((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) *\\n                        (1e27 + temp_)) / // extract utilization (max 16_383 so there is no way this can overflow).\\n                    (FOUR_DECIMALS);\\n                // max possible value of temp_ here is 16383 * (1e27 + 1e31) / 1e4 = ~1.64e31\\n            } else {\\n                // ratio is supplyInterestFree / supplyWithInterest (supplyWithInterest is bigger)\\n                temp_ = temp_ >> 1;\\n                // if temp_ == 0 then only supplyWithInterest => full yield. temp_ is already 0\\n\\n                // e.g. 5_000 * 10_000 + (20 * 10_000 / 80) / 10_000 = 5000 * 12500 / 10000 = 6250 (=62.5%).\\n                temp_ =\\n                    // 1e27 * utilization * (100% + supplyRatio) / 100%\\n                    (1e27 *\\n                        ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) & X14) * // extract utilization (max 16_383 so there is no way this can overflow).\\n                        (FOUR_DECIMALS + temp_)) /\\n                    (FOUR_DECIMALS * FOUR_DECIMALS);\\n                // max possible temp_ value: 1e27 * 16383 * 2e4 / 1e8 = 3.2766e27\\n            }\\n            // from here temp_ => ratioSupplyYield (utilization * supplyRatio part) scaled by 1e27. max possible value ~1.64e31\\n\\n            // step2 of ratioSupplyYield: add borrowRatio (only x% of borrowers paying yield)\\n            if (borrowRatio_ & 1 == 1) {\\n                // ratio is borrowWithInterest / borrowInterestFree (borrowInterestFree is bigger)\\n                borrowRatio_ = borrowRatio_ >> 1;\\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n\\n                // Note: case where borrowRatio_ == 0 (only borrowInterestFree, no yield) already covered\\n                // at the beginning of the method by early return if `borrowRatio_ == 1`.\\n\\n                // based on above example but borrowRawInterest is 10, borrowInterestFree is 50. no fee. borrowRatio = 20%.\\n                // so only 16.66% of borrowers are paying yield. so the 100% - part of the formula is not needed.\\n                // x of borrowers paying yield = (borrowRatio / (100 + borrowRatio)) = 16.6666666%\\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n                borrowRatio_ = (borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_);\\n                // max value here for borrowRatio_ is (1e31 / (1e4 + 1e4))= 5e26 (= 50% of borrowers paying yield).\\n            } else {\\n                // ratio is borrowInterestFree / borrowWithInterest (borrowWithInterest is bigger)\\n                borrowRatio_ = borrowRatio_ >> 1;\\n\\n                // borrowRatio_ => x of total bororwers paying yield. scale to 1e27.\\n                // x of borrowers paying yield = 100% - (borrowRatio / (100 + borrowRatio)) = 100% - 16.6666666% = 83,333%.\\n                borrowRatio_ = (1e27 - ((borrowRatio_ * 1e27) / (FOUR_DECIMALS + borrowRatio_)));\\n                // borrowRatio can never be > 100%. so max subtraction can be 100% - 100% / 200%.\\n                // or if borrowRatio_ is 0 -> 100% - 0. or if borrowRatio_ is 1 -> 100% - 1 / 101.\\n                // max value here for borrowRatio_ is 1e27 - 0 = 1e27 (= 100% of borrowers paying yield).\\n            }\\n\\n            // temp_ => ratioSupplyYield. scaled down from 1e25 = 1% each to normal percent precision 1e2 = 1%.\\n            // max nominator value is ~1.64e31 * 1e27 = 1.64e58. max result = 1.64e8\\n            temp_ = (FOUR_DECIMALS * temp_ * borrowRatio_) / 1e54;\\n\\n            // 2. calculate supply rate\\n            // temp_ => supply rate (borrow rate  - revenueFee%) * ratioSupplyYield.\\n            // division part is done in next step to increase precision. (divided by 2x FOUR_DECIMALS, fee + borrowRate)\\n            // Note that all calculation divisions for supplyExchangePrice are rounded down.\\n            // Note supply rate can be bigger than the borrowRate, e.g. if there are only few lenders with interest\\n            // but more suppliers not earning interest.\\n            temp_ = ((exchangePricesAndConfig_ & X16) * // borrow rate\\n                temp_ * // ratioSupplyYield\\n                (FOUR_DECIMALS - ((exchangePricesAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14))); // revenueFee\\n            // fee can not be > 100%. max possible = 65535 * ~1.64e8 * 1e4 =~1.074774e17.\\n\\n            // 3. calculate increase in supply exchange price\\n            supplyExchangePrice_ += ((supplyExchangePrice_ * temp_ * secondsSinceLastUpdate_) /\\n                (SECONDS_PER_YEAR * FOUR_DECIMALS * FOUR_DECIMALS * FOUR_DECIMALS));\\n            // max possible nominator = max uint 64 * 1.074774e17 * max uint32 = ~8.52e45. Denominator can not be 0.\\n        }\\n    }\\n\\n    ///////////////////////////////////////////////////////////////////////////\\n    //////////                     CALC REVENUE                       /////////\\n    ///////////////////////////////////////////////////////////////////////////\\n\\n    /// @dev gets the `revenueAmount_` for a token given its' totalAmounts and exchangePricesAndConfig from storage\\n    /// and the current balance of the Fluid liquidity contract for the token.\\n    /// @param totalAmounts_ total amounts packed uint256 read from storage\\n    /// @param exchangePricesAndConfig_ exchange prices and config packed uint256 read from storage\\n    /// @param liquidityTokenBalance_   current balance of Liquidity contract (IERC20(token_).balanceOf(address(this)))\\n    /// @return revenueAmount_ collectable revenue amount\\n    function calcRevenue(\\n        uint256 totalAmounts_,\\n        uint256 exchangePricesAndConfig_,\\n        uint256 liquidityTokenBalance_\\n    ) internal view returns (uint256 revenueAmount_) {\\n        // @dev no need to super-optimize this method as it is only used by admin\\n\\n        // calculate the new exchange prices based on earned interest\\n        (uint256 supplyExchangePrice_, uint256 borrowExchangePrice_) = calcExchangePrices(exchangePricesAndConfig_);\\n\\n        // total supply = interest free + with interest converted from raw\\n        uint256 totalSupply_ = getTotalSupply(totalAmounts_, supplyExchangePrice_);\\n\\n        if (totalSupply_ > 0) {\\n            // available revenue: balanceOf(token) + totalBorrowings - totalLendings.\\n            revenueAmount_ = liquidityTokenBalance_ + getTotalBorrow(totalAmounts_, borrowExchangePrice_);\\n            // ensure there is no possible case because of rounding etc. where this would revert,\\n            // explicitly check if >\\n            revenueAmount_ = revenueAmount_ > totalSupply_ ? revenueAmount_ - totalSupply_ : 0;\\n            // Note: if utilization > 100% (totalSupply < totalBorrow), then all the amount above 100% utilization\\n            // can only be revenue.\\n        } else {\\n            // if supply is 0, then rest of balance can be withdrawn as revenue so that no amounts get stuck\\n            revenueAmount_ = liquidityTokenBalance_;\\n        }\\n    }\\n\\n    ///////////////////////////////////////////////////////////////////////////\\n    //////////                      CALC LIMITS                       /////////\\n    ///////////////////////////////////////////////////////////////////////////\\n\\n    /// @dev calculates withdrawal limit before an operate execution:\\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n    /// @param userSupplyData_ user supply data packed uint256 from storage\\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and converted from BigMath\\n    /// @return currentWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction.\\n    ///         returned value is in raw for with interest mode, normal amount for interest free mode!\\n    function calcWithdrawalLimitBeforeOperate(\\n        uint256 userSupplyData_,\\n        uint256 userSupply_\\n    ) internal view returns (uint256 currentWithdrawalLimit_) {\\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet).\\n        // first tx where timestamp is 0 will enter `if (lastWithdrawalLimit_ == 0)` because lastWithdrawalLimit_ is not set yet.\\n        // returning max withdrawal allowed, which is not exactly right but doesn't matter because the first interaction must be\\n        // a deposit anyway. Important is that it would not revert.\\n\\n        // Note the first time a deposit brings the user supply amount to above the base withdrawal limit, the active limit\\n        // is the fully expanded limit immediately.\\n\\n        // extract last set withdrawal limit\\n        uint256 lastWithdrawalLimit_ = (userSupplyData_ >>\\n            LiquiditySlotsLink.BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT) & X64;\\n        lastWithdrawalLimit_ =\\n            (lastWithdrawalLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n            (lastWithdrawalLimit_ & DEFAULT_EXPONENT_MASK);\\n        if (lastWithdrawalLimit_ == 0) {\\n            // withdrawal limit is not activated. Max withdrawal allowed\\n            return 0;\\n        }\\n\\n        uint256 maxWithdrawableLimit_;\\n        uint256 temp_;\\n        unchecked {\\n            // extract max withdrawable percent of user supply and\\n            // calculate maximum withdrawable amount expandPercentage of user supply at full expansion duration elapsed\\n            // e.g.: if 10% expandPercentage, meaning 10% is withdrawable after full expandDuration has elapsed.\\n\\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            maxWithdrawableLimit_ =\\n                (((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14) * userSupply_) /\\n                FOUR_DECIMALS;\\n\\n            // time elapsed since last withdrawal limit was set (in seconds)\\n            // @dev last process timestamp is guaranteed to exist for withdrawal, as a supply must have happened before.\\n            // last timestamp can not be > current timestamp\\n            temp_ =\\n                block.timestamp -\\n                ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP) & X33);\\n        }\\n        // calculate withdrawable amount of expandPercent that is elapsed of expandDuration.\\n        // e.g. if 60% of expandDuration has elapsed, then user should be able to withdraw 6% of user supply, down to 94%.\\n        // Note: no explicit check for this needed, it is covered by setting minWithdrawalLimit_ if needed.\\n        temp_ =\\n            (maxWithdrawableLimit_ * temp_) /\\n            // extract expand duration: After this, decrement won't happen (user can withdraw 100% of withdraw limit)\\n            ((userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_DURATION) & X24); // expand duration can never be 0\\n        // calculate expanded withdrawal limit: last withdrawal limit - withdrawable amount.\\n        // Note: withdrawable amount here can grow bigger than userSupply if timeElapsed is a lot bigger than expandDuration,\\n        // which would cause the subtraction `lastWithdrawalLimit_ - withdrawableAmount_` to revert. In that case, set 0\\n        // which will cause minimum (fully expanded) withdrawal limit to be set in lines below.\\n        unchecked {\\n            // underflow explicitly checked & handled\\n            currentWithdrawalLimit_ = lastWithdrawalLimit_ > temp_ ? lastWithdrawalLimit_ - temp_ : 0;\\n            // calculate minimum withdrawal limit: minimum amount of user supply that must stay supplied at full expansion.\\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n            temp_ = userSupply_ - maxWithdrawableLimit_;\\n        }\\n        // if withdrawal limit is decreased below minimum then set minimum\\n        // (e.g. when more than expandDuration time has elapsed)\\n        if (temp_ > currentWithdrawalLimit_) {\\n            currentWithdrawalLimit_ = temp_;\\n        }\\n    }\\n\\n    /// @dev calculates withdrawal limit after an operate execution:\\n    /// amount of user supply that must stay supplied (not amount that can be withdrawn).\\n    /// i.e. if user has supplied 100m and can withdraw 5M, this method returns the 95M, not the withdrawable amount 5M\\n    /// @param userSupplyData_ user supply data packed uint256 from storage\\n    /// @param userSupply_ current user supply amount already extracted from `userSupplyData_` and added / subtracted with the executed operate amount\\n    /// @param newWithdrawalLimit_ current withdrawal limit updated for expansion since last interaction, result from `calcWithdrawalLimitBeforeOperate`\\n    /// @return withdrawalLimit_ updated withdrawal limit that should be written to storage. returned value is in\\n    ///                          raw for with interest mode, normal amount for interest free mode!\\n    function calcWithdrawalLimitAfterOperate(\\n        uint256 userSupplyData_,\\n        uint256 userSupply_,\\n        uint256 newWithdrawalLimit_\\n    ) internal pure returns (uint256) {\\n        // temp_ => base withdrawal limit. below this, maximum withdrawals are allowed\\n        uint256 temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        // if user supply is below base limit then max withdrawals are allowed\\n        if (userSupply_ < temp_) {\\n            return 0;\\n        }\\n        // temp_ => withdrawal limit expandPercent (is in 1e2 decimals)\\n        temp_ = (userSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_EXPAND_PERCENT) & X14;\\n        unchecked {\\n            // temp_ => minimum withdrawal limit: userSupply - max withdrawable limit (userSupply * expandPercent))\\n            // userSupply_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            // subtraction can not underflow as maxWithdrawableLimit_ is a percentage amount (<=100%) of userSupply_\\n            temp_ = userSupply_ - ((userSupply_ * temp_) / FOUR_DECIMALS);\\n        }\\n        // if new (before operation) withdrawal limit is less than minimum limit then set minimum limit.\\n        // e.g. can happen on new deposits. withdrawal limit is instantly fully expanded in a scenario where\\n        // increased deposit amount outpaces withrawals.\\n        if (temp_ > newWithdrawalLimit_) {\\n            return temp_;\\n        }\\n        return newWithdrawalLimit_;\\n    }\\n\\n    /// @dev calculates borrow limit before an operate execution:\\n    /// total amount user borrow can reach (not borrowable amount in current operation).\\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_`\\n    /// @return currentBorrowLimit_ current borrow limit updated for expansion since last interaction. returned value is in\\n    ///                             raw for with interest mode, normal amount for interest free mode!\\n    function calcBorrowLimitBeforeOperate(\\n        uint256 userBorrowData_,\\n        uint256 userBorrow_\\n    ) internal view returns (uint256 currentBorrowLimit_) {\\n        // @dev must support handling the case where timestamp is 0 (config is set but no interactions yet) -> base limit.\\n        // first tx where timestamp is 0 will enter `if (maxExpandedBorrowLimit_ < baseBorrowLimit_)` because `userBorrow_` and thus\\n        // `maxExpansionLimit_` and thus `maxExpandedBorrowLimit_` is 0 and `baseBorrowLimit_` can not be 0.\\n\\n        // temp_ = extract borrow expand percent (is in 1e2 decimals)\\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14;\\n\\n        uint256 maxExpansionLimit_;\\n        uint256 maxExpandedBorrowLimit_;\\n        unchecked {\\n            // calculate max expansion limit: Max amount limit can expand to since last interaction\\n            // userBorrow_ needs to be atleast 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            maxExpansionLimit_ = ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n\\n            // calculate max borrow limit: Max point limit can increase to since last interaction\\n            maxExpandedBorrowLimit_ = userBorrow_ + maxExpansionLimit_;\\n        }\\n\\n        // currentBorrowLimit_ = extract base borrow limit\\n        currentBorrowLimit_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n        currentBorrowLimit_ =\\n            (currentBorrowLimit_ >> DEFAULT_EXPONENT_SIZE) <<\\n            (currentBorrowLimit_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (maxExpandedBorrowLimit_ < currentBorrowLimit_) {\\n            return currentBorrowLimit_;\\n        }\\n        // time elapsed since last borrow limit was set (in seconds)\\n        unchecked {\\n            // temp_ = timeElapsed_ (last timestamp can not be > current timestamp)\\n            temp_ =\\n                block.timestamp -\\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP) & X33); // extract last update timestamp\\n        }\\n\\n        // currentBorrowLimit_ = expandedBorrowableAmount + extract last set borrow limit\\n        currentBorrowLimit_ =\\n            // calculate borrow limit expansion since last interaction for `expandPercent` that is elapsed of `expandDuration`.\\n            // divisor is extract expand duration (after this, full expansion to expandPercentage happened).\\n            ((maxExpansionLimit_ * temp_) /\\n                ((userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_DURATION) & X24)) + // expand duration can never be 0\\n            //  extract last set borrow limit\\n            BigMathMinified.fromBigNumber(\\n                (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT) & X64,\\n                DEFAULT_EXPONENT_SIZE,\\n                DEFAULT_EXPONENT_MASK\\n            );\\n\\n        // if timeElapsed is bigger than expandDuration, new borrow limit would be > max expansion,\\n        // so set to `maxExpandedBorrowLimit_` in that case.\\n        // also covers the case where last process timestamp = 0 (timeElapsed would simply be very big)\\n        if (currentBorrowLimit_ > maxExpandedBorrowLimit_) {\\n            currentBorrowLimit_ = maxExpandedBorrowLimit_;\\n        }\\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (currentBorrowLimit_ > temp_) {\\n            currentBorrowLimit_ = temp_;\\n        }\\n    }\\n\\n    /// @dev calculates borrow limit after an operate execution:\\n    /// total amount user borrow can reach (not borrowable amount in current operation).\\n    /// i.e. if user has borrowed 50M and can still borrow 5M, this method returns the total 55M, not the borrowable amount 5M\\n    /// @param userBorrowData_ user borrow data packed uint256 from storage\\n    /// @param userBorrow_ current user borrow amount already extracted from `userBorrowData_` and added / subtracted with the executed operate amount\\n    /// @param newBorrowLimit_ current borrow limit updated for expansion since last interaction, result from `calcBorrowLimitBeforeOperate`\\n    /// @return borrowLimit_ updated borrow limit that should be written to storage.\\n    ///                      returned value is in raw for with interest mode, normal amount for interest free mode!\\n    function calcBorrowLimitAfterOperate(\\n        uint256 userBorrowData_,\\n        uint256 userBorrow_,\\n        uint256 newBorrowLimit_\\n    ) internal pure returns (uint256 borrowLimit_) {\\n        // temp_ = extract borrow expand percent\\n        uint256 temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_EXPAND_PERCENT) & X14; // (is in 1e2 decimals)\\n\\n        unchecked {\\n            // borrowLimit_ = calculate maximum borrow limit at full expansion.\\n            // userBorrow_ needs to be at least 1e73 to overflow max limit of ~1e77 in uint256 (no token in existence where this is possible).\\n            borrowLimit_ = userBorrow_ + ((userBorrow_ * temp_) / FOUR_DECIMALS);\\n        }\\n\\n        // temp_ = extract base borrow limit\\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_BASE_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (borrowLimit_ < temp_) {\\n            // below base limit, borrow limit is always base limit\\n            return temp_;\\n        }\\n        // temp_ = extract hard max borrow limit. Above this user can never borrow (not expandable above)\\n        temp_ = (userBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_MAX_BORROW_LIMIT) & X18;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n        // make sure fully expanded borrow limit is not above hard max borrow limit\\n        if (borrowLimit_ > temp_) {\\n            borrowLimit_ = temp_;\\n        }\\n        // if new borrow limit (from before operate) is > max borrow limit, set max borrow limit.\\n        // (e.g. on a repay shrinking instantly to fully expanded borrow limit from new borrow amount. shrinking is instant)\\n        if (newBorrowLimit_ > borrowLimit_) {\\n            return borrowLimit_;\\n        }\\n        return newBorrowLimit_;\\n    }\\n\\n    ///////////////////////////////////////////////////////////////////////////\\n    //////////                      CALC RATES                        /////////\\n    ///////////////////////////////////////////////////////////////////////////\\n\\n    /// @dev Calculates new borrow rate from utilization for a token\\n    /// @param rateData_ rate data packed uint256 from storage for the token\\n    /// @param utilization_ totalBorrow / totalSupply. 1e4 = 100% utilization\\n    /// @return rate_ rate for that particular token in 1e2 precision (e.g. 5% rate = 500)\\n    function calcBorrowRateFromUtilization(uint256 rateData_, uint256 utilization_) internal returns (uint256 rate_) {\\n        // extract rate version: 4 bits (0xF) starting from bit 0\\n        uint256 rateVersion_ = (rateData_ & 0xF);\\n\\n        if (rateVersion_ == 1) {\\n            rate_ = calcRateV1(rateData_, utilization_);\\n        } else if (rateVersion_ == 2) {\\n            rate_ = calcRateV2(rateData_, utilization_);\\n        } else {\\n            revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__UnsupportedRateVersion);\\n        }\\n\\n        if (rate_ > X16) {\\n            // hard cap for borrow rate at maximum value 16 bits (65535) to make sure it does not overflow storage space.\\n            // this is unlikely to ever happen if configs stay within expected levels.\\n            rate_ = X16;\\n            // emit event to more easily become aware\\n            emit BorrowRateMaxCap();\\n        }\\n    }\\n\\n    /// @dev calculates the borrow rate based on utilization for rate data version 1 (with one kink) in 1e2 precision\\n    /// @param rateData_ rate data packed uint256 from storage for the token\\n    /// @param utilization_  in 1e2 (100% = 1e4)\\n    /// @return rate_ rate in 1e2 precision\\n    function calcRateV1(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\\n        /// For rate v1 (one kink) ------------------------------------------------------\\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  52- 67 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Last 188 bits =>  68-255 => blank, might come in use in future\\n\\n        // y = mx + c.\\n        // y is borrow rate\\n        // x is utilization\\n        // m = slope (m can also be negative for declining rates)\\n        // c is constant (c can be negative)\\n\\n        uint256 y1_;\\n        uint256 y2_;\\n        uint256 x1_;\\n        uint256 x2_;\\n\\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_UTILIZATION_AT_KINK) & X16;\\n        if (utilization_ < kink1_) {\\n            // if utilization is less than kink\\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO) & X16;\\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\\n            x1_ = 0; // 0%\\n            x2_ = kink1_;\\n        } else {\\n            // else utilization is greater than kink\\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK) & X16;\\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX) & X16;\\n            x1_ = kink1_;\\n            x2_ = FOUR_DECIMALS; // 100%\\n        }\\n\\n        int256 constant_;\\n        int256 slope_;\\n        unchecked {\\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\\n\\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\\n\\n            // calculating new borrow rate\\n            // - slope_ max value is 65535 * 1e12,\\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\\n            // - constant max value is 65535 * 1e12\\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\\n            // divisor TWELVE_DECIMALS can not be 0\\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\\n            if (slope_ < 0) {\\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\\n            }\\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\\n        }\\n    }\\n\\n    /// @dev calculates the borrow rate based on utilization for rate data version 2 (with two kinks) in 1e4 precision\\n    /// @param rateData_ rate data packed uint256 from storage for the token\\n    /// @param utilization_  in 1e2 (100% = 1e4)\\n    /// @return rate_ rate in 1e4 precision\\n    function calcRateV2(uint256 rateData_, uint256 utilization_) internal pure returns (uint256 rate_) {\\n        /// For rate v2 (two kinks) -----------------------------------------------------\\n        /// Next 16  bits =>  4 - 19 => Rate at utilization 0% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  20- 35 => Utilization at kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  36- 51 => Rate at utilization kink1 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  52- 67 => Utilization at kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  68- 83 => Rate at utilization kink2 (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Next 16  bits =>  84- 99 => Rate at utilization 100% (in 1e2: 100% = 10_000; 1% = 100 -> max value 65535)\\n        /// Last 156 bits => 100-255 => blank, might come in use in future\\n\\n        // y = mx + c.\\n        // y is borrow rate\\n        // x is utilization\\n        // m = slope (m can also be negative for declining rates)\\n        // c is constant (c can be negative)\\n\\n        uint256 y1_;\\n        uint256 y2_;\\n        uint256 x1_;\\n        uint256 x2_;\\n\\n        // extract kink1: 16 bits (0xFFFF) starting from bit 20\\n        // kink is in 1e2, same as utilization, so no conversion needed for direct comparison of the two\\n        uint256 kink1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1) & X16;\\n        if (utilization_ < kink1_) {\\n            // if utilization is less than kink1\\n            y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO) & X16;\\n            y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\\n            x1_ = 0; // 0%\\n            x2_ = kink1_;\\n        } else {\\n            // extract kink2: 16 bits (0xFFFF) starting from bit 52\\n            uint256 kink2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2) & X16;\\n            if (utilization_ < kink2_) {\\n                // if utilization is less than kink2\\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1) & X16;\\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\\n                x1_ = kink1_;\\n                x2_ = kink2_;\\n            } else {\\n                // else utilization is greater than kink2\\n                y1_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2) & X16;\\n                y2_ = (rateData_ >> LiquiditySlotsLink.BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX) & X16;\\n                x1_ = kink2_;\\n                x2_ = FOUR_DECIMALS;\\n            }\\n        }\\n\\n        int256 constant_;\\n        int256 slope_;\\n        unchecked {\\n            // calculating slope with twelve decimal precision. m = (y2 - y1) / (x2 - x1).\\n            // utilization of x2 can not be <= utilization of x1 (so no underflow or 0 divisor)\\n            // y is in 1e2 so can not overflow when multiplied with TWELVE_DECIMALS\\n            slope_ = (int256(y2_ - y1_) * int256(TWELVE_DECIMALS)) / int256((x2_ - x1_));\\n\\n            // calculating constant at 12 decimal precision. slope is already in 12 decimal hence only multiple with y1. c = y - mx.\\n            // maximum y1_ value is 65535. 65535 * 1e12 can not overflow int256\\n            // maximum slope is 65535 - 0 * TWELVE_DECIMALS / 1 = 65535 * 1e12;\\n            // maximum x1_ is 100% (9_999 actually) => slope_ * x1_ can not overflow int256\\n            // subtraction most extreme case would be  0 - max value slope_ * x1_ => can not underflow int256\\n            constant_ = int256(y1_ * TWELVE_DECIMALS) - (slope_ * int256(x1_));\\n\\n            // calculating new borrow rate\\n            // - slope_ max value is 65535 * 1e12,\\n            // - utilization max value is let's say 500% (extreme case where borrow rate increases borrow amount without new supply)\\n            // - constant max value is 65535 * 1e12\\n            // so max values are 65535 * 1e12 * 50_000 + 65535 * 1e12 -> 3.2768*10^21, which easily fits int256\\n            // divisor TWELVE_DECIMALS can not be 0\\n            slope_ = (slope_ * int256(utilization_)) + constant_; // reusing `slope_` as variable for gas savings\\n            if (slope_ < 0) {\\n                revert FluidLiquidityCalcsError(ErrorTypes.LiquidityCalcs__BorrowRateNegative);\\n            }\\n            rate_ = uint256(slope_) / TWELVE_DECIMALS;\\n        }\\n    }\\n\\n    /// @dev reads the total supply out of Liquidity packed storage `totalAmounts_` for `supplyExchangePrice_`\\n    function getTotalSupply(\\n        uint256 totalAmounts_,\\n        uint256 supplyExchangePrice_\\n    ) internal pure returns (uint256 totalSupply_) {\\n        // totalSupply_ => supplyInterestFree\\n        totalSupply_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE) & X64;\\n        totalSupply_ = (totalSupply_ >> DEFAULT_EXPONENT_SIZE) << (totalSupply_ & DEFAULT_EXPONENT_MASK);\\n\\n        uint256 totalSupplyRaw_ = totalAmounts_ & X64; // no shifting as supplyRaw is first 64 bits\\n        totalSupplyRaw_ = (totalSupplyRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalSupplyRaw_ & DEFAULT_EXPONENT_MASK);\\n\\n        // totalSupply = supplyInterestFree + supplyRawInterest normalized from raw\\n        totalSupply_ += ((totalSupplyRaw_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION);\\n    }\\n\\n    /// @dev reads the total borrow out of Liquidity packed storage `totalAmounts_` for `borrowExchangePrice_`\\n    function getTotalBorrow(\\n        uint256 totalAmounts_,\\n        uint256 borrowExchangePrice_\\n    ) internal pure returns (uint256 totalBorrow_) {\\n        // totalBorrow_ => borrowInterestFree\\n        // no & mask needed for borrow interest free as it occupies the last bits in the storage slot\\n        totalBorrow_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE);\\n        totalBorrow_ = (totalBorrow_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrow_ & DEFAULT_EXPONENT_MASK);\\n\\n        uint256 totalBorrowRaw_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) & X64;\\n        totalBorrowRaw_ = (totalBorrowRaw_ >> DEFAULT_EXPONENT_SIZE) << (totalBorrowRaw_ & DEFAULT_EXPONENT_MASK);\\n\\n        // totalBorrow = borrowInterestFree + borrowRawInterest normalized from raw\\n        totalBorrow_ += ((totalBorrowRaw_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION);\\n    }\\n}\\n\",\"keccak256\":\"0xa65e2f84b2c33769ceb6b28fbd3221be29da2f8ac96e4d8b8cea91948d81a707\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/liquiditySlotsLink.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\\nlibrary LiquiditySlotsLink {\\n    /// @dev storage slot for status at Liquidity\\n    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\\n    /// @dev storage slot for auths mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\\n    /// @dev storage slot for guardians mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\\n    /// @dev storage slot for user class mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\\n    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\\n    /// @dev storage slot for rateData mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\\n    /// @dev storage slot for totalAmounts mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\\n    /// @dev storage slot for user supply double mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\\n    /// @dev storage slot for user borrow double mapping at Liquidity\\n    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\\n    /// @dev storage slot for listed tokens array at Liquidity\\n    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\\n    /// @dev storage slot for listed tokens array at Liquidity\\n    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\\n\\n    // --------------------------------\\n    // @dev stacked uint256 storage slots bits position data for each:\\n\\n    // ExchangePricesAndConfig\\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\\n    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\\n\\n    // RateData:\\n    uint256 internal constant BITS_RATE_DATA_VERSION = 0;\\n    // RateData: V1\\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\\n    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\\n    // RateData: V2\\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\\n\\n    // TotalAmounts\\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\\n\\n    // UserSupplyData\\n    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\\n    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\\n\\n    // UserBorrowData\\n    uint256 internal constant BITS_USER_BORROW_MODE = 0;\\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\\n    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\\n\\n    // Configs2\\n    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\\n\\n    // --------------------------------\\n\\n    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\\n        return keccak256(abi.encode(key_, slot_));\\n    }\\n\\n    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\\n    function calculateDoubleMappingStorageSlot(\\n        uint256 slot_,\\n        address key1_,\\n        address key2_\\n    ) internal pure returns (bytes32) {\\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\\n        return keccak256(abi.encode(key2_, intermediateSlot_));\\n    }\\n}\\n\",\"keccak256\":\"0x0ae3e1d231bb6c14b54fc1f5ffa306edc0ac827a6a92279c77c0c09627fe08ae\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/safeTransfer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT OR Apache-2.0\\npragma solidity 0.8.21;\\n\\nimport { LibsErrorTypes as ErrorTypes } from \\\"./errorTypes.sol\\\";\\n\\n/// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom\\nlibrary SafeTransfer {\\n    uint256 internal constant MAX_NATIVE_TRANSFER_GAS = 20000; // pass max. 20k gas for native transfers\\n\\n    error FluidSafeTransferError(uint256 errorId_);\\n\\n    /// @dev Transfer `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    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63\\n    function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal {\\n        bool success_;\\n\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Get a pointer to some free memory.\\n            let freeMemoryPointer := mload(0x40)\\n\\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n            mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \\\"from_\\\" argument.\\n            mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \\\"to_\\\" argument.\\n            mstore(add(freeMemoryPointer, 68), amount_) // Append the \\\"amount_\\\" argument. Masking not required as it's a full 32 byte type.\\n\\n            success_ := and(\\n                // Set success to whether the call reverted, if not we check it either\\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n                // Counterintuitively, this call must be positioned second to the or() call in the\\n                // surrounding and() call or else returndatasize() will be zero during the computation.\\n                call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32)\\n            )\\n        }\\n\\n        if (!success_) {\\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed);\\n        }\\n    }\\n\\n    /// @dev Transfer `amount_` of `token_` to `to_`.\\n    /// If `token_` returns no value, non-reverting calls are assumed to be successful.\\n    /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error):\\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95\\n    function safeTransfer(address token_, address to_, uint256 amount_) internal {\\n        bool success_;\\n\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Get a pointer to some free memory.\\n            let freeMemoryPointer := mload(0x40)\\n\\n            // Write the abi-encoded calldata into memory, beginning with the function selector.\\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n            mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the \\\"to_\\\" argument.\\n            mstore(add(freeMemoryPointer, 36), amount_) // Append the \\\"amount_\\\" argument. Masking not required as it's a full 32 byte type.\\n\\n            success_ := and(\\n                // Set success to whether the call reverted, if not we check it either\\n                // returned exactly 1 (can't just be non-zero data), or had no return data.\\n                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n                // Counterintuitively, this call must be positioned second to the or() call in the\\n                // surrounding and() call or else returndatasize() will be zero during the computation.\\n                call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32)\\n            )\\n        }\\n\\n        if (!success_) {\\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\\n        }\\n    }\\n\\n    /// @dev Transfer `amount_` of ` native token to `to_`.\\n    /// Minimally modified from Solmate SafeTransferLib (Custom Error):\\n    /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L15-L25\\n    function safeTransferNative(address to_, uint256 amount_) internal {\\n        bool success_;\\n\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Transfer the ETH and store if it succeeded or not. Pass limited gas\\n            success_ := call(MAX_NATIVE_TRANSFER_GAS, to_, amount_, 0, 0, 0, 0)\\n        }\\n\\n        if (!success_) {\\n            revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x7f7d3a39d984c62e41c669a3d11deb899b3512ace9313263592575bf48a6e079\",\"license\":\"MIT OR Apache-2.0\"},\"contracts/libraries/storageRead.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\n/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.\\ncontract StorageRead {\\n    function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {\\n        assembly {\\n            result_ := sload(slot_) // read value from the storage slot\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x1b03dfe294c2f0376f7e34c3960fe7088d7ff44bb2ffd9cb2ac940486bfba8c9\",\"license\":\"BUSL-1.1\"},\"contracts/liquidity/adminModule/structs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nabstract contract Structs {\\n    struct AddressBool {\\n        address addr;\\n        bool value;\\n    }\\n\\n    struct AddressUint256 {\\n        address addr;\\n        uint256 value;\\n    }\\n\\n    /// @notice struct to set borrow rate data for version 1\\n    struct RateDataV1Params {\\n        ///\\n        /// @param token for rate data\\n        address token;\\n        ///\\n        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\\n        uint256 kink;\\n        ///\\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\\n        /// i.e. constant minimum borrow rate\\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\\n        uint256 rateAtUtilizationZero;\\n        ///\\n        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\\n        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\\n        uint256 rateAtUtilizationKink;\\n        ///\\n        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\\n        uint256 rateAtUtilizationMax;\\n    }\\n\\n    /// @notice struct to set borrow rate data for version 2\\n    struct RateDataV2Params {\\n        ///\\n        /// @param token for rate data\\n        address token;\\n        ///\\n        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\\n        uint256 kink1;\\n        ///\\n        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\\n        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\\n        uint256 kink2;\\n        ///\\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\\n        /// i.e. constant minimum borrow rate\\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\\n        uint256 rateAtUtilizationZero;\\n        ///\\n        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\\n        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\\n        uint256 rateAtUtilizationKink1;\\n        ///\\n        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\\n        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\\n        uint256 rateAtUtilizationKink2;\\n        ///\\n        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\\n        uint256 rateAtUtilizationMax;\\n    }\\n\\n    /// @notice struct to set token config\\n    struct TokenConfig {\\n        ///\\n        /// @param token address\\n        address token;\\n        ///\\n        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\\n        uint256 fee;\\n        ///\\n        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\\n        uint256 threshold;\\n        ///\\n        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\\n        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).\\n        uint256 maxUtilization;\\n    }\\n\\n    /// @notice struct to set user supply & withdrawal config\\n    struct UserSupplyConfig {\\n        ///\\n        /// @param user address\\n        address user;\\n        ///\\n        /// @param token address\\n        address token;\\n        ///\\n        /// @param mode: 0 = without interest. 1 = with interest\\n        uint8 mode;\\n        ///\\n        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\\n        /// Also used to calculate rate at which withdrawal limit should decrease (instant).\\n        uint256 expandPercent;\\n        ///\\n        /// @param expandDuration withdrawal limit expand duration in seconds.\\n        /// used to calculate rate together with expandPercent\\n        uint256 expandDuration;\\n        ///\\n        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n        /// with interest -> raw, without interest -> normal\\n        uint256 baseWithdrawalLimit;\\n    }\\n\\n    /// @notice struct to set user borrow & payback config\\n    struct UserBorrowConfig {\\n        ///\\n        /// @param user address\\n        address user;\\n        ///\\n        /// @param token address\\n        address token;\\n        ///\\n        /// @param mode: 0 = without interest. 1 = with interest\\n        uint8 mode;\\n        ///\\n        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\\n        /// Also used to calculate rate at which debt limit should decrease (instant).\\n        uint256 expandPercent;\\n        ///\\n        /// @param expandDuration debt limit expand duration in seconds.\\n        /// used to calculate rate together with expandPercent\\n        uint256 expandDuration;\\n        ///\\n        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\\n        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n        /// with interest -> raw, without interest -> normal\\n        uint256 baseDebtCeiling;\\n        ///\\n        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\\n        /// with interest -> raw, without interest -> normal\\n        uint256 maxDebtCeiling;\\n    }\\n}\\n\",\"keccak256\":\"0x10353c70015f27b880125cefab806dbed24a4458f187da66964f3ef60488f757\",\"license\":\"BUSL-1.1\"},\"contracts/liquidity/interfaces/iLiquidity.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\nimport { IProxy } from \\\"../../infiniteProxy/interfaces/iProxy.sol\\\";\\nimport { Structs as AdminModuleStructs } from \\\"../adminModule/structs.sol\\\";\\n\\ninterface IFluidLiquidityAdmin {\\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\\n    /// @param authsStatus_ array of structs setting allowed status for an address.\\n    ///                     status true => add auth, false => remove auth\\n    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\\n\\n    /// @notice adds/removes guardians. Only callable by Governance.\\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\\n    ///                         status true => add guardian, false => remove guardian\\n    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\\n\\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\\n    /// @param revenueCollector_  new revenue collector address\\n    function updateRevenueCollector(address revenueCollector_) external;\\n\\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\\n    /// @param newStatus_ new status\\n    ///        status = 2 -> pause, status = 1 -> resume.\\n    function changeStatus(uint256 newStatus_) external;\\n\\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\\n    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\\n\\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\\n    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\\n\\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\\n    ///         Only callable by Auths.\\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\\n    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\\n\\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\\n    ///         Only callable by Auths.\\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\\n    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\\n\\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\\n    ///         Only callable by Auths.\\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\\n    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\\n\\n    /// @notice sets a new withdrawal limit as the current limit for a certain user\\n    /// @param user_ user address for which to update the withdrawal limit\\n    /// @param token_ token address for which to update the withdrawal limit\\n    /// @param newLimit_ new limit until which user supply can decrease to.\\n    ///                  Important: input in raw. Must account for exchange price in input param calculation.\\n    ///                  Note any limit that is < max expansion or > current user supply will set max expansion limit or\\n    ///                  current user supply as limit respectively.\\n    ///                  - set 0 to make maximum possible withdrawable: instant full expansion, and if that goes\\n    ///                  below base limit then fully down to 0.\\n    ///                  - set type(uint256).max to make current withdrawable 0 (sets current user supply as limit).\\n    function updateUserWithdrawalLimit(address user_, address token_, uint256 newLimit_) external;\\n\\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\\n    ///         Only callable by Auths.\\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\\n    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\\n\\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\\n    /// Only callable by Guardians.\\n    /// @param user_          address of user to pause operations for\\n    /// @param supplyTokens_  token addresses to pause withdrawals for\\n    /// @param borrowTokens_  token addresses to pause borrowings for\\n    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\\n\\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\\n    /// Only callable by Guardians.\\n    /// @param user_          address of user to unpause operations for\\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\\n    /// @param borrowTokens_  token addresses to unpause borrowings for\\n    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\\n\\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\\n    /// @param tokens_  array of tokens to collect revenue for\\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\\n    function collectRevenue(address[] calldata tokens_) external;\\n\\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\\n    /// @param tokens_ tokens to update exchange prices for\\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\\n    function updateExchangePrices(\\n        address[] calldata tokens_\\n    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\\n}\\n\\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\\n    /// @notice Single function which handles supply, withdraw, borrow & payback\\n    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\\n    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\\n    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\\n    /// @param withdrawTo_ if withdrawal then to which address\\n    /// @param borrowTo_ if borrow then to which address\\n    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\\n    /// @return memVar3_ updated supplyExchangePrice\\n    /// @return memVar4_ updated borrowExchangePrice\\n    /// @dev to trigger skipping in / out transfers (gas optimization):\\n    /// -  ` callbackData_` MUST be encoded so that \\\"from\\\" address is the last 20 bytes in the last 32 bytes slot,\\n    ///     also for native token operations where liquidityCallback is not triggered!\\n    ///     from address must come at last position if there is more data. I.e. encode like:\\n    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\\n    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\\n    /// -   this \\\"from\\\" address must match withdrawTo_ or borrowTo_ and must be == `msg.sender`\\n    /// -   `callbackData_` must in addition to the from address as described above include bytes32 SKIP_TRANSFERS\\n    ///     in the slot before (bytes 32 to 63)\\n    /// -   `msg.value` must be 0.\\n    /// -   Amounts must be either:\\n    ///     -  supply(+) == borrow(+), withdraw(-) == payback(-).\\n    ///     -  Liquidity must be on the winning side (deposit < borrow OR payback < withdraw).\\n    function operate(\\n        address token_,\\n        int256 supplyAmount_,\\n        int256 borrowAmount_,\\n        address withdrawTo_,\\n        address borrowTo_,\\n        bytes calldata callbackData_\\n    ) external payable returns (uint256 memVar3_, uint256 memVar4_);\\n}\\n\\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\\n\",\"keccak256\":\"0x4aa83e84baa7c2f4d58b07a3eca4ab7fe7d6fc660898daaac338dc3f129c4123\",\"license\":\"MIT\"},\"contracts/protocols/dex/error.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { Structs } from \\\"./poolT1/coreModule/structs.sol\\\";\\n\\nabstract contract Error {\\n    error FluidDexError(uint256 errorId_);\\n\\n    error FluidDexFactoryError(uint256 errorId);\\n\\n    /// @notice used to simulate swap to find the output amount\\n    error FluidDexSwapResult(uint256 amountOut);\\n\\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\\n\\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\\n\\n    error FluidDexLiquidityOutput(uint256 shares_);\\n\\n    error FluidDexPricesAndExchangeRates(Structs.PricesAndExchangePrice pex_);\\n}\\n\",\"keccak256\":\"0xfb70930e36c5c0d60e06fb1be8a6fffdfbc17d0ae9745582f4dda666e3b010aa\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/errorTypes.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nlibrary ErrorTypes {\\n    /***********************************|\\n    |             DexT1                 | \\n    |__________________________________*/\\n\\n    /// @notice thrown at reentrancy\\n    uint256 internal constant DexT1__AlreadyEntered = 51001;\\n\\n    uint256 internal constant DexT1__NotAnAuth = 51002;\\n\\n    uint256 internal constant DexT1__SmartColNotEnabled = 51003;\\n\\n    uint256 internal constant DexT1__SmartDebtNotEnabled = 51004;\\n\\n    uint256 internal constant DexT1__PoolNotInitialized = 51005;\\n\\n    uint256 internal constant DexT1__TokenReservesTooLow = 51006;\\n\\n    uint256 internal constant DexT1__EthAndAmountInMisMatch = 51007;\\n\\n    uint256 internal constant DexT1__EthSentForNonNativeSwap = 51008;\\n\\n    uint256 internal constant DexT1__NoSwapRoute = 51009;\\n\\n    uint256 internal constant DexT1__NotEnoughAmountOut = 51010;\\n\\n    uint256 internal constant DexT1__LiquidityLayerTokenUtilizationCapReached = 51011;\\n\\n    uint256 internal constant DexT1__HookReturnedFalse = 51012;\\n\\n    // Either user's config are not set or user is paused\\n    uint256 internal constant DexT1__UserSupplyInNotOn = 51013;\\n\\n    // Either user's config are not set or user is paused\\n    uint256 internal constant DexT1__UserDebtInNotOn = 51014;\\n\\n    // Thrown when contract asks for more token0 or token1 than what user's wants to give on deposit\\n    uint256 internal constant DexT1__AboveDepositMax = 51015;\\n\\n    uint256 internal constant DexT1__MsgValueLowOnDepositOrPayback = 51016;\\n\\n    uint256 internal constant DexT1__WithdrawLimitReached = 51017;\\n\\n    // Thrown when contract gives less token0 or token1 than what user's wants on withdraw\\n    uint256 internal constant DexT1__BelowWithdrawMin = 51018;\\n\\n    uint256 internal constant DexT1__DebtLimitReached = 51019;\\n\\n    // Thrown when contract gives less token0 or token1 than what user's wants on borrow\\n    uint256 internal constant DexT1__BelowBorrowMin = 51020;\\n\\n    // Thrown when contract asks for more token0 or token1 than what user's wants on payback\\n    uint256 internal constant DexT1__AbovePaybackMax = 51021;\\n\\n    uint256 internal constant DexT1__InvalidDepositAmts = 51022;\\n\\n    uint256 internal constant DexT1__DepositAmtsZero = 51023;\\n\\n    uint256 internal constant DexT1__SharesMintedLess = 51024;\\n\\n    uint256 internal constant DexT1__WithdrawalNotEnough = 51025;\\n\\n    uint256 internal constant DexT1__InvalidWithdrawAmts = 51026;\\n\\n    uint256 internal constant DexT1__WithdrawAmtsZero = 51027;\\n\\n    uint256 internal constant DexT1__WithdrawExcessSharesBurn = 51028;\\n\\n    uint256 internal constant DexT1__InvalidBorrowAmts = 51029;\\n\\n    uint256 internal constant DexT1__BorrowAmtsZero = 51030;\\n\\n    uint256 internal constant DexT1__BorrowExcessSharesMinted = 51031;\\n\\n    uint256 internal constant DexT1__PaybackAmtTooHigh = 51032;\\n\\n    uint256 internal constant DexT1__InvalidPaybackAmts = 51033;\\n\\n    uint256 internal constant DexT1__PaybackAmtsZero = 51034;\\n\\n    uint256 internal constant DexT1__PaybackSharedBurnedLess = 51035;\\n\\n    uint256 internal constant DexT1__NothingToArbitrage = 51036;\\n\\n    uint256 internal constant DexT1__MsgSenderNotLiquidity = 51037;\\n\\n    // On liquidity callback reentrancy bit should be on\\n    uint256 internal constant DexT1__ReentrancyBitShouldBeOn = 51038;\\n\\n    // Thrown is reentrancy is already on and someone tries to fetch oracle price. Should not be possible to this\\n    uint256 internal constant DexT1__OraclePriceFetchAlreadyEntered = 51039;\\n\\n    // Thrown when swap changes the current price by more than 5%\\n    uint256 internal constant DexT1__OracleUpdateHugeSwapDiff = 51040;\\n\\n    uint256 internal constant DexT1__Token0ShouldBeSmallerThanToken1 = 51041;\\n\\n    uint256 internal constant DexT1__OracleMappingOverflow = 51042;\\n\\n    /// @notice thrown if governance has paused the swapping & arbitrage so only perfect functions are usable\\n    uint256 internal constant DexT1__SwapAndArbitragePaused = 51043;\\n\\n    uint256 internal constant DexT1__ExceedsAmountInMax = 51044;\\n\\n    /// @notice thrown if amount in is too high or too low\\n    uint256 internal constant DexT1__SwapInLimitingAmounts = 51045;\\n\\n    /// @notice thrown if amount out is too high or too low\\n    uint256 internal constant DexT1__SwapOutLimitingAmounts = 51046;\\n\\n    uint256 internal constant DexT1__MintAmtOverflow = 51047;\\n\\n    uint256 internal constant DexT1__BurnAmtOverflow = 51048;\\n\\n    uint256 internal constant DexT1__LimitingAmountsSwapAndNonPerfectActions = 51049;\\n\\n    uint256 internal constant DexT1__InsufficientOracleData = 51050;\\n\\n    uint256 internal constant DexT1__SharesAmountInsufficient = 51051;\\n\\n    uint256 internal constant DexT1__CenterPriceOutOfRange = 51052;\\n\\n    uint256 internal constant DexT1__DebtReservesTooLow = 51053;\\n\\n    uint256 internal constant DexT1__SwapAndDepositTooLowOrTooHigh = 51054;\\n\\n    uint256 internal constant DexT1__WithdrawAndSwapTooLowOrTooHigh = 51055;\\n\\n    uint256 internal constant DexT1__BorrowAndSwapTooLowOrTooHigh = 51056;\\n\\n    uint256 internal constant DexT1__SwapAndPaybackTooLowOrTooHigh = 51057;\\n\\n    uint256 internal constant DexT1__InvalidImplementation = 51058;\\n\\n    uint256 internal constant DexT1__OnlyDelegateCallAllowed = 51059;\\n\\n    uint256 internal constant DexT1__IncorrectDataLength = 51060;\\n\\n    uint256 internal constant DexT1__AmountToSendLessThanAmount = 51061;\\n\\n    uint256 internal constant DexT1__InvalidCollateralReserves = 51062;\\n\\n    uint256 internal constant DexT1__InvalidDebtReserves = 51063;\\n\\n    uint256 internal constant DexT1__SupplySharesOverflow = 51064;\\n\\n    uint256 internal constant DexT1__BorrowSharesOverflow = 51065;\\n\\n    uint256 internal constant DexT1__OracleNotActive = 51066;\\n\\n    /***********************************|\\n    |            DEX Admin              | \\n    |__________________________________*/\\n\\n    /// @notice thrown when pool is not initialized\\n    uint256 internal constant DexT1Admin__PoolNotInitialized = 52001;\\n\\n    uint256 internal constant DexT1Admin__SmartColIsAlreadyOn = 52002;\\n\\n    uint256 internal constant DexT1Admin__SmartDebtIsAlreadyOn = 52003;\\n\\n    /// @notice thrown when any of the configs value overflow the maximum limit\\n    uint256 internal constant DexT1Admin__ConfigOverflow = 52004;\\n\\n    uint256 internal constant DexT1Admin__AddressNotAContract = 52005;\\n\\n    uint256 internal constant DexT1Admin__InvalidParams = 52006;\\n\\n    uint256 internal constant DexT1Admin__UserNotDefined = 52007;\\n\\n    uint256 internal constant DexT1Admin__OnlyDelegateCallAllowed = 52008;\\n\\n    uint256 internal constant DexT1Admin__UnexpectedPoolState = 52009;\\n\\n    /// @notice thrown when trying to pause or unpause but user is already in the target pause state\\n    uint256 internal constant DexT1Admin__InvalidPauseToggle = 52009;\\n\\n    /***********************************|\\n    |            DEX Factory            | \\n    |__________________________________*/\\n\\n    uint256 internal constant DexFactory__InvalidOperation = 53001;\\n    uint256 internal constant DexFactory__Unauthorized = 53002;\\n    uint256 internal constant DexFactory__SameTokenNotAllowed = 53003;\\n    uint256 internal constant DexFactory__TokenConfigNotProper = 53004;\\n    uint256 internal constant DexFactory__InvalidParams = 53005;\\n    uint256 internal constant DexFactory__OnlyDelegateCallAllowed = 53006;\\n    uint256 internal constant DexFactory__InvalidDexAddress = 53007;\\n}\\n\",\"keccak256\":\"0xc1f51cbf40f6b5c904a1f3a455dc76ef6d4ab9625e1f604d11b72670a268b6fb\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/interfaces/iDexFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\ninterface IFluidDexFactory {\\n    /// @notice Global auth is auth for all dexes\\n    function isGlobalAuth(address auth_) external view returns (bool);\\n\\n    /// @notice Dex auth is auth for a specific dex\\n    function isDexAuth(address vault_, address auth_) external view returns (bool);\\n\\n    /// @notice Total dexes deployed.\\n    function totalDexes() external view returns (uint256);\\n\\n    /// @notice Compute dexAddress\\n    function getDexAddress(uint256 dexId_) external view returns (address);\\n\\n    /// @notice read uint256 `result_` for a storage `slot_` key\\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\\n}\\n\",\"keccak256\":\"0xfc81e2f8de72dcf84022b69495996f59fe560cac430767f504de1064c32f550e\",\"license\":\"MIT\"},\"contracts/protocols/dex/interfaces/iDexT1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\ninterface IFluidDexT1 {\\n    error FluidDexError(uint256 errorId);\\n\\n    /// @notice used to simulate swap to find the output amount\\n    error FluidDexSwapResult(uint256 amountOut);\\n\\n    error FluidDexPerfectLiquidityOutput(uint256 token0Amt, uint token1Amt);\\n\\n    error FluidDexSingleTokenOutput(uint256 tokenAmt);\\n\\n    error FluidDexLiquidityOutput(uint256 shares);\\n\\n    error FluidDexPricesAndExchangeRates(PricesAndExchangePrice pex_);\\n\\n    /// @notice returns the dex id\\n    function DEX_ID() external view returns (uint256);\\n\\n    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\\n\\n    struct Implementations {\\n        address shift;\\n        address admin;\\n        address colOperations;\\n        address debtOperations;\\n        address perfectOperationsAndOracle;\\n    }\\n\\n    struct ConstantViews {\\n        uint256 dexId;\\n        address liquidity;\\n        address factory;\\n        Implementations implementations;\\n        address deployerContract;\\n        address token0;\\n        address token1;\\n        bytes32 supplyToken0Slot;\\n        bytes32 borrowToken0Slot;\\n        bytes32 supplyToken1Slot;\\n        bytes32 borrowToken1Slot;\\n        bytes32 exchangePriceToken0Slot;\\n        bytes32 exchangePriceToken1Slot;\\n        uint256 oracleMapping;\\n    }\\n\\n    struct ConstantViews2 {\\n        uint token0NumeratorPrecision;\\n        uint token0DenominatorPrecision;\\n        uint token1NumeratorPrecision;\\n        uint token1DenominatorPrecision;\\n    }\\n\\n    struct PricesAndExchangePrice {\\n        uint lastStoredPrice; // last stored price in 1e27 decimals\\n        uint centerPrice; // last stored price in 1e27 decimals\\n        uint upperRange; // price at upper range in 1e27 decimals\\n        uint lowerRange; // price at lower range in 1e27 decimals\\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\\n        uint supplyToken0ExchangePrice;\\n        uint borrowToken0ExchangePrice;\\n        uint supplyToken1ExchangePrice;\\n        uint borrowToken1ExchangePrice;\\n    }\\n\\n    struct CollateralReserves {\\n        uint token0RealReserves;\\n        uint token1RealReserves;\\n        uint token0ImaginaryReserves;\\n        uint token1ImaginaryReserves;\\n    }\\n\\n    struct DebtReserves {\\n        uint token0Debt;\\n        uint token1Debt;\\n        uint token0RealReserves;\\n        uint token1RealReserves;\\n        uint token0ImaginaryReserves;\\n        uint token1ImaginaryReserves;\\n    }\\n\\n    function getCollateralReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0SupplyExchangePrice_,\\n        uint token1SupplyExchangePrice_\\n    ) external view returns (CollateralReserves memory c_);\\n\\n    function getDebtReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0BorrowExchangePrice_,\\n        uint token1BorrowExchangePrice_\\n    ) external view returns (DebtReserves memory d_);\\n\\n    // reverts with FluidDexPricesAndExchangeRates(pex_);\\n    function getPricesAndExchangePrices() external;\\n\\n    function constantsView() external view returns (ConstantViews memory constantsView_);\\n\\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_);\\n\\n    struct Oracle {\\n        uint twap1by0; // TWAP price\\n        uint lowestPrice1by0; // lowest price point\\n        uint highestPrice1by0; // highest price point\\n        uint twap0by1; // TWAP price\\n        uint lowestPrice0by1; // lowest price point\\n        uint highestPrice0by1; // highest price point\\n    }\\n\\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountIn_ The exact amount of input tokens to swap\\n    /// @param amountOutMin_ The minimum amount of output tokens the user is willing to accept\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\\n    /// @return amountOut_ The amount of output tokens received from the swap\\n    function swapIn(\\n        bool swap0to1_,\\n        uint256 amountIn_,\\n        uint256 amountOutMin_,\\n        address to_\\n    ) external payable returns (uint256 amountOut_);\\n\\n    /// @dev Swap tokens with perfect amount out\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountOut_ The exact amount of tokens to receive after swap\\n    /// @param amountInMax_ Maximum amount of tokens to swap in\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\\n    /// @return amountIn_ The amount of input tokens used for the swap\\n    function swapOut(\\n        bool swap0to1_,\\n        uint256 amountOut_,\\n        uint256 amountInMax_,\\n        address to_\\n    ) external payable returns (uint256 amountIn_);\\n\\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\\n    /// @param shares_ The number of shares to mint\\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\\n    /// @return token0Amt_ Amount of token0 deposited\\n    /// @return token1Amt_ Amount of token1 deposited\\n    function depositPerfect(\\n        uint shares_,\\n        uint maxToken0Deposit_,\\n        uint maxToken1Deposit_,\\n        bool estimate_\\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\\n\\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\\n    /// @param shares_ The number of shares to withdraw\\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\\n    /// @return token0Amt_ The amount of token0 withdrawn\\n    /// @return token1Amt_ The amount of token1 withdrawn\\n    function withdrawPerfect(\\n        uint shares_,\\n        uint minToken0Withdraw_,\\n        uint minToken1Withdraw_,\\n        address to_\\n    ) external returns (uint token0Amt_, uint token1Amt_);\\n\\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\\n    /// @param shares_ The number of shares to borrow\\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\\n    /// @return token0Amt_ Amount of token0 borrowed\\n    /// @return token1Amt_ Amount of token1 borrowed\\n    function borrowPerfect(\\n        uint shares_,\\n        uint minToken0Borrow_,\\n        uint minToken1Borrow_,\\n        address to_\\n    ) external returns (uint token0Amt_, uint token1Amt_);\\n\\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\\n    /// @param shares_ The number of shares to pay back\\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\\n    /// @return token0Amt_ Amount of token0 paid back\\n    /// @return token1Amt_ Amount of token1 paid back\\n    function paybackPerfect(\\n        uint shares_,\\n        uint maxToken0Payback_,\\n        uint maxToken1Payback_,\\n        bool estimate_\\n    ) external payable returns (uint token0Amt_, uint token1Amt_);\\n\\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\\n    /// @param token0Amt_ The amount of token0 to deposit\\n    /// @param token1Amt_ The amount of token1 to deposit\\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\\n    /// @return shares_ The amount of shares minted for the deposit\\n    function deposit(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint minSharesAmt_,\\n        bool estimate_\\n    ) external payable returns (uint shares_);\\n\\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\\n    /// @param token0Amt_ The amount of token0 to withdraw\\n    /// @param token1Amt_ The amount of token1 to withdraw\\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\\n    /// @return shares_ The number of shares burned for the withdrawal\\n    function withdraw(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint maxSharesAmt_,\\n        address to_\\n    ) external returns (uint shares_);\\n\\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\\n    /// @param token0Amt_ The amount of token0 to borrow\\n    /// @param token1Amt_ The amount of token1 to borrow\\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\\n    function borrow(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint maxSharesAmt_,\\n        address to_\\n    ) external returns (uint shares_);\\n\\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\\n    /// @param token0Amt_ The amount of token0 to payback\\n    /// @param token1Amt_ The amount of token1 to payback\\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\\n    /// @return shares_ The amount of borrow shares burned for the payback\\n    function payback(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint minSharesAmt_,\\n        bool estimate_\\n    ) external payable returns (uint shares_);\\n\\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\\n    /// @param shares_ The number of shares to burn for withdrawal\\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\\n    function withdrawPerfectInOneToken(\\n        uint shares_,\\n        uint minToken0_,\\n        uint minToken1_,\\n        address to_\\n    ) external returns (\\n        uint withdrawAmt_\\n    );\\n\\n    /// @dev This function allows users to payback their debt with perfect shares in one token\\n    /// @param shares_ The number of shares to burn for payback\\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\\n    function paybackPerfectInOneToken(\\n        uint shares_,\\n        uint maxToken0_,\\n        uint maxToken1_,\\n        bool estimate_\\n    ) external payable returns (\\n        uint paybackAmt_\\n    );\\n\\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\\n    /// but the difference due to interest will be super low so this difference is ignored\\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\\n    /// @return currentPrice_ price of pool after the most recent swap\\n    function oraclePrice(\\n        uint[] memory secondsAgos_\\n    ) external view returns (\\n        Oracle[] memory twaps_,\\n        uint currentPrice_\\n    );\\n}\\n\",\"keccak256\":\"0xa405007cdd45409412ce0fe02a991cadbae17760bc15402c839375505f69d7b2\",\"license\":\"MIT\"},\"contracts/protocols/dex/poolT1/common/constantVariables.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { StorageRead } from \\\"../../../../libraries/storageRead.sol\\\";\\n\\ninterface ITokenDecimals {\\n    function decimals() external view returns (uint8);\\n}\\n\\nabstract contract ConstantVariables is StorageRead {\\n    /*//////////////////////////////////////////////////////////////\\n                          CONSTANTS / IMMUTABLES\\n    //////////////////////////////////////////////////////////////*/\\n\\n    address internal constant TEAM_MULTISIG = 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e;\\n\\n    address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n    uint256 internal constant NATIVE_TOKEN_DECIMALS = 18;\\n    address internal constant ADDRESS_DEAD = 0x000000000000000000000000000000000000dEaD;\\n    uint256 internal constant TOKENS_DECIMALS_PRECISION = 12;\\n    uint256 internal constant TOKENS_DECIMALS = 1e12;\\n\\n    uint256 internal constant SMALL_COEFFICIENT_SIZE = 10;\\n    uint256 internal constant DEFAULT_COEFFICIENT_SIZE = 56;\\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xFF;\\n\\n    uint256 internal constant X2 = 0x3;\\n    uint256 internal constant X3 = 0x7;\\n    uint256 internal constant X5 = 0x1f;\\n    uint256 internal constant X7 = 0x7f;\\n    uint256 internal constant X8 = 0xff;\\n    uint256 internal constant X9 = 0x1ff;\\n    uint256 internal constant X10 = 0x3ff;\\n    uint256 internal constant X11 = 0x7ff;\\n    uint256 internal constant X14 = 0x3fff;\\n    uint256 internal constant X16 = 0xffff;\\n    uint256 internal constant X17 = 0x1ffff;\\n    uint256 internal constant X18 = 0x3ffff;\\n    uint256 internal constant X20 = 0xfffff;\\n    uint256 internal constant X22 = 0x3fffff;\\n    uint256 internal constant X23 = 0x7fffff;\\n    uint256 internal constant X24 = 0xffffff;\\n    uint256 internal constant X28 = 0xfffffff;\\n    uint256 internal constant X30 = 0x3fffffff;\\n    uint256 internal constant X32 = 0xffffffff;\\n    uint256 internal constant X33 = 0x1ffffffff;\\n    uint256 internal constant X40 = 0xffffffffff;\\n    uint256 internal constant X64 = 0xffffffffffffffff;\\n    uint256 internal constant X96 = 0xffffffffffffffffffffffff;\\n    uint256 internal constant X128 = 0xffffffffffffffffffffffffffffffff;\\n\\n    uint256 internal constant TWO_DECIMALS = 1e2;\\n    uint256 internal constant THREE_DECIMALS = 1e3;\\n    uint256 internal constant FOUR_DECIMALS = 1e4;\\n    uint256 internal constant FIVE_DECIMALS = 1e5;\\n    uint256 internal constant SIX_DECIMALS = 1e6;\\n    uint256 internal constant EIGHT_DECIMALS = 1e8;\\n    uint256 internal constant NINE_DECIMALS = 1e9;\\n\\n    uint256 internal constant PRICE_PRECISION = 1e27;\\n\\n    uint256 internal constant ORACLE_PRECISION = 1e18; // 100%\\n    uint256 internal constant ORACLE_LIMIT = 5 * 1e16; // 5%\\n\\n    /// after swap token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_SWAP\\n    /// after swap token1 reserves should not be less than token0InToken1 / MINIMUM_LIQUIDITY_SWAP\\n    uint256 internal constant MINIMUM_LIQUIDITY_SWAP = 1e4;\\n\\n    /// after user operations (deposit, withdraw, borrow, payback) token0 reserves should not be less than token1InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\\n    /// after user operations (deposit, withdraw, borrow, payback) token1 reserves should not be less than token0InToken0 / MINIMUM_LIQUIDITY_USER_OPERATIONS\\n    uint256 internal constant MINIMUM_LIQUIDITY_USER_OPERATIONS = 1e6;\\n\\n    /// To skip transfers in liquidity layer if token in & out is same and liquidity layer is on the winning side\\n    bytes32 internal constant SKIP_TRANSFERS = keccak256(bytes(\\\"SKIP_TRANSFERS\\\"));\\n\\n    function _decimals(address token_) internal view returns (uint256) {\\n        return (token_ == NATIVE_TOKEN) ? NATIVE_TOKEN_DECIMALS : ITokenDecimals(token_).decimals();\\n    }\\n}\\n\",\"keccak256\":\"0xab697f39bfede319530bac2bc86e71e663c6b81de2bafea4255f2cc65f2b520b\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/common/variables.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nabstract contract Variables {\\n    /*//////////////////////////////////////////////////////////////\\n                          STORAGE VARIABLES\\n    //////////////////////////////////////////////////////////////*/\\n\\n    /// First 1 bit  => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\\n    /// Next 40 bits => 1-40 => last to last stored price. BigNumber (32 bits precision, 8 bits exponent)\\n    /// Next 40 bits => 41-80 => last stored price of pool. BigNumber (32 bits precision, 8 bits exponent)\\n    /// Next 40 bits => 81-120 => center price. Center price from where the ranges will be calculated. BigNumber (32 bits precision, 8 bits exponent)\\n    /// Next 33 bits => 121-153 => last interaction time stamp\\n    /// Next 22 bits => 154-175 => max 4194303 seconds (~1165 hrs, ~48.5 days), time difference between last to last and last price stored\\n    /// Next 3 bits  => 176-178 => oracle checkpoint, if 0 then first slot, if 7 then last slot\\n    /// Next 16 bits => 179-194 => current mapping or oracle, after every 8 transaction it will increase by 1. Max capacity is 65535 but it can be lower than that check dexVariables2\\n    /// Next 1 bit  => 195 => is oracle active?\\n    uint internal dexVariables;\\n\\n    /// Next  1 bit  => 0 => is smart collateral enabled?\\n    /// Next  1 bit  => 1 => is smart debt enabled?\\n    /// Next 17 bits => 2-18 => fee (1% = 10000, max value: 100000 = 10%, fee should not be more than 10%)\\n    /// Next  7 bits => 19-25 => revenue cut from fee (1 = 1%, 100 = 100%). If fee is 1000 = 0.1% and revenue cut is 10 = 10% then governance get 0.01% of every swap\\n    /// Next  1 bit  => 26 => percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\\n    /// Next 20 bits => 27-46 => upperPercent (1% = 10000, max value: 104.8575%) upperRange - upperRange * upperPercent = centerPrice. Hence, upperRange = centerPrice / (1 - upperPercent)\\n    /// Next 20 bits => 47-66 => lowerPercent. lowerRange = centerPrice - centerPrice * lowerPercent.\\n    /// Next  1 bit  => 67 => threshold percent active change going on or not, 0 = false, 1 = true, if true than that means governance has updated the below percents and the update should happen with a specified time.\\n    /// Next 10 bits => 68-77 => upper shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice > (centerPrice + (upperRange - centerPrice) * (1000 - upperShiftThresholdPercent) / 1000) then trigger shift\\n    /// Next 10 bits => 78-87 => lower shift threshold percent, 1 = 0.1%. 1000 = 100%. if currentPrice < (centerPrice - (centerPrice - lowerRange) * (1000 - lowerShiftThresholdPercent) / 1000) then trigger shift\\n    /// Next 24 bits => 88-111 => Shifting time (~194 days) (rate = (% up + % down) / time ?)\\n    /// Next 30 bits => 112-131 => Address of center price if center price should be fetched externally, for example, for wstETH <> ETH pool, fetch wstETH exchange rate into stETH from wstETH contract.\\n    /// Why fetch it externally? Because let's say pool width is 0.1% and wstETH temporarily got depeg of 0.5% then pool will start to shift to newer pricing\\n    /// but we don't want pool to shift to 0.5% because we know the depeg will recover so to avoid the loss for users.\\n    /// Next 30 bits => 142-171 => Hooks bits, calculate hook address by storing deployment nonce from factory.\\n    /// Next 28 bits => 172-199 => max center price. BigNumber (20 bits precision, 8 bits exponent)\\n    /// Next 28 bits => 200-227 => min center price. BigNumber (20 bits precision, 8 bits exponent)\\n    /// Next 10 bits => 228-237 => utilization limit of token0. Max value 1000 = 100%, if 100% then no need to check the utilization.\\n    /// Next 10 bits => 238-247 => utilization limit of token1. Max value 1000 = 100%, if 100% then no need to check the utilization.\\n    /// Next 1  bit  => 248     => is center price shift active\\n    /// Last 1  bit  => 255     => Pause swap & arbitrage (only perfect functions will be usable), if we need to pause entire DEX then that can be done through pausing DEX on Liquidity Layer\\n    uint internal dexVariables2;\\n\\n    /// first 128 bits => 0-127 => total supply shares\\n    /// last 128 bits => 128-255 => max supply shares\\n    uint internal _totalSupplyShares;\\n\\n    /// @dev user supply data: user -> data\\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userSupplyData. Hence exact same supply & borrow limit library can be used\\n    /// First  1 bit  =>       0 => is user allowed to supply? 0 = not allowed, 1 = allowed\\n    /// Next  64 bits =>   1- 64 => user supply amount/shares; BigMath: 56 | 8\\n    /// Next  64 bits =>  65-128 => previous user withdrawal limit; BigMath: 56 | 8\\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\\n    /// Next  14 bits => 162-175 => expand withdrawal limit percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383).\\n    ///                             @dev shrinking is instant\\n    /// Next  24 bits => 176-199 => withdrawal limit expand duration in seconds.(Max value 16_777_215; ~4_660 hours, ~194 days)\\n    /// Next  18 bits => 200-217 => base withdrawal limit: below this, 100% withdrawals can be done (aka shares can be burned); BigMath: 10 | 8\\n    /// Next  38 bits => 218-255 => empty for future use\\n    mapping(address => uint) internal _userSupplyData;\\n\\n    /// first 128 bits => 0-127 => total borrow shares\\n    /// last 128 bits => 128-255 => max borrow shares\\n    uint internal _totalBorrowShares;\\n\\n    /// @dev user borrow data: user -> data\\n    /// Aside from 1st bit, entire bits here are same as liquidity layer _userBorrowData. Hence exact same supply & borrow limit library function can be used\\n    /// First  1 bit  =>       0 => is user allowed to borrow? 0 = not allowed, 1 = allowed\\n    /// Next  64 bits =>   1- 64 => user debt amount/shares; BigMath: 56 | 8\\n    /// Next  64 bits =>  65-128 => previous user debt ceiling; BigMath: 56 | 8\\n    /// Next  33 bits => 129-161 => last triggered process timestamp (enough until 16 March 2242 -> max value 8589934591)\\n    /// Next  14 bits => 162-175 => expand debt ceiling percentage (in 1e2: 100% = 10_000; 1% = 100 -> max value 16_383)\\n    ///                             @dev shrinking is instant\\n    /// Next  24 bits => 176-199 => debt ceiling expand duration in seconds (Max value 16_777_215; ~4_660 hours, ~194 days)\\n    /// Next  18 bits => 200-217 => base debt ceiling: below this, there's no debt ceiling limits; BigMath: 10 | 8\\n    /// Next  18 bits => 218-235 => max debt ceiling: absolute maximum debt ceiling can expand to; BigMath: 10 | 8\\n    /// Next  20 bits => 236-255 => empty for future use\\n    mapping(address => uint) internal _userBorrowData;\\n\\n    /// Price difference between last swap of last block & last swap of new block\\n    /// If last swap happened at Block B - 4 and next swap happened after 4 blocks at Block B then it will store that difference\\n    /// considering time difference between these 4 blocks is 48 seconds, hence time will be stored as 48\\n    /// New oracle update:\\n    /// time to 9 bits and precision to 22 bits\\n    /// if time exceeds 9 bits which is 511 sec or ~8.5 min then we will use 2 oracle slot to store the data\\n    /// we will leave the both time slot as 0 and on first sign + precision slot we will store time and\\n    /// on second sign + precision slot we will store sign & precision\\n    /// First 9 bits =>   0-  8 => time, 511 seconds\\n    /// Next   1 bit  =>  9     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits =>  10- 31 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits =>  32- 40 => time, 511 seconds\\n    /// Next   1 bit  =>  41     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits =>  42- 63 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits =>  64- 72 => time, 511 seconds\\n    /// Next   1 bit  =>  73     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits =>  74- 95 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits =>  96-104 => time, 511 seconds\\n    /// Next   1 bit  => 105     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits => 106-127 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits => 128-136 => time, 511 seconds\\n    /// Next   1 bit  => 137     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits => 138-159 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits => 160-168 => time, 511 seconds\\n    /// Next   1 bit  => 169     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits => 170-191 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits => 192-200 => time, 511 seconds\\n    /// Next   1 bit  => 201     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits => 202-223 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    /// Next  9 bits => 224-232 => time, 511 seconds\\n    /// Next   1 bit  => 233     => sign of percent in change, if 1 then 0 or positive, else negative\\n    /// Next  22 bits => 234-255 => 4194303, change in price, max change is capped to 5%, so 4194303 = 5%, 1 = 0.0000011920931797249746%\\n    mapping(uint => uint) internal _oracle;\\n\\n    /// First 20 bits =>  0-19 => old upper shift\\n    /// Next  20 bits => 20-39 => old lower shift\\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\\n    uint128 internal _rangeShift;\\n\\n    /// First 10 bits =>  0- 9 => old upper shift\\n    /// Next  10 bits => 10-19 => empty so we can use same helper function\\n    /// Next  10 bits => 20-29 => old lower shift\\n    /// Next  10 bits => 30-39 => empty so we can use same helper function\\n    /// Next  20 bits => 40-59 => in seconds, ~12 days max, shift can last for max ~12 days\\n    /// Next  33 bits => 60-92 => timestamp of when the shift has started.\\n    /// Next  24 bits => 93-116 => old threshold time\\n    uint128 internal _thresholdShift;\\n\\n    /// Shifting is fuzzy and with time it'll keep on getting closer and then eventually get over\\n    /// First 33 bits => 0 -32 => starting timestamp\\n    /// Next  20 bits => 33-52 => % shift\\n    /// Next  20 bits => 53-72 => time to shift that percent\\n    uint256 internal _centerPriceShift;\\n}\\n\",\"keccak256\":\"0x16b4df290f6f0b75669f726435b8d94fe0748c0a06720b694b9cded6832be722\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/core/main.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { CoreHelpers } from \\\"../helpers/coreHelpers.sol\\\";\\nimport { SafeTransfer } from \\\"../../../../../libraries/safeTransfer.sol\\\";\\nimport { DexSlotsLink } from \\\"../../../../../libraries/dexSlotsLink.sol\\\";\\nimport { DexCalcs } from \\\"../../../../../libraries/dexCalcs.sol\\\";\\nimport { BigMathMinified } from \\\"../../../../../libraries/bigMathMinified.sol\\\";\\nimport { ErrorTypes } from \\\"../../../errorTypes.sol\\\";\\nimport { IFluidDexT1 } from \\\"../../../interfaces/iDexT1.sol\\\";\\n\\ninterface IDexCallback {\\n    function dexCallback(address token_, uint256 amount_) external;\\n}\\n\\n/// @title FluidDexT1\\n/// @notice Implements core logics for Fluid Dex protocol.\\n/// Note Token transfers happen directly from user to Liquidity contract and vice-versa.\\ncontract FluidDexT1 is CoreHelpers {\\n    using BigMathMinified for uint256;\\n\\n    constructor(ConstantViews memory constantViews_) CoreHelpers(constantViews_) {\\n        // any implementations should not be zero\\n        if (\\n            constantViews_.implementations.shift == address(0) ||\\n            constantViews_.implementations.admin == address(0) ||\\n            constantViews_.implementations.colOperations == address(0) ||\\n            constantViews_.implementations.debtOperations == address(0) ||\\n            constantViews_.implementations.perfectOperationsAndSwapOut == address(0)\\n        ) {\\n            revert FluidDexError(ErrorTypes.DexT1__InvalidImplementation);\\n        }\\n    }\\n\\n    struct SwapInExtras {\\n        address to;\\n        uint amountOutMin;\\n        bool isCallback;\\n    }\\n\\n    /// @dev This function allows users to swap a specific amount of input tokens for output tokens\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountIn_ The exact amount of input tokens to swap\\n    /// @param extras_ Additional parameters for the swap:\\n    ///   - to: Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\\n    ///   - amountOutMin: The minimum amount of output tokens the user expects to receive\\n    ///   - isCallback: If true, indicates that the input tokens should be transferred via a callback\\n    /// @return amountOut_ The amount of output tokens received from the swap\\n    function _swapIn(\\n        bool swap0to1_,\\n        uint256 amountIn_,\\n        SwapInExtras memory extras_\\n    ) internal returns (uint256 amountOut_) {\\n        uint dexVariables_ = dexVariables;\\n        uint dexVariables2_ = dexVariables2;\\n\\n        if ((dexVariables2_ >> 255) == 1) revert FluidDexError(ErrorTypes.DexT1__SwapAndArbitragePaused);\\n\\n        _check(dexVariables_, dexVariables2_);\\n\\n        if (extras_.to == address(0)) extras_.to = msg.sender;\\n\\n        SwapInMemory memory s_;\\n\\n        if (swap0to1_) {\\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_0, TOKEN_1);\\n            unchecked {\\n                s_.amtInAdjusted = (amountIn_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION;\\n            }\\n        } else {\\n            (s_.tokenIn, s_.tokenOut) = (TOKEN_1, TOKEN_0);\\n            unchecked {\\n                s_.amtInAdjusted = (amountIn_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION;\\n            }\\n        }\\n\\n        _verifySwapAndNonPerfectActions(s_.amtInAdjusted, amountIn_);\\n\\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables_, dexVariables2_);\\n\\n        if (msg.value > 0) {\\n            if (msg.value != amountIn_) revert FluidDexError(ErrorTypes.DexT1__EthAndAmountInMisMatch);\\n            if (s_.tokenIn != NATIVE_TOKEN) revert FluidDexError(ErrorTypes.DexT1__EthSentForNonNativeSwap);\\n        }\\n\\n        // is smart collateral pool enabled\\n        uint temp_ = dexVariables2_ & 1;\\n        // is smart debt pool enabled\\n        uint temp2_ = (dexVariables2_ >> 1) & 1;\\n\\n        uint temp3_;\\n        uint temp4_;\\n\\n        // extracting fee\\n        temp3_ = ((dexVariables2_ >> 2) & X17);\\n        unchecked {\\n            // revenueCut in 6 decimals, to have proper precision\\n            // if fee = 1% and revenue cut = 10% then revenueCut = 1e8 - (10000 * 10) = 99900000\\n            s_.revenueCut = EIGHT_DECIMALS - ((((dexVariables2_ >> 19) & X7) * temp3_));\\n            // fee in 4 decimals\\n            // 1 - fee. If fee is 1% then withoutFee will be 1e6 - 1e4\\n            // s_.fee => 1 - withdraw fee\\n            s_.fee = SIX_DECIMALS - temp3_;\\n        }\\n\\n        CollateralReservesSwap memory cs_;\\n        DebtReservesSwap memory ds_;\\n        if (temp_ == 1) {\\n            // smart collateral is enabled\\n            {\\n                CollateralReserves memory c_ = _getCollateralReserves(\\n                    pex_.geometricMean,\\n                    pex_.upperRange,\\n                    pex_.lowerRange,\\n                    pex_.supplyToken0ExchangePrice,\\n                    pex_.supplyToken1ExchangePrice\\n                );\\n                if (swap0to1_) {\\n                    (\\n                        cs_.tokenInRealReserves,\\n                        cs_.tokenOutRealReserves,\\n                        cs_.tokenInImaginaryReserves,\\n                        cs_.tokenOutImaginaryReserves\\n                    ) = (\\n                        c_.token0RealReserves,\\n                        c_.token1RealReserves,\\n                        c_.token0ImaginaryReserves,\\n                        c_.token1ImaginaryReserves\\n                    );\\n                } else {\\n                    (\\n                        cs_.tokenInRealReserves,\\n                        cs_.tokenOutRealReserves,\\n                        cs_.tokenInImaginaryReserves,\\n                        cs_.tokenOutImaginaryReserves\\n                    ) = (\\n                        c_.token1RealReserves,\\n                        c_.token0RealReserves,\\n                        c_.token1ImaginaryReserves,\\n                        c_.token0ImaginaryReserves\\n                    );\\n                }\\n            }\\n        }\\n\\n        if (temp2_ == 1) {\\n            // smart debt is enabled\\n            {\\n                DebtReserves memory d_ = _getDebtReserves(\\n                    pex_.geometricMean,\\n                    pex_.upperRange,\\n                    pex_.lowerRange,\\n                    pex_.borrowToken0ExchangePrice,\\n                    pex_.borrowToken1ExchangePrice\\n                );\\n                if (swap0to1_) {\\n                    (\\n                        ds_.tokenInDebt,\\n                        ds_.tokenOutDebt,\\n                        ds_.tokenInRealReserves,\\n                        ds_.tokenOutRealReserves,\\n                        ds_.tokenInImaginaryReserves,\\n                        ds_.tokenOutImaginaryReserves\\n                    ) = (\\n                        d_.token0Debt,\\n                        d_.token1Debt,\\n                        d_.token0RealReserves,\\n                        d_.token1RealReserves,\\n                        d_.token0ImaginaryReserves,\\n                        d_.token1ImaginaryReserves\\n                    );\\n                } else {\\n                    (\\n                        ds_.tokenInDebt,\\n                        ds_.tokenOutDebt,\\n                        ds_.tokenInRealReserves,\\n                        ds_.tokenOutRealReserves,\\n                        ds_.tokenInImaginaryReserves,\\n                        ds_.tokenOutImaginaryReserves\\n                    ) = (\\n                        d_.token1Debt,\\n                        d_.token0Debt,\\n                        d_.token1RealReserves,\\n                        d_.token0RealReserves,\\n                        d_.token1ImaginaryReserves,\\n                        d_.token0ImaginaryReserves\\n                    );\\n                }\\n            }\\n        }\\n\\n        // limiting amtInAdjusted to be not more than 50% of both (collateral & debt) imaginary tokenIn reserves combined\\n        // basically, if this throws that means user is trying to swap 0.5x tokenIn if current tokenIn imaginary reserves is x\\n        // let's take x as token0 here, that means, initially the pool pricing might be:\\n        // token1Reserve / x and new pool pricing will become token1Reserve / 1.5x (token1Reserve will decrease after swap but for simplicity ignoring that)\\n        // So pool price is decreased by ~33.33% (oracle will throw error in this case as it only allows 5% price difference but better to limit it before hand)\\n        unchecked {\\n            if (s_.amtInAdjusted > ((cs_.tokenInImaginaryReserves + ds_.tokenInImaginaryReserves) / 2))\\n                revert FluidDexError(ErrorTypes.DexT1__SwapInLimitingAmounts);\\n        }\\n\\n        if (temp_ == 1 && temp2_ == 1) {\\n            // unless both pools are enabled s_.swapRoutingAmt will be 0\\n            s_.swapRoutingAmt = _swapRoutingIn(\\n                s_.amtInAdjusted,\\n                cs_.tokenOutImaginaryReserves,\\n                cs_.tokenInImaginaryReserves,\\n                ds_.tokenOutImaginaryReserves,\\n                ds_.tokenInImaginaryReserves\\n            );\\n        }\\n\\n        // In below if else statement temps are:\\n        // temp_ => deposit amt\\n        // temp2_ => withdraw amt\\n        // temp3_ => payback amt\\n        // temp4_ => borrow amt\\n        if (int(s_.amtInAdjusted) > s_.swapRoutingAmt && s_.swapRoutingAmt > 0) {\\n            // swap will route from the both pools\\n            // temp_ = amountInCol_\\n            temp_ = uint(s_.swapRoutingAmt);\\n            unchecked {\\n                // temp3_ = amountInDebt_\\n                temp3_ = s_.amtInAdjusted - temp_;\\n            }\\n\\n            (temp2_, temp4_) = (0, 0);\\n\\n            // debt pool price will be the same as collateral pool after the swap\\n            s_.withdrawTo = extras_.to;\\n            s_.borrowTo = extras_.to;\\n        } else if ((temp_ == 1 && temp2_ == 0) || (s_.swapRoutingAmt >= int(s_.amtInAdjusted))) {\\n            // entire swap will route through collateral pool\\n            (temp_, temp2_, temp3_, temp4_) = (s_.amtInAdjusted, 0, 0, 0);\\n            // price can slightly differ from debt pool but difference will be very small. Probably <0.01% for active DEX pools.\\n            s_.withdrawTo = extras_.to;\\n        } else if ((temp_ == 0 && temp2_ == 1) || (s_.swapRoutingAmt <= 0)) {\\n            // entire swap will route through debt pool\\n            (temp_, temp2_, temp3_, temp4_) = (0, 0, s_.amtInAdjusted, 0);\\n            // price can slightly differ from collateral pool but difference will be very small. Probably <0.01% for active DEX pools.\\n            s_.borrowTo = extras_.to;\\n        } else {\\n            // swap should never reach this point but if it does then reverting\\n            revert FluidDexError(ErrorTypes.DexT1__NoSwapRoute);\\n        }\\n\\n        if (temp_ > 0) {\\n            // temp2_ = amountOutCol_\\n            temp2_ = _getAmountOut(\\n                ((temp_ * s_.fee) / SIX_DECIMALS),\\n                cs_.tokenInImaginaryReserves,\\n                cs_.tokenOutImaginaryReserves\\n            );\\n            swap0to1_\\n                ? _verifyToken1Reserves(\\n                    (cs_.tokenInRealReserves + temp_),\\n                    (cs_.tokenOutRealReserves - temp2_),\\n                    pex_.centerPrice,\\n                    MINIMUM_LIQUIDITY_SWAP\\n                )\\n                : _verifyToken0Reserves(\\n                    (cs_.tokenOutRealReserves - temp2_),\\n                    (cs_.tokenInRealReserves + temp_),\\n                    pex_.centerPrice,\\n                    MINIMUM_LIQUIDITY_SWAP\\n                );\\n        }\\n        if (temp3_ > 0) {\\n            // temp4_ = amountOutDebt_\\n            temp4_ = _getAmountOut(\\n                ((temp3_ * s_.fee) / SIX_DECIMALS),\\n                ds_.tokenInImaginaryReserves,\\n                ds_.tokenOutImaginaryReserves\\n            );\\n            swap0to1_\\n                ? _verifyToken1Reserves(\\n                    (ds_.tokenInRealReserves + temp3_),\\n                    (ds_.tokenOutRealReserves - temp4_),\\n                    pex_.centerPrice,\\n                    MINIMUM_LIQUIDITY_SWAP\\n                )\\n                : _verifyToken0Reserves(\\n                    (ds_.tokenOutRealReserves - temp4_),\\n                    (ds_.tokenInRealReserves + temp3_),\\n                    pex_.centerPrice,\\n                    MINIMUM_LIQUIDITY_SWAP\\n                );\\n        }\\n\\n        // (temp_ + temp3_) == amountIn_ == msg.value (for native token), if there is revenue cut then this statement is not true\\n        temp_ = (temp_ * s_.revenueCut) / EIGHT_DECIMALS;\\n        temp3_ = (temp3_ * s_.revenueCut) / EIGHT_DECIMALS;\\n\\n        // from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same\\n        if (temp_ > temp3_) {\\n            // new pool price from col pool\\n            s_.price = swap0to1_\\n                ? ((cs_.tokenOutImaginaryReserves - temp2_) * 1e27) / (cs_.tokenInImaginaryReserves + temp_)\\n                : ((cs_.tokenInImaginaryReserves + temp_) * 1e27) / (cs_.tokenOutImaginaryReserves - temp2_);\\n        } else {\\n            // new pool price from debt pool\\n            s_.price = swap0to1_\\n                ? ((ds_.tokenOutImaginaryReserves - temp4_) * 1e27) / (ds_.tokenInImaginaryReserves + temp3_)\\n                : ((ds_.tokenInImaginaryReserves + temp3_) * 1e27) / (ds_.tokenOutImaginaryReserves - temp4_);\\n        }\\n\\n        // converting into normal token amounts\\n        if (swap0to1_) {\\n            temp_ = ((temp_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\\n            temp3_ = ((temp3_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\\n            // only adding uncheck in out amount\\n            unchecked {\\n                temp2_ = ((temp2_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\\n                temp4_ = ((temp4_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\\n            }\\n        } else {\\n            temp_ = ((temp_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\\n            temp3_ = ((temp3_ * TOKEN_1_DENOMINATOR_PRECISION) / TOKEN_1_NUMERATOR_PRECISION);\\n            // only adding uncheck in out amount\\n            unchecked {\\n                temp2_ = ((temp2_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\\n                temp4_ = ((temp4_ * TOKEN_0_DENOMINATOR_PRECISION) / TOKEN_0_NUMERATOR_PRECISION);\\n            }\\n        }\\n\\n        unchecked {\\n            amountOut_ = temp2_ + temp4_;\\n        }\\n\\n        // if address dead then reverting with amountOut\\n        if (extras_.to == ADDRESS_DEAD) revert FluidDexSwapResult(amountOut_);\\n\\n        if (amountOut_ < extras_.amountOutMin) revert FluidDexError(ErrorTypes.DexT1__NotEnoughAmountOut);\\n\\n        // allocating to avoid stack-too-deep error\\n        // not setting in the callbackData as last 2nd to avoid SKIP_TRANSFERS clashing\\n        s_.data = abi.encode(amountIn_, extras_.isCallback, msg.sender); // true/false is to decide if dex should do callback or directly transfer from user\\n        // deposit & payback token in at liquidity\\n        LIQUIDITY.operate{ value: msg.value }(s_.tokenIn, int(temp_), -int(temp3_), address(0), address(0), s_.data);\\n        // withdraw & borrow token out at liquidity\\n        LIQUIDITY.operate(s_.tokenOut, -int(temp2_), int(temp4_), s_.withdrawTo, s_.borrowTo, new bytes(0));\\n\\n        // if hook exists then calling hook\\n        temp_ = (dexVariables2_ >> 142) & X30;\\n        if (temp_ > 0) {\\n            s_.swap0to1 = swap0to1_;\\n            _hookVerify(temp_, 1, s_.swap0to1, s_.price);\\n        }\\n\\n        swap0to1_\\n            ? _utilizationVerify(((dexVariables2_ >> 238) & X10), EXCHANGE_PRICE_TOKEN_1_SLOT)\\n            : _utilizationVerify(((dexVariables2_ >> 228) & X10), EXCHANGE_PRICE_TOKEN_0_SLOT);\\n\\n        dexVariables = _updateOracle(s_.price, pex_.centerPrice, dexVariables_);\\n\\n        emit Swap(swap0to1_, amountIn_, amountOut_, extras_.to);\\n    }\\n\\n    /// @dev Swap tokens with perfect amount in\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountIn_ The exact amount of tokens to swap in\\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\\n    /// @return amountOut_ The amount of output tokens received from the swap\\n    function swapIn(\\n        bool swap0to1_,\\n        uint256 amountIn_,\\n        uint256 amountOutMin_,\\n        address to_\\n    ) public payable returns (uint256 amountOut_) {\\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, false));\\n    }\\n\\n    /// @dev Swap tokens with perfect amount in and callback functionality\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountIn_ The exact amount of tokens to swap in\\n    /// @param amountOutMin_ The minimum amount of tokens to receive after swap\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_\\n    /// @return amountOut_ The amount of output tokens received from the swap\\n    function swapInWithCallback(\\n        bool swap0to1_,\\n        uint256 amountIn_,\\n        uint256 amountOutMin_,\\n        address to_\\n    ) public payable returns (uint256 amountOut_) {\\n        return _swapIn(swap0to1_, amountIn_, SwapInExtras(to_, amountOutMin_, true));\\n    }\\n\\n    /// @dev Swap tokens with perfect amount out\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountOut_ The exact amount of tokens to receive after swap\\n    /// @param amountInMax_ Maximum amount of tokens to swap in\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\\n    /// @return amountIn_ The amount of input tokens used for the swap\\n    function swapOut(\\n        bool swap0to1_,\\n        uint256 amountOut_,\\n        uint256 amountInMax_,\\n        address to_\\n    ) public payable returns (uint256 amountIn_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev Swap tokens with perfect amount out and callback functionality\\n    /// @param swap0to1_ Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0\\n    /// @param amountOut_ The exact amount of tokens to receive after swap\\n    /// @param amountInMax_ Maximum amount of tokens to swap in\\n    /// @param to_ Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_\\n    /// @return amountIn_ The amount of input tokens used for the swap\\n    function swapOutWithCallback(\\n        bool swap0to1_,\\n        uint256 amountOut_,\\n        uint256 amountInMax_,\\n        address to_\\n    ) public payable returns (uint256 amountIn_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev Deposit tokens in equal proportion to the current pool ratio\\n    /// @param shares_ The number of shares to mint\\n    /// @param maxToken0Deposit_ Maximum amount of token0 to deposit\\n    /// @param maxToken1Deposit_ Maximum amount of token1 to deposit\\n    /// @param estimate_ If true, function will revert with estimated deposit amounts without executing the deposit\\n    /// @return token0Amt_ Amount of token0 deposited\\n    /// @return token1Amt_ Amount of token1 deposited\\n    function depositPerfect(\\n        uint shares_,\\n        uint maxToken0Deposit_,\\n        uint maxToken1Deposit_,\\n        bool estimate_\\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\\n    }\\n\\n    /// @dev This function allows users to withdraw a perfect amount of collateral liquidity\\n    /// @param shares_ The number of shares to withdraw\\n    /// @param minToken0Withdraw_ The minimum amount of token0 the user is willing to accept\\n    /// @param minToken1Withdraw_ The minimum amount of token1 the user is willing to accept\\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\\n    /// @return token0Amt_ The amount of token0 withdrawn\\n    /// @return token1Amt_ The amount of token1 withdrawn\\n    function withdrawPerfect(\\n        uint shares_,\\n        uint minToken0Withdraw_,\\n        uint minToken1Withdraw_,\\n        address to_\\n    ) public returns (uint token0Amt_, uint token1Amt_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\\n    }\\n\\n    /// @dev This function allows users to borrow tokens in equal proportion to the current debt pool ratio\\n    /// @param shares_ The number of shares to borrow\\n    /// @param minToken0Borrow_ Minimum amount of token0 to borrow\\n    /// @param minToken1Borrow_ Minimum amount of token1 to borrow\\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_\\n    /// @return token0Amt_ Amount of token0 borrowed\\n    /// @return token1Amt_ Amount of token1 borrowed\\n    function borrowPerfect(\\n        uint shares_,\\n        uint minToken0Borrow_,\\n        uint minToken1Borrow_,\\n        address to_\\n    ) public returns (uint token0Amt_, uint token1Amt_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\\n    }\\n\\n    /// @dev This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio\\n    /// @param shares_ The number of shares to pay back\\n    /// @param maxToken0Payback_ Maximum amount of token0 to pay back\\n    /// @param maxToken1Payback_ Maximum amount of token1 to pay back\\n    /// @param estimate_ If true, function will revert with estimated payback amounts without executing the payback\\n    /// @return token0Amt_ Amount of token0 paid back\\n    /// @return token1Amt_ Amount of token1 paid back\\n    function paybackPerfect(\\n        uint shares_,\\n        uint maxToken0Payback_,\\n        uint maxToken1Payback_,\\n        bool estimate_\\n    ) public payable returns (uint token0Amt_, uint token1Amt_) {\\n        return abi.decode(_spell(PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION, msg.data), (uint256, uint256));\\n    }\\n\\n    /// @dev This function allows users to deposit tokens in any proportion into the col pool\\n    /// @param token0Amt_ The amount of token0 to deposit\\n    /// @param token1Amt_ The amount of token1 to deposit\\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to receive\\n    /// @param estimate_ If true, function will revert with estimated shares without executing the deposit\\n    /// @return shares_ The amount of shares minted for the deposit\\n    function deposit(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint minSharesAmt_,\\n        bool estimate_\\n    ) public payable returns (uint shares_) {\\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev This function allows users to withdraw tokens in any proportion from the col pool\\n    /// @param token0Amt_ The amount of token0 to withdraw\\n    /// @param token1Amt_ The amount of token1 to withdraw\\n    /// @param maxSharesAmt_ The maximum number of shares the user is willing to burn\\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\\n    /// @return shares_ The number of shares burned for the withdrawal\\n    function withdraw(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint maxSharesAmt_,\\n        address to_\\n    ) public returns (uint shares_) {\\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev This function allows users to borrow tokens in any proportion from the debt pool\\n    /// @param token0Amt_ The amount of token0 to borrow\\n    /// @param token1Amt_ The amount of token1 to borrow\\n    /// @param maxSharesAmt_ The maximum amount of shares the user is willing to receive\\n    /// @param to_ Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_\\n    /// @return shares_ The amount of borrow shares minted to represent the borrowed amount\\n    function borrow(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint maxSharesAmt_,\\n        address to_\\n    ) public returns (uint shares_) {\\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev This function allows users to payback tokens in any proportion to the debt pool\\n    /// @param token0Amt_ The amount of token0 to payback\\n    /// @param token1Amt_ The amount of token1 to payback\\n    /// @param minSharesAmt_ The minimum amount of shares the user expects to burn\\n    /// @param estimate_ If true, function will revert with estimated shares without executing the payback\\n    /// @return shares_ The amount of borrow shares burned for the payback\\n    function payback(\\n        uint token0Amt_,\\n        uint token1Amt_,\\n        uint minSharesAmt_,\\n        bool estimate_\\n    ) public payable returns (uint shares_) {\\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev This function allows users to withdraw their collateral with perfect shares in one token\\n    /// @param shares_ The number of shares to burn for withdrawal\\n    /// @param minToken0_ The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)\\n    /// @param minToken1_ The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)\\n    /// @param to_ Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_\\n    /// @return withdrawAmt_ The amount of tokens withdrawn in the chosen token\\n    function withdrawPerfectInOneToken(\\n        uint shares_,\\n        uint minToken0_,\\n        uint minToken1_,\\n        address to_\\n    ) public returns (uint withdrawAmt_) {\\n        return abi.decode(_spell(COL_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev This function allows users to payback their debt with perfect shares in one token\\n    /// @param shares_ The number of shares to burn for payback\\n    /// @param maxToken0_ The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)\\n    /// @param maxToken1_ The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)\\n    /// @param estimate_ If true, the function will revert with the estimated payback amount without executing the payback\\n    /// @return paybackAmt_ The amount of tokens paid back in the chosen token\\n    function paybackPerfectInOneToken(\\n        uint shares_,\\n        uint maxToken0_,\\n        uint maxToken1_,\\n        bool estimate_\\n    ) public payable returns (uint paybackAmt_) {\\n        return abi.decode(_spell(DEBT_OPERATIONS_IMPLEMENTATION, msg.data), (uint256));\\n    }\\n\\n    /// @dev liquidity callback for cheaper token transfers in case of deposit or payback.\\n    /// only callable by Liquidity during an operation.\\n    function liquidityCallback(address token_, uint amount_, bytes calldata data_) external {\\n        if (msg.sender != address(LIQUIDITY)) revert FluidDexError(ErrorTypes.DexT1__MsgSenderNotLiquidity);\\n        if (dexVariables & 1 == 0) revert FluidDexError(ErrorTypes.DexT1__ReentrancyBitShouldBeOn);\\n        if (data_.length != 96) revert FluidDexError(ErrorTypes.DexT1__IncorrectDataLength);\\n\\n        (uint amountToSend_, bool isCallback_, address from_) = abi.decode(data_, (uint, bool, address));\\n\\n        if (amountToSend_ < amount_) revert FluidDexError(ErrorTypes.DexT1__AmountToSendLessThanAmount);\\n\\n        if (isCallback_) {\\n            IDexCallback(from_).dexCallback(token_, amountToSend_);\\n        } else {\\n            SafeTransfer.safeTransferFrom(token_, from_, address(LIQUIDITY), amountToSend_);\\n        }\\n    }\\n\\n    /// @dev the oracle assumes last set price of pool till the next swap happens.\\n    /// There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration\\n    /// but the difference due to interest will be super low so this difference is ignored\\n    /// For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other.\\n    /// then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%\\n    /// @param secondsAgos_ array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]\\n    /// @return twaps_ twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints\\n    /// @return currentPrice_ price of pool after the most recent swap\\n    function oraclePrice(\\n        uint[] memory secondsAgos_\\n    ) external view returns (Oracle[] memory twaps_, uint currentPrice_) {\\n        OraclePriceMemory memory o_;\\n\\n        uint dexVariables_ = dexVariables;\\n\\n        if ((dexVariables_ >> 195) & 1 == 0) {\\n            revert FluidDexError(ErrorTypes.DexT1__OracleNotActive);\\n        }\\n\\n        twaps_ = new Oracle[](secondsAgos_.length);\\n\\n        uint totalTime_;\\n        uint time_;\\n\\n        uint i;\\n        uint secondsAgo_ = secondsAgos_[0];\\n\\n        currentPrice_ = (dexVariables_ >> 41) & X40;\\n        currentPrice_ = (currentPrice_ >> DEFAULT_EXPONENT_SIZE) << (currentPrice_ & DEFAULT_EXPONENT_MASK);\\n        uint price_ = currentPrice_;\\n        o_.lowestPrice1by0 = currentPrice_;\\n        o_.highestPrice1by0 = currentPrice_;\\n\\n        uint twap1by0_;\\n        uint twap0by1_;\\n\\n        uint j;\\n\\n        o_.oracleSlot = (dexVariables_ >> 176) & X3;\\n        o_.oracleMap = (dexVariables_ >> 179) & X16;\\n        // if o_.oracleSlot == 7 then it'll enter the if statement in the below while loop\\n        o_.oracle = o_.oracleSlot < 7 ? _oracle[o_.oracleMap] : 0;\\n\\n        uint slotData_;\\n        uint percentDiff_;\\n\\n        if (((dexVariables_ >> 121) & X33) < block.timestamp) {\\n            // last swap didn't occured in this block.\\n            // hence last price is current price of pool & also the last price\\n            time_ = block.timestamp - ((dexVariables_ >> 121) & X33);\\n        } else {\\n            // last swap occured in this block, that means current price is active for 0 secs. Hence TWAP for it will be 0.\\n            ++j;\\n        }\\n\\n        while (true) {\\n            if (j == 2) {\\n                if (++o_.oracleSlot == 8) {\\n                    o_.oracleSlot = 0;\\n                    if (o_.oracleMap == 0) {\\n                        o_.oracleMap = TOTAL_ORACLE_MAPPING;\\n                    }\\n                    o_.oracle = _oracle[--o_.oracleMap];\\n                }\\n\\n                slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\\n                if (slotData_ > 0) {\\n                    time_ = slotData_ & X9;\\n                    if (time_ == 0) {\\n                        // time is in precision & sign bits\\n                        time_ = slotData_ >> 9;\\n                        // if o_.oracleSlot is 7 then precision & bits and stored in 1 less map\\n                        if (o_.oracleSlot == 7) {\\n                            o_.oracleSlot = 0;\\n                            if (o_.oracleMap == 0) {\\n                                o_.oracleMap = TOTAL_ORACLE_MAPPING;\\n                            }\\n                            o_.oracle = _oracle[--o_.oracleMap];\\n                            slotData_ = o_.oracle & X32;\\n                        } else {\\n                            ++o_.oracleSlot;\\n                            slotData_ = (o_.oracle >> (o_.oracleSlot * 32)) & X32;\\n                        }\\n                    }\\n                    percentDiff_ = slotData_ >> 10;\\n                    percentDiff_ = (ORACLE_LIMIT * percentDiff_) / X22;\\n                    if (((slotData_ >> 9) & 1 == 1)) {\\n                        // if positive then old price was lower than current hence subtracting\\n                        price_ = price_ - (price_ * percentDiff_) / ORACLE_PRECISION;\\n                    } else {\\n                        // if negative then old price was higher than current hence adding\\n                        price_ = price_ + (price_ * percentDiff_) / ORACLE_PRECISION;\\n                    }\\n                } else {\\n                    // oracle data does not exist. Probably due to pool recently got initialized and not have much swaps.\\n                    revert FluidDexError(ErrorTypes.DexT1__InsufficientOracleData);\\n                }\\n            } else if (j == 1) {\\n                // last & last to last price\\n                price_ = (dexVariables_ >> 1) & X40;\\n                price_ = (price_ >> DEFAULT_EXPONENT_SIZE) << (price_ & DEFAULT_EXPONENT_MASK);\\n                time_ = (dexVariables_ >> 154) & X22;\\n                ++j;\\n            } else if (j == 0) {\\n                ++j;\\n            }\\n\\n            totalTime_ += time_;\\n            if (o_.lowestPrice1by0 > price_) o_.lowestPrice1by0 = price_;\\n            if (o_.highestPrice1by0 < price_) o_.highestPrice1by0 = price_;\\n            if (totalTime_ < secondsAgo_) {\\n                twap1by0_ += price_ * time_;\\n                twap0by1_ += (1e54 / price_) * time_;\\n            } else {\\n                time_ = time_ + secondsAgo_ - totalTime_;\\n                twap1by0_ += price_ * time_;\\n                twap0by1_ += (1e54 / price_) * time_;\\n                // also auto checks that secondsAgos_ should not be == 0\\n                twap1by0_ = twap1by0_ / secondsAgo_;\\n                twap0by1_ = twap0by1_ / secondsAgo_;\\n\\n                twaps_[i] = Oracle(\\n                    twap1by0_,\\n                    o_.lowestPrice1by0,\\n                    o_.highestPrice1by0,\\n                    twap0by1_,\\n                    (1e54 / o_.highestPrice1by0),\\n                    (1e54 / o_.lowestPrice1by0)\\n                );\\n\\n                // TWAP for next secondsAgo will start with price_\\n                o_.lowestPrice1by0 = price_;\\n                o_.highestPrice1by0 = price_;\\n\\n                while (++i < secondsAgos_.length) {\\n                    // secondsAgo_ = [60, 15, 0]\\n                    time_ = totalTime_ - secondsAgo_;\\n                    // updating total time as new seconds ago started\\n                    totalTime_ = time_;\\n                    // also auto checks that secondsAgos_[i + 1] > secondsAgos_[i]\\n                    secondsAgo_ = secondsAgos_[i] - secondsAgos_[i - 1];\\n                    if (totalTime_ < secondsAgo_) {\\n                        twap1by0_ = price_ * time_;\\n                        twap0by1_ = (1e54 / price_) * time_;\\n                        // if time_ comes out as 0 here then lowestPrice & highestPrice should not be price_, it should be next price_ that we will calculate\\n                        if (time_ == 0) {\\n                            o_.lowestPrice1by0 = type(uint).max;\\n                            o_.highestPrice1by0 = 0;\\n                        }\\n                        break;\\n                    } else {\\n                        time_ = time_ + secondsAgo_ - totalTime_;\\n                        // twap1by0_ = price_ here\\n                        twap1by0_ = price_ * time_;\\n                        // twap0by1_ = (1e54 / price_) * time_;\\n                        twap0by1_ = (1e54 / price_) * time_;\\n                        twap1by0_ = twap1by0_ / secondsAgo_;\\n                        twap0by1_ = twap0by1_ / secondsAgo_;\\n                        twaps_[i] = Oracle(\\n                            twap1by0_,\\n                            o_.lowestPrice1by0,\\n                            o_.highestPrice1by0,\\n                            twap0by1_,\\n                            (1e54 / o_.highestPrice1by0),\\n                            (1e54 / o_.lowestPrice1by0)\\n                        );\\n                    }\\n                }\\n                if (i == secondsAgos_.length) return (twaps_, currentPrice_); // oracle fetch over\\n            }\\n        }\\n    }\\n\\n    function getPricesAndExchangePrices() public {\\n        uint dexVariables_ = dexVariables;\\n        uint dexVariables2_ = dexVariables2;\\n\\n        _check(dexVariables_, dexVariables2_);\\n\\n        PricesAndExchangePrice memory pex_ = _getPricesAndExchangePrices(dexVariables, dexVariables2);\\n\\n        revert FluidDexPricesAndExchangeRates(pex_);\\n    }\\n\\n    /// @dev Internal fallback function to handle calls to non-existent functions\\n    /// @notice This function is called when a transaction is sent to the contract without matching any other function\\n    /// @notice It checks if the caller is authorized, enables re-entrancy protection, delegates the call to the admin implementation, and then disables re-entrancy protection\\n    /// @notice Only authorized callers (global or dex auth) can trigger this function\\n    /// @notice This function uses assembly to perform a delegatecall to the admin implementation to update configs related to DEX\\n    function _fallback() private {\\n        if (!(DEX_FACTORY.isGlobalAuth(msg.sender) || DEX_FACTORY.isDexAuth(address(this), msg.sender))) {\\n            revert FluidDexError(ErrorTypes.DexT1__NotAnAuth);\\n        }\\n\\n        uint dexVariables_ = dexVariables;\\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\\n        // enabling re-entrancy\\n        dexVariables = dexVariables_ | 1;\\n\\n        // Delegate the current call to `ADMIN_IMPLEMENTATION`.\\n        _spell(ADMIN_IMPLEMENTATION, msg.data);\\n\\n        // disabling re-entrancy\\n        // directly fetching from storage so updates from Admin module will get auto covered\\n        dexVariables = dexVariables & ~uint(1);\\n    }\\n\\n    fallback() external payable {\\n        _fallback();\\n    }\\n\\n    receive() external payable {\\n        if (msg.sig != 0x00000000) {\\n            _fallback();\\n        }\\n    }\\n\\n    /// @notice returns all Vault constants\\n    function constantsView() external view returns (ConstantViews memory constantsView_) {\\n        constantsView_.dexId = DEX_ID;\\n        constantsView_.liquidity = address(LIQUIDITY);\\n        constantsView_.factory = address(DEX_FACTORY);\\n        constantsView_.token0 = TOKEN_0;\\n        constantsView_.token1 = TOKEN_1;\\n        constantsView_.implementations.shift = SHIFT_IMPLEMENTATION;\\n        constantsView_.implementations.admin = ADMIN_IMPLEMENTATION;\\n        constantsView_.implementations.colOperations = COL_OPERATIONS_IMPLEMENTATION;\\n        constantsView_.implementations.debtOperations = DEBT_OPERATIONS_IMPLEMENTATION;\\n        constantsView_.implementations.perfectOperationsAndSwapOut = PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\\n        constantsView_.deployerContract = DEPLOYER_CONTRACT;\\n        constantsView_.supplyToken0Slot = SUPPLY_TOKEN_0_SLOT;\\n        constantsView_.borrowToken0Slot = BORROW_TOKEN_0_SLOT;\\n        constantsView_.supplyToken1Slot = SUPPLY_TOKEN_1_SLOT;\\n        constantsView_.borrowToken1Slot = BORROW_TOKEN_1_SLOT;\\n        constantsView_.exchangePriceToken0Slot = EXCHANGE_PRICE_TOKEN_0_SLOT;\\n        constantsView_.exchangePriceToken1Slot = EXCHANGE_PRICE_TOKEN_1_SLOT;\\n        constantsView_.oracleMapping = TOTAL_ORACLE_MAPPING;\\n    }\\n\\n    /// @notice returns all Vault constants\\n    function constantsView2() external view returns (ConstantViews2 memory constantsView2_) {\\n        constantsView2_.token0NumeratorPrecision = TOKEN_0_NUMERATOR_PRECISION;\\n        constantsView2_.token0DenominatorPrecision = TOKEN_0_DENOMINATOR_PRECISION;\\n        constantsView2_.token1NumeratorPrecision = TOKEN_1_NUMERATOR_PRECISION;\\n        constantsView2_.token1DenominatorPrecision = TOKEN_1_DENOMINATOR_PRECISION;\\n    }\\n\\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\\n    ///      based on the geometric mean and price range\\n    /// @param geometricMean_ The geometric mean of the token prices\\n    /// @param upperRange_ The upper price range\\n    /// @param lowerRange_ The lower price range\\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\\n    ///         - token0RealReserves: The real reserves of token0\\n    ///         - token1RealReserves: The real reserves of token1\\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\\n    function getCollateralReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0SupplyExchangePrice_,\\n        uint token1SupplyExchangePrice_\\n    ) public view returns (CollateralReserves memory c_) {\\n        return\\n            _getCollateralReserves(\\n                geometricMean_,\\n                upperRange_,\\n                lowerRange_,\\n                token0SupplyExchangePrice_,\\n                token1SupplyExchangePrice_\\n            );\\n    }\\n\\n    /// @notice Calculates the debt reserves for both tokens\\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\\n    /// @param upperRange_ The upper price range\\n    /// @param lowerRange_ The lower price range\\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\\n    /// @return d_ The calculated debt reserves for both tokens, containing:\\n    ///         - token0Debt: The debt amount of token0\\n    ///         - token1Debt: The debt amount of token1\\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\\n    function getDebtReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0BorrowExchangePrice_,\\n        uint token1BorrowExchangePrice_\\n    ) public view returns (DebtReserves memory d_) {\\n        return\\n            _getDebtReserves(\\n                geometricMean_,\\n                upperRange_,\\n                lowerRange_,\\n                token0BorrowExchangePrice_,\\n                token1BorrowExchangePrice_\\n            );\\n    }\\n}\\n\",\"keccak256\":\"0xd50c8b8f72d8d9de610e1367e0d400a7eb9dd80a7826d13fffcfab7f50326908\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/events.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nabstract contract Events {\\n    /// @notice Emitted on token swaps\\n    /// @param swap0to1 Indicates whether the swap is from token0 to token1 or vice-versa.\\n    /// @param amountIn The amount of tokens to be sent to the vault to swap.\\n    /// @param amountOut The amount of tokens user got from the swap.\\n    /// @param to Recepient of swapped tokens.\\n    event Swap(bool swap0to1, uint256 amountIn, uint256 amountOut, address to);\\n\\n    /// @notice Emitted when liquidity is added with shares specified.\\n    /// @param shares Expected exact shares to be received.\\n    /// @param token0Amt Amount of token0 deposited.\\n    /// @param token0Amt Amount of token1 deposited.\\n    event LogDepositPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when liquidity is withdrawn with shares specified.\\n    /// @param shares shares burned\\n    /// @param token0Amt Amount of token0 withdrawn.\\n    /// @param token1Amt Amount of token1 withdrawn.\\n    event LogWithdrawPerfectColLiquidity(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when liquidity is borrowed with shares specified.\\n    /// @param shares shares minted\\n    /// @param token0Amt Amount of token0 borrowed.\\n    /// @param token1Amt Amount of token1 borrowed.\\n    event LogBorrowPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when liquidity is paid back with shares specified.\\n    /// @param shares shares burned\\n    /// @param token0Amt Amount of token0 paid back.\\n    /// @param token1Amt Amount of token1 paid back.\\n    event LogPaybackPerfectDebtLiquidity(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when liquidity is deposited with specified token0 & token1 amount\\n    /// @param amount0 Amount of token0 deposited.\\n    /// @param amount1 Amount of token1 deposited.\\n    /// @param shares Amount of shares minted.\\n    event LogDepositColLiquidity(uint amount0, uint amount1, uint shares);\\n\\n    /// @notice Emitted when liquidity is withdrawn with specified token0 & token1 amount\\n    /// @param amount0 Amount of token0 withdrawn.\\n    /// @param amount1 Amount of token1 withdrawn.\\n    /// @param shares Amount of shares burned.\\n    event LogWithdrawColLiquidity(uint amount0, uint amount1, uint shares);\\n\\n    /// @notice Emitted when liquidity is borrowed with specified token0 & token1 amount\\n    /// @param amount0 Amount of token0 borrowed.\\n    /// @param amount1 Amount of token1 borrowed.\\n    /// @param shares Amount of shares minted.\\n    event LogBorrowDebtLiquidity(uint amount0, uint amount1, uint shares);\\n\\n    /// @notice Emitted when liquidity is paid back with specified token0 & token1 amount\\n    /// @param amount0 Amount of token0 paid back.\\n    /// @param amount1 Amount of token1 paid back.\\n    /// @param shares Amount of shares burned.\\n    event LogPaybackDebtLiquidity(uint amount0, uint amount1, uint shares);\\n\\n    /// @notice Emitted when liquidity is withdrawn with shares specified into one token only.\\n    /// @param shares shares burned\\n    /// @param token0Amt Amount of token0 withdrawn.\\n    /// @param token1Amt Amount of token1 withdrawn.\\n    event LogWithdrawColInOneToken(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when liquidity is paid back with shares specified from one token only.\\n    /// @param shares shares burned\\n    /// @param token0Amt Amount of token0 paid back.\\n    /// @param token1Amt Amount of token1 paid back.\\n    event LogPaybackDebtInOneToken(uint shares, uint token0Amt, uint token1Amt);\\n\\n    /// @notice Emitted when internal arbitrage between 2 pools happen\\n    /// @param routing if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback\\n    /// @param amtOut if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow\\n    event LogArbitrage(int routing, uint amtOut);\\n}\\n\",\"keccak256\":\"0x2ccdd6f07486693ec9abccbba5eaaf21ffe1b5436ed961322e663f78b6f1b998\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/helpers/coreHelpers.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { FixedPointMathLib } from \\\"solmate/src/utils/FixedPointMathLib.sol\\\";\\n\\nimport { Variables } from \\\"../../common/variables.sol\\\";\\nimport { ImmutableVariables } from \\\"../immutableVariables.sol\\\";\\nimport { Events } from \\\"../events.sol\\\";\\nimport { ErrorTypes } from \\\"../../../errorTypes.sol\\\";\\nimport { IHook, ICenterPrice } from \\\"../interfaces.sol\\\";\\nimport { LiquiditySlotsLink } from \\\"../../../../../libraries/liquiditySlotsLink.sol\\\";\\nimport { LiquidityCalcs } from \\\"../../../../../libraries/liquidityCalcs.sol\\\";\\nimport { DexSlotsLink } from \\\"../../../../../libraries/dexSlotsLink.sol\\\";\\nimport { DexCalcs } from \\\"../../../../../libraries/dexCalcs.sol\\\";\\nimport { BigMathMinified } from \\\"../../../../../libraries/bigMathMinified.sol\\\";\\nimport { AddressCalcs } from \\\"../../../../../libraries/addressCalcs.sol\\\";\\n\\ninterface IShifting {\\n    /// @dev Calculates the new upper and lower range values during an active range shift\\n    /// @param upperRange_ The target upper range value\\n    /// @param lowerRange_ The target lower range value\\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\\n    /// @return The updated upper range, lower range, and dexVariables2\\n    function _calcRangeShifting(\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint dexVariables2_\\n    ) external payable returns (uint, uint, uint);\\n\\n    /// @dev Calculates the new threshold values during an active threshold shift\\n    /// @param upperThreshold_ The target upper threshold value\\n    /// @param lowerThreshold_ The target lower threshold value\\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\\n    /// @return The updated upper threshold, lower threshold, and dexVariables2\\n    function _calcThresholdShifting(\\n        uint upperThreshold_,\\n        uint lowerThreshold_,\\n        uint dexVariables2_\\n    ) external payable returns (uint, uint, uint);\\n\\n    /// @dev Calculates the new center price during an active center price shift\\n    /// @param dexVariables_ The current state of dex variables\\n    /// @param dexVariables2_ Additional dex variables\\n    /// @return The updated center price\\n    function _calcCenterPrice(\\n        uint dexVariables_,\\n        uint dexVariables2_\\n    ) external payable returns (uint);\\n}\\n\\nabstract contract CoreHelpers is Variables, ImmutableVariables, Events {\\n    using BigMathMinified for uint256;\\n\\n    /// @dev            do any arbitrary call\\n    /// @param target_  Address to which the call needs to be delegated\\n    /// @param data_    Data to execute at the delegated address\\n    function _spell(address target_, bytes memory data_) internal returns (bytes memory response_) {\\n        assembly {\\n            let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)\\n            let size := returndatasize()\\n\\n            response_ := mload(0x40)\\n            mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))\\n            mstore(response_, size)\\n            returndatacopy(add(response_, 0x20), 0, size)\\n\\n            if iszero(succeeded) {\\n                // throw if delegatecall failed\\n                returndatacopy(0x00, 0x00, size)\\n                revert(0x00, size)\\n            }\\n        }\\n    }\\n\\n    /// @dev Given an input amount of asset and pair reserves, returns the maximum output amount of the other asset\\n    /// @param amountIn_ The amount of input asset.\\n    /// @param iReserveIn_ Imaginary token reserve with input amount.\\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\\n    function _getAmountOut(\\n        uint256 amountIn_,\\n        uint iReserveIn_,\\n        uint iReserveOut_\\n    ) internal pure returns (uint256 amountOut_) {\\n        unchecked {\\n            // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\\n            uint256 numerator_ = amountIn_ * iReserveOut_;\\n            uint256 denominator_ = iReserveIn_ + amountIn_;\\n\\n            // Using the swap formula: (AmountIn * iReserveY) / (iReserveX + AmountIn)\\n            amountOut_ = numerator_ / denominator_;\\n        }\\n    }\\n\\n    /// @dev Given an output amount of asset and pair reserves, returns the input amount of the other asset\\n    /// @param amountOut_ Desired output amount of the asset.\\n    /// @param iReserveIn_ Imaginary token reserve of input amount.\\n    /// @param iReserveOut_ Imaginary token reserve of output amount.\\n    function _getAmountIn(\\n        uint256 amountOut_,\\n        uint iReserveIn_,\\n        uint iReserveOut_\\n    ) internal pure returns (uint256 amountIn_) {\\n        // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.\\n        uint256 numerator_ = amountOut_ * iReserveIn_;\\n        uint256 denominator_ = iReserveOut_ - amountOut_;\\n\\n        // Using the swap formula: (AmountOut * iReserveX) / (iReserveY - AmountOut)\\n        amountIn_ = numerator_ / denominator_;\\n    }\\n\\n    /// @param t total amount in\\n    /// @param x imaginary reserves of token out of collateral\\n    /// @param y imaginary reserves of token in of collateral\\n    /// @param x2 imaginary reserves of token out of debt\\n    /// @param y2 imaginary reserves of token in of debt\\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\\n    /// note if a > 0 & a < t then swap will route through both pools\\n    function _swapRoutingIn(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\\n        // Main equations:\\n        // 1. out = x * a / (y + a)\\n        // 2. out2 = x2 * (t - a) / (y2 + (t - a))\\n        // final price should be same\\n        // 3. (y + a) / (x - out) = (y2 + (t - a)) / (x2 - out2)\\n        // derivation: https://chatgpt.com/share/dce6f381-ee5f-4d5f-b6ea-5996e84d5b57\\n\\n        // adding 1e18 precision\\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\\n\\n        a_ = (int(y2 * xyRoot_ + t * xyRoot_) - int(y * x2y2Root_)) / int(xyRoot_ + x2y2Root_);\\n    }\\n\\n    /// @param t total amount out\\n    /// @param x imaginary reserves of token in of collateral\\n    /// @param y imaginary reserves of token out of collateral\\n    /// @param x2 imaginary reserves of token in of debt\\n    /// @param y2 imaginary reserves of token out of debt\\n    /// @return a_ how much swap should go through collateral pool. Remaining will go from debt\\n    /// note if a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool\\n    /// note if a > t then entire trade route through col pool and col pool arbitrage with debt pool\\n    /// note if a > 0 & a < t then swap will route through both pools\\n    function _swapRoutingOut(uint t, uint x, uint y, uint x2, uint y2) internal pure returns (int a_) {\\n        // Main equations:\\n        // 1. in = (x * a) / (y - a)\\n        // 2. in2 = (x2 * (t - a)) / (y2 - (t - a))\\n        // final price should be same\\n        // 3. (y - a) / (x + in) = (y2 - (t - a)) / (x2 + in2)\\n        // derivation: https://chatgpt.com/share/6585bc28-841f-49ec-aea2-1e5c5b7f4fa9\\n\\n        // adding 1e18 precision\\n        uint xyRoot_ = FixedPointMathLib.sqrt(x * y * 1e18);\\n        uint x2y2Root_ = FixedPointMathLib.sqrt(x2 * y2 * 1e18);\\n\\n        // 1e18 precision gets cancelled out in division\\n        a_ = (int(t * xyRoot_ + y * x2y2Root_) - int(y2 * xyRoot_)) / int(xyRoot_ + x2y2Root_);\\n    }\\n\\n    function _utilizationVerify(uint utilizationLimit_, bytes32 exchangePriceSlot_) internal view {\\n        if (utilizationLimit_ < THREE_DECIMALS) {\\n            utilizationLimit_ = utilizationLimit_ * 10;\\n            // extracting utilization of token from liquidity layer\\n            uint liquidityLayerUtilization_ = LIQUIDITY.readFromStorage(exchangePriceSlot_);\\n            liquidityLayerUtilization_ =\\n                (liquidityLayerUtilization_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_UTILIZATION) &\\n                X14;\\n            // Note: this can go slightly above the utilization limit if no update is written to storage at liquidity layer\\n            // if swap was not big enough to go far enough above or any other storage update threshold write cause there\\n            // so just to keep in mind when configuring the actual limit reachable can be utilizationLimit_ + storageUpdateThreshold at Liquidity\\n            if (liquidityLayerUtilization_ > utilizationLimit_)\\n                revert FluidDexError(ErrorTypes.DexT1__LiquidityLayerTokenUtilizationCapReached);\\n        }\\n    }\\n\\n    function _check(uint dexVariables_, uint dexVariables2_) internal {\\n        if (dexVariables_ & 1 == 1) revert FluidDexError(ErrorTypes.DexT1__AlreadyEntered);\\n        if (dexVariables2_ & 3 == 0) revert FluidDexError(ErrorTypes.DexT1__PoolNotInitialized);\\n        // enabling re-entrancy\\n        dexVariables = dexVariables_ | 1;\\n    }\\n\\n    /// @dev if token0 reserves are too low w.r.t token1 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\\n    function _verifyToken0Reserves(\\n        uint token0Reserves_,\\n        uint token1Reserves_,\\n        uint centerPrice_,\\n        uint minLiquidity_\\n    ) internal pure {\\n        if (((token0Reserves_) < ((token1Reserves_ * 1e27) / (centerPrice_ * minLiquidity_)))) {\\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\\n        }\\n    }\\n\\n    /// @dev if token1 reserves are too low w.r.t token0 then revert, this is to avoid edge case scenario and making sure that precision on calculations should be high enough\\n    function _verifyToken1Reserves(\\n        uint token0Reserves_,\\n        uint token1Reserves_,\\n        uint centerPrice_,\\n        uint minLiquidity_\\n    ) internal pure {\\n        if (((token1Reserves_) < ((token0Reserves_ * centerPrice_) / (1e27 * minLiquidity_)))) {\\n            revert FluidDexError(ErrorTypes.DexT1__TokenReservesTooLow);\\n        }\\n    }\\n\\n    function _verifySwapAndNonPerfectActions(uint amountAdjusted_, uint amount_) internal pure {\\n        // after shifting amount should not become 0\\n        // limiting to six decimals which means in case of USDC, USDT it's 1 wei, for WBTC 100 wei, for ETH 1000 gwei\\n        if (amountAdjusted_ < SIX_DECIMALS || amountAdjusted_ > X96 || amount_ < TWO_DECIMALS || amount_ > X128)\\n            revert FluidDexError(ErrorTypes.DexT1__LimitingAmountsSwapAndNonPerfectActions);\\n    }\\n\\n    /// @dev Calculates the new upper and lower range values during an active range shift\\n    /// @param upperRange_ The target upper range value\\n    /// @param lowerRange_ The target lower range value\\n    /// @param dexVariables2_ needed in case shift is ended and we need to update dexVariables2\\n    /// @return The updated upper range, lower range, and dexVariables2\\n    /// @notice This function handles the gradual shifting of range values over time\\n    /// @notice If the shift is complete, it updates the state and clears the shift data\\n    function _calcRangeShifting(\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint dexVariables2_\\n    ) internal returns (uint, uint, uint) {\\n        return\\n            abi.decode(\\n                _spell(\\n                    SHIFT_IMPLEMENTATION,\\n                    abi.encodeWithSelector(\\n                        IShifting._calcRangeShifting.selector,\\n                        upperRange_,\\n                        lowerRange_,\\n                        dexVariables2_\\n                    )\\n                ),\\n                (uint, uint, uint)\\n            );\\n    }\\n\\n    /// @dev Calculates the new upper and lower threshold values during an active threshold shift\\n    /// @param upperThreshold_ The target upper threshold value\\n    /// @param lowerThreshold_ The target lower threshold value\\n    /// @param thresholdTime_ The time passed since shifting started\\n    /// @return The updated upper threshold, lower threshold, and threshold time\\n    /// @notice This function handles the gradual shifting of threshold values over time\\n    /// @notice If the shift is complete, it updates the state and clears the shift data\\n    function _calcThresholdShifting(\\n        uint upperThreshold_,\\n        uint lowerThreshold_,\\n        uint thresholdTime_\\n    ) internal returns (uint, uint, uint) {\\n        return\\n            abi.decode(\\n                _spell(\\n                    SHIFT_IMPLEMENTATION,\\n                    abi.encodeWithSelector(\\n                        IShifting._calcThresholdShifting.selector,\\n                        upperThreshold_,\\n                        lowerThreshold_,\\n                        thresholdTime_\\n                    )\\n                ),\\n                (uint, uint, uint)\\n            );\\n    }\\n\\n    /// @dev Calculates the new center price during an active price shift\\n    /// @param dexVariables_ The current state of dex variables\\n    /// @param dexVariables2_ Additional dex variables\\n    /// @return newCenterPrice_ The updated center price\\n    /// @notice This function gradually shifts the center price towards a new target price over time\\n    /// @notice It uses an external price source (via ICenterPrice) to determine the target price\\n    /// @notice The shift continues until the current price reaches the target, or the shift duration ends\\n    /// @notice Once the shift is complete, it updates the state and clears the shift data\\n    /// @notice The shift rate is dynamic and depends on:\\n    /// @notice - Time remaining in the shift duration\\n    /// @notice - The new center price (fetched externally, which may change)\\n    /// @notice - The current (old) center price\\n    /// @notice This results in a fuzzy shifting mechanism where the rate can change as these parameters evolve\\n    /// @notice The externally fetched new center price is expected to not differ significantly from the last externally fetched center price\\n    function _calcCenterPrice(uint dexVariables_, uint dexVariables2_) internal returns (uint newCenterPrice_) {\\n        return\\n            abi.decode(\\n                _spell(\\n                    SHIFT_IMPLEMENTATION,\\n                    abi.encodeWithSelector(IShifting._calcCenterPrice.selector, dexVariables_, dexVariables2_)\\n                ),\\n                (uint)\\n            );\\n    }\\n\\n    /// @notice Calculates and returns the current prices and exchange prices for the pool\\n    /// @param dexVariables_ The first set of DEX variables containing various pool parameters\\n    /// @param dexVariables2_ The second set of DEX variables containing additional pool parameters\\n    /// @return pex_ A struct containing the calculated prices and exchange prices:\\n    ///         - pex_.lastStoredPrice: The last stored price in 1e27 decimals\\n    ///         - pex_.centerPrice: The calculated or fetched center price in 1e27 decimals\\n    ///         - pex_.upperRange: The upper range price limit in 1e27 decimals\\n    ///         - pex_.lowerRange: The lower range price limit in 1e27 decimals\\n    ///         - pex_.geometricMean: The geometric mean of upper range & lower range in 1e27 decimals\\n    ///         - pex_.supplyToken0ExchangePrice: The current exchange price for supplying token0\\n    ///         - pex_.borrowToken0ExchangePrice: The current exchange price for borrowing token0\\n    ///         - pex_.supplyToken1ExchangePrice: The current exchange price for supplying token1\\n    ///         - pex_.borrowToken1ExchangePrice: The current exchange price for borrowing token1\\n    /// @dev This function performs the following operations:\\n    ///      1. Determines the center price (either from storage, external source, or calculated)\\n    ///      2. Retrieves the last stored price from dexVariables_\\n    ///      3. Calculates the upper and lower range prices based on the center price and range percentages\\n    ///      4. Checks if rebalancing is needed based on threshold settings\\n    ///      5. Adjusts prices if necessary based on the time elapsed and threshold conditions\\n    ///      6. Update the dexVariables2_ if changes were made\\n    ///      7. Returns the calculated prices and exchange prices in the PricesAndExchangePrice struct\\n    function _getPricesAndExchangePrices(\\n        uint dexVariables_,\\n        uint dexVariables2_\\n    ) internal returns (PricesAndExchangePrice memory pex_) {\\n        uint centerPrice_;\\n\\n        if (((dexVariables2_ >> 248) & 1) == 0) {\\n            // centerPrice_ => center price hook\\n            centerPrice_ = (dexVariables2_ >> 112) & X30;\\n            if (centerPrice_ == 0) {\\n                centerPrice_ = (dexVariables_ >> 81) & X40;\\n                centerPrice_ = (centerPrice_ >> DEFAULT_EXPONENT_SIZE) << (centerPrice_ & DEFAULT_EXPONENT_MASK);\\n            } else {\\n                // center price should be fetched from external source. For exmaple, in case of wstETH <> ETH pool,\\n                // we would want the center price to be pegged to wstETH exchange rate into ETH\\n                centerPrice_ = ICenterPrice(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, centerPrice_)).centerPrice();\\n            }\\n        } else {\\n            // an active centerPrice_ shift is going on\\n            centerPrice_ = _calcCenterPrice(dexVariables_, dexVariables2_);\\n        }\\n\\n        uint lastStoredPrice_ = (dexVariables_ >> 41) & X40;\\n        lastStoredPrice_ = (lastStoredPrice_ >> DEFAULT_EXPONENT_SIZE) << (lastStoredPrice_ & DEFAULT_EXPONENT_MASK);\\n\\n        uint upperRange_ = ((dexVariables2_ >> 27) & X20);\\n        uint lowerRange_ = ((dexVariables2_ >> 47) & X20);\\n        if (((dexVariables2_ >> 26) & 1) == 1) {\\n            // an active range shift is going on\\n            (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(upperRange_, lowerRange_, dexVariables2_);\\n        }\\n\\n        unchecked {\\n            // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\\n            // 1% = 1e4, 100% = 1e6\\n            upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\\n            // 1% = 1e4, 100% = 1e6\\n            lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\\n        }\\n\\n        bool changed_;\\n        {\\n            // goal will be to keep threshold percents 0 if center price is fetched from external source\\n            // checking if threshold are set non 0 then only rebalancing is on\\n            if (((dexVariables2_ >> 68) & X20) > 0) {\\n                uint upperThreshold_ = (dexVariables2_ >> 68) & X10;\\n                uint lowerThreshold_ = (dexVariables2_ >> 78) & X10;\\n                uint shiftingTime_ = (dexVariables2_ >> 88) & X24;\\n                if (((dexVariables2_ >> 67) & 1) == 1) {\\n                    // if active shift is going on for threshold then calculate threshold real time\\n                    (upperThreshold_, lowerThreshold_, shiftingTime_) = _calcThresholdShifting(\\n                        upperThreshold_,\\n                        lowerThreshold_,\\n                        shiftingTime_\\n                    );\\n                }\\n\\n                unchecked {\\n                    if (\\n                        lastStoredPrice_ >\\n                        (centerPrice_ +\\n                            ((upperRange_ - centerPrice_) * (THREE_DECIMALS - upperThreshold_)) /\\n                            THREE_DECIMALS)\\n                    ) {\\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\\n                        // price shifting towards upper range\\n                        if (timeElapsed_ < shiftingTime_) {\\n                            centerPrice_ = centerPrice_ + ((upperRange_ - centerPrice_) * timeElapsed_) / shiftingTime_;\\n                        } else {\\n                            // 100% price shifted\\n                            centerPrice_ = upperRange_;\\n                        }\\n                        changed_ = true;\\n                    } else if (\\n                        lastStoredPrice_ <\\n                        (centerPrice_ -\\n                            ((centerPrice_ - lowerRange_) * (THREE_DECIMALS - lowerThreshold_)) /\\n                            THREE_DECIMALS)\\n                    ) {\\n                        uint timeElapsed_ = block.timestamp - ((dexVariables_ >> 121) & X33);\\n                        // price shifting towards lower range\\n                        if (timeElapsed_ < shiftingTime_) {\\n                            centerPrice_ = centerPrice_ - ((centerPrice_ - lowerRange_) * timeElapsed_) / shiftingTime_;\\n                        } else {\\n                            // 100% price shifted\\n                            centerPrice_ = lowerRange_;\\n                        }\\n                        changed_ = true;\\n                    }\\n                }\\n            }\\n        }\\n\\n        // temp_ => max center price\\n        uint temp_ = (dexVariables2_ >> 172) & X28;\\n        temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n        if (centerPrice_ > temp_) {\\n            // if center price is greater than max center price\\n            centerPrice_ = temp_;\\n            changed_ = true;\\n        } else {\\n            // check if center price is less than min center price\\n            // temp_ => min center price\\n            temp_ = (dexVariables2_ >> 200) & X28;\\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n            if (centerPrice_ < temp_) {\\n                centerPrice_ = temp_;\\n                changed_ = true;\\n            }\\n        }\\n\\n        // if centerPrice_ is changed then calculating upper and lower range again\\n        if (changed_) {\\n            upperRange_ = ((dexVariables2_ >> 27) & X20);\\n            lowerRange_ = ((dexVariables2_ >> 47) & X20);\\n            if (((dexVariables2_ >> 26) & 1) == 1) {\\n                (upperRange_, lowerRange_, dexVariables2_) = _calcRangeShifting(\\n                    upperRange_,\\n                    lowerRange_,\\n                    dexVariables2_\\n                );\\n            }\\n\\n            unchecked {\\n                // adding into unchecked because upperRange_ & lowerRange_ can only be > 0 & < SIX_DECIMALS\\n                // 1% = 1e4, 100% = 1e6\\n                upperRange_ = (centerPrice_ * SIX_DECIMALS) / (SIX_DECIMALS - upperRange_);\\n                // 1% = 1e4, 100% = 1e6\\n                lowerRange_ = (centerPrice_ * (SIX_DECIMALS - lowerRange_)) / SIX_DECIMALS;\\n            }\\n        }\\n\\n        pex_.lastStoredPrice = lastStoredPrice_;\\n        pex_.centerPrice = centerPrice_;\\n        pex_.upperRange = upperRange_;\\n        pex_.lowerRange = lowerRange_;\\n\\n        unchecked {\\n            if (upperRange_ < 1e38) {\\n                // 1e38 * 1e38 = 1e76 which is less than max uint limit\\n                pex_.geometricMean = FixedPointMathLib.sqrt(upperRange_ * lowerRange_);\\n            } else {\\n                // upperRange_ price is pretty large hence lowerRange_ will also be pretty large\\n                pex_.geometricMean = FixedPointMathLib.sqrt((upperRange_ / 1e18) * (lowerRange_ / 1e18)) * 1e18;\\n            }\\n        }\\n\\n        // Exchange price will remain same as Liquidity Layer\\n        (pex_.supplyToken0ExchangePrice, pex_.borrowToken0ExchangePrice) = LiquidityCalcs.calcExchangePrices(\\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_0_SLOT)\\n        );\\n\\n        (pex_.supplyToken1ExchangePrice, pex_.borrowToken1ExchangePrice) = LiquidityCalcs.calcExchangePrices(\\n            LIQUIDITY.readFromStorage(EXCHANGE_PRICE_TOKEN_1_SLOT)\\n        );\\n    }\\n\\n    /// @dev getting reserves outside range.\\n    /// @param gp_ is geometric mean pricing of upper percent & lower percent\\n    /// @param pa_ price of upper range or lower range\\n    /// @param rx_ real reserves of token0 or token1\\n    /// @param ry_ whatever is rx_ the other will be ry_\\n    function _calculateReservesOutsideRange(\\n        uint gp_,\\n        uint pa_,\\n        uint rx_,\\n        uint ry_\\n    ) internal pure returns (uint xa_, uint yb_) {\\n        // equations we have:\\n        // 1. x*y = k\\n        // 2. xa*ya = k\\n        // 3. xb*yb = k\\n        // 4. Pa = ya / xa = upperRange_ (known)\\n        // 5. Pb = yb / xb = lowerRange_ (known)\\n        // 6. x - xa = rx = real reserve of x (known)\\n        // 7. y - yb = ry = real reserve of y (known)\\n        // With solving we get:\\n        // ((Pa*Pb)^(1/2) - Pa)*xa^2 + (rx * (Pa*Pb)^(1/2) + ry)*xa + rx*ry = 0\\n        // yb = yb = xa * (Pa * Pb)^(1/2)\\n\\n        // xa = (GP⋅rx + ry + (-rx⋅ry⋅4⋅(GP - Pa) + (GP⋅rx + ry)^2)^0.5) / (2Pa - 2GP)\\n        // multiply entire equation by 1e27 to remove the price decimals precision of 1e27\\n        // xa = (GP⋅rx + ry⋅1e27 + (rx⋅ry⋅4⋅(Pa - GP)⋅1e27 + (GP⋅rx + ry⋅1e27)^2)^0.5) / 2*(Pa - GP)\\n        // dividing the equation with 2*(Pa - GP). Pa is always > GP so answer will be positive.\\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅4⋅(Pa - GP)⋅1e27) / 4*(Pa - GP)^2) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\\n        // xa = (((GP⋅rx + ry⋅1e27) / 2*(Pa - GP)) + (((rx⋅ry⋅1e27) / (Pa - GP)) + ((GP⋅rx + ry⋅1e27) / 2*(Pa - GP))^2)^0.5)\\n\\n        // dividing in 3 parts for simplification:\\n        // part1 = (Pa - GP)\\n        // part2 = (GP⋅rx + ry⋅1e27) / (2*part1)\\n        // part3 = rx⋅ry\\n        // note: part1 will almost always be < 1e28 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e29\\n        uint p1_ = pa_ - gp_;\\n        uint p2_ = ((gp_ * rx_) + (ry_ * 1e27)) / (2 * p1_);\\n        uint p3_ = rx_ * ry_;\\n        // to avoid overflowing\\n        p3_ = (p3_ < 1e50) ? ((p3_ * 1e27) / p1_) : (p3_ / p1_) * 1e27;\\n\\n        // xa = part2 + (part3 + (part2 * part2))^(1/2)\\n        // yb = xa_ * gp_\\n        xa_ = p2_ + FixedPointMathLib.sqrt((p3_ + (p2_ * p2_)));\\n        yb_ = (xa_ * gp_) / 1e27;\\n    }\\n\\n    /// @dev Retrieves collateral amount from liquidity layer for a given token\\n    /// @param supplyTokenSlot_ The storage slot for the supply token data\\n    /// @param tokenExchangePrice_ The exchange price of the token\\n    /// @param isToken0_ Boolean indicating if the token is token0 (true) or token1 (false)\\n    /// @return tokenSupply_ The calculated liquidity collateral amount\\n    function _getLiquidityCollateral(\\n        bytes32 supplyTokenSlot_,\\n        uint tokenExchangePrice_,\\n        bool isToken0_\\n    ) internal view returns (uint tokenSupply_) {\\n        uint tokenSupplyData_ = LIQUIDITY.readFromStorage(supplyTokenSlot_);\\n        tokenSupply_ = (tokenSupplyData_ >> LiquiditySlotsLink.BITS_USER_SUPPLY_AMOUNT) & X64;\\n        tokenSupply_ = (tokenSupply_ >> DEFAULT_EXPONENT_SIZE) << (tokenSupply_ & DEFAULT_EXPONENT_MASK);\\n\\n        if (tokenSupplyData_ & 1 == 1) {\\n            // supply with interest is on\\n            unchecked {\\n                tokenSupply_ = (tokenSupply_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\\n            }\\n        }\\n\\n        unchecked {\\n            tokenSupply_ = isToken0_\\n                ? ((tokenSupply_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\\n                : ((tokenSupply_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\\n        }\\n    }\\n\\n    /// @notice Calculates the real and imaginary reserves for collateral tokens\\n    /// @dev This function retrieves the supply of both tokens from the liquidity layer,\\n    ///      adjusts them based on exchange prices, and calculates imaginary reserves\\n    ///      based on the geometric mean and price range\\n    /// @param geometricMean_ The geometric mean of the token prices\\n    /// @param upperRange_ The upper price range\\n    /// @param lowerRange_ The lower price range\\n    /// @param token0SupplyExchangePrice_ The exchange price for token0 from liquidity layer\\n    /// @param token1SupplyExchangePrice_ The exchange price for token1 from liquidity layer\\n    /// @return c_ A struct containing the calculated real and imaginary reserves for both tokens:\\n    ///         - token0RealReserves: The real reserves of token0\\n    ///         - token1RealReserves: The real reserves of token1\\n    ///         - token0ImaginaryReserves: The imaginary reserves of token0\\n    ///         - token1ImaginaryReserves: The imaginary reserves of token1\\n    function _getCollateralReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0SupplyExchangePrice_,\\n        uint token1SupplyExchangePrice_\\n    ) internal view returns (CollateralReserves memory c_) {\\n        uint token0Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_0_SLOT, token0SupplyExchangePrice_, true);\\n        uint token1Supply_ = _getLiquidityCollateral(SUPPLY_TOKEN_1_SLOT, token1SupplyExchangePrice_, false);\\n\\n        if (geometricMean_ < 1e27) {\\n            (c_.token0ImaginaryReserves, c_.token1ImaginaryReserves) = _calculateReservesOutsideRange(\\n                geometricMean_,\\n                upperRange_,\\n                token0Supply_,\\n                token1Supply_\\n            );\\n        } else {\\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\\n            // 1 / geometricMean for new geometricMean\\n            // 1 / lowerRange will become upper range\\n            // 1 / upperRange will become lower range\\n            (c_.token1ImaginaryReserves, c_.token0ImaginaryReserves) = _calculateReservesOutsideRange(\\n                (1e54 / geometricMean_),\\n                (1e54 / lowerRange_),\\n                token1Supply_,\\n                token0Supply_\\n            );\\n        }\\n\\n        c_.token0RealReserves = token0Supply_;\\n        c_.token1RealReserves = token1Supply_;\\n        unchecked {\\n            c_.token0ImaginaryReserves += token0Supply_;\\n            c_.token1ImaginaryReserves += token1Supply_;\\n        }\\n    }\\n\\n    /// @notice Calculates the real and imaginary debt reserves for both tokens\\n    /// @dev This function uses a quadratic equation to determine the debt reserves\\n    ///      based on the geometric mean price and the current debt amounts\\n    /// @param gp_ The geometric mean price of upper range & lower range\\n    /// @param pb_ The price of lower range\\n    /// @param dx_ The debt amount of one token\\n    /// @param dy_ The debt amount of the other token\\n    /// @return rx_ The real debt reserve of the first token\\n    /// @return ry_ The real debt reserve of the second token\\n    /// @return irx_ The imaginary debt reserve of the first token\\n    /// @return iry_ The imaginary debt reserve of the second token\\n    function _calculateDebtReserves(\\n        uint gp_,\\n        uint pb_,\\n        uint dx_,\\n        uint dy_\\n    ) internal pure returns (uint rx_, uint ry_, uint irx_, uint iry_) {\\n        // Assigning letter to knowns:\\n        // c = debtA\\n        // d = debtB\\n        // e = upperPrice\\n        // f = lowerPrice\\n        // g = upperPrice^1/2\\n        // h = lowerPrice^1/2\\n\\n        // c = 1\\n        // d = 2000\\n        // e = 2222.222222\\n        // f = 1800\\n        // g = 2222.222222^1/2\\n        // h = 1800^1/2\\n\\n        // Assigning letter to unknowns:\\n        // w = realDebtReserveA\\n        // x = realDebtReserveB\\n        // y = imaginaryDebtReserveA\\n        // z = imaginaryDebtReserveB\\n        // k = k\\n\\n        // below quadratic will give answer of realDebtReserveB\\n        // A, B, C of quadratic equation:\\n        // A = h\\n        // B = dh - cfg\\n        // C = -cfdh\\n\\n        // A = lowerPrice^1/2\\n        // B = debtB⋅lowerPrice^1/2 - debtA⋅lowerPrice⋅upperPrice^1/2\\n        // C = -(debtA⋅lowerPrice⋅debtB⋅lowerPrice^1/2)\\n\\n        // x = (cfg − dh + (4cdf(h^2)+(cfg−dh)^2))^(1/2)) / 2h\\n        // simplifying dividing by h, note h = f^1/2\\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((4⋅c⋅d⋅f⋅f) / (4h^2) + ((c⋅f⋅g) / 2h − (d⋅h) / 2h)^2))^(1/2))\\n        // x = ((c⋅g⋅(f^1/2) − d) / 2 + ((c⋅d⋅f) + ((c⋅g⋅(f^1/2) − d) / 2)^2))^(1/2))\\n\\n        // dividing in 3 parts for simplification:\\n        // part1 = (c⋅g⋅(f^1/2) − d) / 2\\n        // part2 = (c⋅d⋅f)\\n        // x = (part1 + (part2 + part1^2)^(1/2))\\n        // note: part1 will almost always be < 1e27 but in case it goes above 1e27 then it's extremely unlikely it'll go above > 1e28\\n\\n        // part1 = ((debtA * upperPrice^1/2 * lowerPrice^1/2) - debtB) / 2\\n        // note: upperPrice^1/2 * lowerPrice^1/2 = geometric mean\\n        // part1 = ((debtA * geometricMean) - debtB) / 2\\n        // part2 = debtA * debtB * lowerPrice\\n\\n        // converting decimals properly as price is in 1e27 decimals\\n        // part1 = ((debtA * geometricMean) - (debtB * 1e27)) / (2 * 1e27)\\n        // part2 = (debtA * debtB * lowerPrice) / 1e27\\n        // final x equals:\\n        // x = (part1 + (part2 + part1^2)^(1/2))\\n        int p1_ = (int(dx_ * gp_) - int(dy_ * 1e27)) / (2 * 1e27);\\n        uint p2_ = (dx_ * dy_);\\n        p2_ = p2_ < 1e50 ? (p2_ * pb_) / 1e27 : (p2_ / 1e27) * pb_;\\n        ry_ = uint(p1_ + int(FixedPointMathLib.sqrt((p2_ + uint(p1_ * p1_)))));\\n\\n        // finding z:\\n        // x^2 - zx + cfz = 0\\n        // z*(x - cf) = x^2\\n        // z = x^2 / (x - cf)\\n        // z = x^2 / (x - debtA * lowerPrice)\\n        // converting decimals properly as price is in 1e27 decimals\\n        // z = (x^2 * 1e27) / ((x * 1e27) - (debtA * lowerPrice))\\n\\n        iry_ = ((ry_ * 1e27) - (dx_ * pb_));\\n        if (iry_ < SIX_DECIMALS) {\\n            // almost impossible situation to ever get here\\n            revert FluidDexError(ErrorTypes.DexT1__DebtReservesTooLow);\\n        }\\n        if (ry_ < 1e25) {\\n            iry_ = (ry_ * ry_ * 1e27) / iry_;\\n        } else {\\n            // note: it can never result in negative as final result will always be in positive\\n            iry_ = (ry_ * ry_) / (iry_ / 1e27);\\n        }\\n\\n        // finding y\\n        // x = z * c / (y + c)\\n        // y + c = z * c / x\\n        // y = (z * c / x) - c\\n        // y = (z * debtA / x) - debtA\\n        irx_ = ((iry_ * dx_) / ry_) - dx_;\\n\\n        // finding w\\n        // w = y * d / (z + d)\\n        // w = (y * debtB) / (z + debtB)\\n        rx_ = (irx_ * dy_) / (iry_ + dy_);\\n    }\\n\\n    /// @notice Calculates the debt amount for a given token from liquidity layer\\n    /// @param borrowTokenSlot_ The storage slot for the token's borrow data\\n    /// @param tokenExchangePrice_ The current exchange price of the token\\n    /// @param isToken0_ Boolean indicating if this is for token0 (true) or token1 (false)\\n    /// @return tokenDebt_ The calculated debt amount for the token\\n    function _getLiquidityDebt(\\n        bytes32 borrowTokenSlot_,\\n        uint tokenExchangePrice_,\\n        bool isToken0_\\n    ) internal view returns (uint tokenDebt_) {\\n        uint tokenBorrowData_ = LIQUIDITY.readFromStorage(borrowTokenSlot_);\\n\\n        tokenDebt_ = (tokenBorrowData_ >> LiquiditySlotsLink.BITS_USER_BORROW_AMOUNT) & X64;\\n        tokenDebt_ = (tokenDebt_ >> 8) << (tokenDebt_ & X8);\\n\\n        if (tokenBorrowData_ & 1 == 1) {\\n            // borrow with interest is on\\n            unchecked {\\n                tokenDebt_ = (tokenDebt_ * tokenExchangePrice_) / LiquidityCalcs.EXCHANGE_PRICES_PRECISION;\\n            }\\n        }\\n\\n        unchecked {\\n            tokenDebt_ = isToken0_\\n                ? ((tokenDebt_ * TOKEN_0_NUMERATOR_PRECISION) / TOKEN_0_DENOMINATOR_PRECISION)\\n                : ((tokenDebt_ * TOKEN_1_NUMERATOR_PRECISION) / TOKEN_1_DENOMINATOR_PRECISION);\\n        }\\n    }\\n\\n    /// @notice Calculates the debt reserves for both tokens\\n    /// @param geometricMean_ The geometric mean of the upper and lower price ranges\\n    /// @param upperRange_ The upper price range\\n    /// @param lowerRange_ The lower price range\\n    /// @param token0BorrowExchangePrice_ The exchange price of token0 from liquidity layer\\n    /// @param token1BorrowExchangePrice_ The exchange price of token1 from liquidity layer\\n    /// @return d_ The calculated debt reserves for both tokens, containing:\\n    ///         - token0Debt: The debt amount of token0\\n    ///         - token1Debt: The debt amount of token1\\n    ///         - token0RealReserves: The real reserves of token0 derived from token1 debt\\n    ///         - token1RealReserves: The real reserves of token1 derived from token0 debt\\n    ///         - token0ImaginaryReserves: The imaginary debt reserves of token0\\n    ///         - token1ImaginaryReserves: The imaginary debt reserves of token1\\n    function _getDebtReserves(\\n        uint geometricMean_,\\n        uint upperRange_,\\n        uint lowerRange_,\\n        uint token0BorrowExchangePrice_,\\n        uint token1BorrowExchangePrice_\\n    ) internal view returns (DebtReserves memory d_) {\\n        uint token0Debt_ = _getLiquidityDebt(BORROW_TOKEN_0_SLOT, token0BorrowExchangePrice_, true);\\n        uint token1Debt_ = _getLiquidityDebt(BORROW_TOKEN_1_SLOT, token1BorrowExchangePrice_, false);\\n\\n        d_.token0Debt = token0Debt_;\\n        d_.token1Debt = token1Debt_;\\n\\n        if (geometricMean_ < 1e27) {\\n            (\\n                d_.token0RealReserves,\\n                d_.token1RealReserves,\\n                d_.token0ImaginaryReserves,\\n                d_.token1ImaginaryReserves\\n            ) = _calculateDebtReserves(geometricMean_, lowerRange_, token0Debt_, token1Debt_);\\n        } else {\\n            // inversing, something like `xy = k` so for calculation we are making everything related to x into y & y into x\\n            // 1 / geometricMean for new geometricMean\\n            // 1 / lowerRange will become upper range\\n            // 1 / upperRange will become lower range\\n            (\\n                d_.token1RealReserves,\\n                d_.token0RealReserves,\\n                d_.token1ImaginaryReserves,\\n                d_.token0ImaginaryReserves\\n            ) = _calculateDebtReserves((1e54 / geometricMean_), (1e54 / upperRange_), token1Debt_, token0Debt_);\\n        }\\n    }\\n\\n    function _priceDiffCheck(uint oldPrice_, uint newPrice_) internal pure returns (int priceDiff_) {\\n        // check newPrice_ & oldPrice_ difference should not be more than 5%\\n        // old price w.r.t new price\\n        priceDiff_ = int(ORACLE_PRECISION) - int((oldPrice_ * ORACLE_PRECISION) / newPrice_);\\n\\n        unchecked {\\n            if ((priceDiff_ > int(ORACLE_LIMIT)) || (priceDiff_ < -int(ORACLE_LIMIT))) {\\n                // if oracle price difference is more than 5% then revert\\n                // in 1 swap price should only change by <= 5%\\n                // if a total fall by let's say 8% then in current block price can only fall by 5% and\\n                // in next block it'll fall the remaining 3%\\n                revert FluidDexError(ErrorTypes.DexT1__OracleUpdateHugeSwapDiff);\\n            }\\n        }\\n    }\\n\\n    function _updateOracle(uint newPrice_, uint centerPrice_, uint dexVariables_) internal returns (uint) {\\n        // time difference between last & current swap\\n        uint timeDiff_ = block.timestamp - ((dexVariables_ >> 121) & X33);\\n        uint temp_;\\n        uint temp2_;\\n        uint temp3_;\\n\\n        if (timeDiff_ == 0) {\\n            // doesn't matter if oracle is on or off when timediff = 0 code for both is same\\n\\n            // temp_ => oldCenterPrice\\n            temp_ = (dexVariables_ >> 81) & X40;\\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n            // Ensure that the center price is within the acceptable range of the old center price if it's not the first swap in the same block\\n            unchecked {\\n                if (\\n                    (centerPrice_ < (((EIGHT_DECIMALS - 1) * temp_) / EIGHT_DECIMALS)) ||\\n                    (centerPrice_ > (((EIGHT_DECIMALS + 1) * temp_) / EIGHT_DECIMALS))\\n                ) {\\n                    revert FluidDexError(ErrorTypes.DexT1__CenterPriceOutOfRange);\\n                }\\n            }\\n\\n            // olderPrice_ => temp_\\n            temp_ = (dexVariables_ >> 1) & X40;\\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n            _priceDiffCheck(temp_, newPrice_);\\n\\n            // 2nd swap in same block no need to update anything around oracle, only need to update last swap price in dexVariables\\n            return ((dexVariables_ & 0xfffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff) |\\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41));\\n        }\\n\\n        if (((dexVariables_ >> 195) & 1) == 0) {\\n            // if oracle is not active then just returning updated DEX variable\\n            temp_ = ((dexVariables_ >> 41) & X40);\\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n            _priceDiffCheck(temp_, newPrice_);\\n            \\n            return ((dexVariables_ & 0xfffffffffffffffffffffffffc00000000000000000000000000000000000001) |\\n                (((dexVariables_ >> 41) & X40) << 1) |\\n                (newPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\\n                (centerPrice_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\\n                (block.timestamp << 121));\\n        } else {\\n            // oracle is active hence update oracle\\n\\n            // olderPrice_ => temp_\\n            temp_ = (dexVariables_ >> 1) & X40;\\n            temp_ = (temp_ >> DEFAULT_EXPONENT_SIZE) << (temp_ & DEFAULT_EXPONENT_MASK);\\n\\n            // oldPrice_ => temp2_\\n            temp2_ = (dexVariables_ >> 41) & X40;\\n            temp2_ = (temp2_ >> DEFAULT_EXPONENT_SIZE) << (temp2_ & DEFAULT_EXPONENT_MASK);\\n\\n            int priceDiff_ = _priceDiffCheck(temp2_, newPrice_);\\n\\n            unchecked {\\n                // older price w.r.t old price\\n                priceDiff_ = int(ORACLE_PRECISION) - int((temp_ * ORACLE_PRECISION) / temp2_);\\n            }\\n\\n            // priceDiffInPercentAndSign_ => temp3_\\n            // priceDiff_ will always be lower than ORACLE_LIMIT due to above check\\n            unchecked {\\n                if (priceDiff_ < 0) {\\n                    temp3_ = ((uint(-priceDiff_) * X22) / ORACLE_LIMIT) << 1;\\n                } else {\\n                    // if greater than or equal to 0 then make sign flag 1\\n                    temp3_ = (((uint(priceDiff_) * X22) / ORACLE_LIMIT) << 1) | 1;\\n                }\\n            }\\n\\n            if (timeDiff_ > X22) {\\n                // if time difference is this then that means DEX has been inactive ~45 days\\n                // that means oracle price of this DEX should not be used.\\n                timeDiff_ = X22;\\n            }\\n\\n            // temp_ => lastTimeDiff_\\n            temp_ = (dexVariables_ >> 154) & X22;\\n            uint nextOracleSlot_ = ((dexVariables_ >> 176) & X3);\\n            uint oracleMap_ = (dexVariables_ >> 179) & X16;\\n            if (temp_ > X9) {\\n                if (nextOracleSlot_ > 0) {\\n                    // if greater than 0 then current slot has 2 or more oracle slot empty\\n                    // First 9 bits are of time, so not using that\\n                    temp3_ = (temp3_ << 41) | (temp_ << 9);\\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (--nextOracleSlot_ * 32));\\n                    if (nextOracleSlot_ > 0) {\\n                        --nextOracleSlot_;\\n                    } else {\\n                        // if == 0 that means the oracle slots will get filled and shift to next oracle map\\n                        nextOracleSlot_ = 7;\\n                        unchecked {\\n                            oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\\n                        }\\n                        _oracle[oracleMap_] = 0;\\n                    }\\n                } else {\\n                    // if == 0\\n                    // then seconds will be in last map\\n                    // precision will be in last map + 1\\n                    // Storing precision & sign slot in first precision & sign slot and leaving time slot empty\\n                    temp3_ = temp3_ << 9;\\n                    _oracle[oracleMap_] = _oracle[oracleMap_] | temp3_;\\n                    nextOracleSlot_ = 6; // storing 6 here as 7 is going to occupied right now\\n                    unchecked {\\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\\n                    }\\n                    // Storing time in 2nd precision & sign and leaving time slot empty\\n                    _oracle[oracleMap_] = temp_ << ((7 * 32) + 9);\\n                }\\n            } else {\\n                temp3_ = (temp3_ << 9) | temp_;\\n                unchecked {\\n                    if (nextOracleSlot_ < 7) {\\n                        _oracle[oracleMap_] = _oracle[oracleMap_] | (temp3_ << (nextOracleSlot_ * 32));\\n                    } else {\\n                        _oracle[oracleMap_] = temp3_ << ((7 * 32));\\n                    }\\n                }\\n                if (nextOracleSlot_ > 0) {\\n                    --nextOracleSlot_;\\n                } else {\\n                    nextOracleSlot_ = 7;\\n                    unchecked {\\n                        oracleMap_ = (oracleMap_ + 1) % TOTAL_ORACLE_MAPPING;\\n                    }\\n                    _oracle[oracleMap_] = 0;\\n                }\\n            }\\n\\n            // doing this due to stack too deep error when using params memory variables\\n            temp_ = newPrice_;\\n            temp2_ = centerPrice_;\\n            temp3_ = dexVariables_;\\n\\n            // then update last price\\n            return ((temp3_ & 0xfffffffffffffff8000000000000000000000000000000000000000000000001) |\\n                (((temp3_ >> 41) & X40) << 1) |\\n                (temp_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 41) |\\n                (temp2_.toBigNumber(32, 8, BigMathMinified.ROUND_DOWN) << 81) |\\n                (block.timestamp << 121) |\\n                (timeDiff_ << 154) |\\n                (nextOracleSlot_ << 176) |\\n                (oracleMap_ << 179));\\n        }\\n    }\\n\\n    function _hookVerify(uint hookAddress_, uint mode_, bool swap0to1_, uint price_) internal {\\n        try\\n            IHook(AddressCalcs.addressCalc(DEPLOYER_CONTRACT, hookAddress_)).dexPrice(\\n                mode_,\\n                swap0to1_,\\n                TOKEN_0,\\n                TOKEN_1,\\n                price_\\n            )\\n        returns (bool isOk_) {\\n            if (!isOk_) revert FluidDexError(ErrorTypes.DexT1__HookReturnedFalse);\\n        } catch (bytes memory /*lowLevelData*/) {\\n            // skip checking hook nothing\\n        }\\n    }\\n\\n    function _updateSupplyShares(uint newTotalShares_) internal {\\n        uint totalSupplyShares_ = _totalSupplyShares;\\n\\n        // new total shares are greater than old total shares && new total shares are greater than max supply shares\\n        if (\\n            (newTotalShares_ > (totalSupplyShares_ & X128)) && \\n            newTotalShares_ > (totalSupplyShares_ >> 128)\\n        ) {\\n            revert FluidDexError(ErrorTypes.DexT1__SupplySharesOverflow);\\n        }\\n\\n        // keeping max supply shares intact\\n        _totalSupplyShares = ((totalSupplyShares_ >> 128) << 128) | newTotalShares_;\\n    }\\n\\n    function _updateBorrowShares(uint newTotalShares_) internal {\\n        uint totalBorrowShares_ = _totalBorrowShares;\\n\\n        // new total shares are greater than old total shares && new total shares are greater than max borrow shares\\n        if (\\n            (newTotalShares_ > (totalBorrowShares_ & X128)) && \\n            newTotalShares_ > (totalBorrowShares_ >> 128)\\n        ) {\\n            revert FluidDexError(ErrorTypes.DexT1__BorrowSharesOverflow);\\n        }\\n\\n        // keeping max borrow shares intact\\n        _totalBorrowShares = ((totalBorrowShares_ >> 128) << 128) | newTotalShares_;\\n    }\\n\\n    constructor(ConstantViews memory constantViews_) ImmutableVariables(constantViews_) {}\\n}\\n\",\"keccak256\":\"0xb9758a62a536b0897d7da4f99ef7e8538ca339022394f757fcda71fc5ae85c80\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/immutableVariables.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nimport { IFluidLiquidity } from \\\"../../../../liquidity/interfaces/iLiquidity.sol\\\";\\nimport { Structs } from \\\"./structs.sol\\\";\\nimport { ConstantVariables } from \\\"../common/constantVariables.sol\\\";\\nimport { IFluidDexFactory } from \\\"../../interfaces/iDexFactory.sol\\\";\\nimport { Error } from \\\"../../error.sol\\\";\\nimport { ErrorTypes } from \\\"../../errorTypes.sol\\\";\\n\\nabstract contract ImmutableVariables is ConstantVariables, Structs, Error {\\n    /*//////////////////////////////////////////////////////////////\\n                          CONSTANTS / IMMUTABLES\\n    //////////////////////////////////////////////////////////////*/\\n\\n    uint256 public immutable DEX_ID;\\n\\n    /// @dev Address of token 0\\n    address internal immutable TOKEN_0;\\n\\n    /// @dev Address of token 1\\n    address internal immutable TOKEN_1;\\n\\n    address internal immutable THIS_CONTRACT;\\n\\n    uint256 internal immutable TOKEN_0_NUMERATOR_PRECISION;\\n    uint256 internal immutable TOKEN_0_DENOMINATOR_PRECISION;\\n    uint256 internal immutable TOKEN_1_NUMERATOR_PRECISION;\\n    uint256 internal immutable TOKEN_1_DENOMINATOR_PRECISION;\\n\\n    /// @dev Address of liquidity contract\\n    IFluidLiquidity internal immutable LIQUIDITY;\\n\\n    /// @dev Address of DEX factory contract\\n    IFluidDexFactory internal immutable DEX_FACTORY;\\n\\n    /// @dev Address of Shift implementation\\n    address internal immutable SHIFT_IMPLEMENTATION;\\n\\n    /// @dev Address of Admin implementation\\n    address internal immutable ADMIN_IMPLEMENTATION;\\n\\n    /// @dev Address of Col Operations implementation\\n    address internal immutable COL_OPERATIONS_IMPLEMENTATION;\\n\\n    /// @dev Address of Debt Operations implementation\\n    address internal immutable DEBT_OPERATIONS_IMPLEMENTATION;\\n\\n    /// @dev Address of Perfect Operations and Swap Out implementation\\n    address internal immutable PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION;\\n\\n    /// @dev Address of contract used for deploying center price & hook related contract\\n    address internal immutable DEPLOYER_CONTRACT;\\n\\n    /// @dev Liquidity layer slots\\n    bytes32 internal immutable SUPPLY_TOKEN_0_SLOT;\\n    bytes32 internal immutable BORROW_TOKEN_0_SLOT;\\n    bytes32 internal immutable SUPPLY_TOKEN_1_SLOT;\\n    bytes32 internal immutable BORROW_TOKEN_1_SLOT;\\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_0_SLOT;\\n    bytes32 internal immutable EXCHANGE_PRICE_TOKEN_1_SLOT;\\n    uint256 internal immutable TOTAL_ORACLE_MAPPING;\\n\\n    function _calcNumeratorAndDenominator(\\n        address token_\\n    ) private view returns (uint256 numerator_, uint256 denominator_) {\\n        uint256 decimals_ = _decimals(token_);\\n        if (decimals_ > TOKENS_DECIMALS_PRECISION) {\\n            numerator_ = 1;\\n            denominator_ = 10 ** (decimals_ - TOKENS_DECIMALS_PRECISION);\\n        } else {\\n            numerator_ = 10 ** (TOKENS_DECIMALS_PRECISION - decimals_);\\n            denominator_ = 1;\\n        }\\n    }\\n\\n    constructor(ConstantViews memory constants_) {\\n        THIS_CONTRACT = address(this);\\n\\n        DEX_ID = constants_.dexId;\\n        LIQUIDITY = IFluidLiquidity(constants_.liquidity);\\n        DEX_FACTORY = IFluidDexFactory(constants_.factory);\\n\\n        TOKEN_0 = constants_.token0;\\n        TOKEN_1 = constants_.token1;\\n\\n        if (TOKEN_0 >= TOKEN_1) revert FluidDexError(ErrorTypes.DexT1__Token0ShouldBeSmallerThanToken1);\\n\\n        (TOKEN_0_NUMERATOR_PRECISION, TOKEN_0_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_0);\\n        (TOKEN_1_NUMERATOR_PRECISION, TOKEN_1_DENOMINATOR_PRECISION) = _calcNumeratorAndDenominator(TOKEN_1);\\n\\n        if (constants_.implementations.shift != address(0)) {\\n            SHIFT_IMPLEMENTATION = constants_.implementations.shift;\\n        } else {\\n            SHIFT_IMPLEMENTATION = address(this);\\n        }\\n        if (constants_.implementations.admin != address(0)) {\\n            ADMIN_IMPLEMENTATION = constants_.implementations.admin;\\n        } else {\\n            ADMIN_IMPLEMENTATION = address(this);\\n        }\\n        if (constants_.implementations.colOperations != address(0)) {\\n            COL_OPERATIONS_IMPLEMENTATION = constants_.implementations.colOperations;\\n        } else {\\n            COL_OPERATIONS_IMPLEMENTATION = address(this);\\n        }\\n        if (constants_.implementations.debtOperations != address(0)) {\\n            DEBT_OPERATIONS_IMPLEMENTATION = constants_.implementations.debtOperations;\\n        } else {\\n            DEBT_OPERATIONS_IMPLEMENTATION = address(this);\\n        }\\n        if (constants_.implementations.perfectOperationsAndSwapOut != address(0)) {\\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = constants_.implementations.perfectOperationsAndSwapOut;\\n        } else {\\n            PERFECT_OPERATIONS_AND_SWAP_OUT_IMPLEMENTATION = address(this);\\n        }\\n\\n        DEPLOYER_CONTRACT = constants_.deployerContract;\\n\\n        SUPPLY_TOKEN_0_SLOT = constants_.supplyToken0Slot;\\n        BORROW_TOKEN_0_SLOT = constants_.borrowToken0Slot;\\n        SUPPLY_TOKEN_1_SLOT = constants_.supplyToken1Slot;\\n        BORROW_TOKEN_1_SLOT = constants_.borrowToken1Slot;\\n        EXCHANGE_PRICE_TOKEN_0_SLOT = constants_.exchangePriceToken0Slot;\\n        EXCHANGE_PRICE_TOKEN_1_SLOT = constants_.exchangePriceToken1Slot;\\n\\n        if (constants_.oracleMapping > X16) revert FluidDexError(ErrorTypes.DexT1__OracleMappingOverflow);\\n\\n        TOTAL_ORACLE_MAPPING = constants_.oracleMapping;\\n    }\\n}\\n\",\"keccak256\":\"0x03a004dfca351193090a40ea5829311a0bfb33c3c433ab8353a40de9c9448f87\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/interfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\ninterface IHook {\\n    /// @notice Hook function to check for liquidation opportunities before external swaps\\n    /// @dev The primary use of this hook is to check if a particular pair vault has liquidation available.\\n    ///      If liquidation is available, it gives priority to the liquidation process before allowing external swaps.\\n    ///      In most cases, this hook will not be set.\\n    /// @param id_ Identifier for the operation type: 1 for swap, 2 for internal arbitrage\\n    /// @param swap0to1_ Direction of the swap: true if swapping token0 for token1, false otherwise\\n    /// @param token0_ Address of the first token in the pair\\n    /// @param token1_ Address of the second token in the pair\\n    /// @param price_ The price ratio of token1 to token0, expressed with 27 decimal places\\n    /// @return isOk_ Boolean indicating whether the operation should proceed\\n    function dexPrice(\\n        uint id_,\\n        bool swap0to1_,\\n        address token0_,\\n        address token1_,\\n        uint price_\\n    ) external returns (bool isOk_);\\n}\\n\\ninterface ICenterPrice {\\n    /// @notice Retrieves the center price for the pool\\n    /// @dev This function is marked as non-constant (potentially state-changing) to allow flexibility in price fetching mechanisms.\\n    ///      While typically used as a read-only operation, this design permits write operations if needed for certain token pairs\\n    ///      (e.g., fetching up-to-date exchange rates that may require state changes).\\n    /// @return price The current price ratio of token1 to token0, expressed with 27 decimal places\\n    function centerPrice() external returns (uint price);\\n}\\n\",\"keccak256\":\"0x6e42130fb15dbcfc2850e69bd7f26a1c709a6711cd00c10d2afb7aa1b97cfcc8\",\"license\":\"BUSL-1.1\"},\"contracts/protocols/dex/poolT1/coreModule/structs.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.21;\\n\\nabstract contract Structs {\\n    struct PricesAndExchangePrice {\\n        uint lastStoredPrice; // last stored price in 1e27 decimals\\n        uint centerPrice; // last stored price in 1e27 decimals\\n        uint upperRange; // price at upper range in 1e27 decimals\\n        uint lowerRange; // price at lower range in 1e27 decimals\\n        uint geometricMean; // geometric mean of upper range & lower range in 1e27 decimals\\n        uint supplyToken0ExchangePrice;\\n        uint borrowToken0ExchangePrice;\\n        uint supplyToken1ExchangePrice;\\n        uint borrowToken1ExchangePrice;\\n    }\\n\\n    struct ExchangePrices {\\n        uint supplyToken0ExchangePrice;\\n        uint borrowToken0ExchangePrice;\\n        uint supplyToken1ExchangePrice;\\n        uint borrowToken1ExchangePrice;\\n    }\\n\\n    struct CollateralReserves {\\n        uint token0RealReserves;\\n        uint token1RealReserves;\\n        uint token0ImaginaryReserves;\\n        uint token1ImaginaryReserves;\\n    }\\n\\n    struct CollateralReservesSwap {\\n        uint tokenInRealReserves;\\n        uint tokenOutRealReserves;\\n        uint tokenInImaginaryReserves;\\n        uint tokenOutImaginaryReserves;\\n    }\\n\\n    struct DebtReserves {\\n        uint token0Debt;\\n        uint token1Debt;\\n        uint token0RealReserves;\\n        uint token1RealReserves;\\n        uint token0ImaginaryReserves;\\n        uint token1ImaginaryReserves;\\n    }\\n\\n    struct DebtReservesSwap {\\n        uint tokenInDebt;\\n        uint tokenOutDebt;\\n        uint tokenInRealReserves;\\n        uint tokenOutRealReserves;\\n        uint tokenInImaginaryReserves;\\n        uint tokenOutImaginaryReserves;\\n    }\\n\\n    struct SwapInMemory {\\n        address tokenIn;\\n        address tokenOut;\\n        uint256 amtInAdjusted;\\n        address withdrawTo;\\n        address borrowTo;\\n        uint price; // price of pool after swap\\n        uint fee; // fee of pool\\n        uint revenueCut; // revenue cut of pool\\n        bool swap0to1;\\n        int swapRoutingAmt;\\n        bytes data; // just added to avoid stack-too-deep error\\n    }\\n\\n    struct SwapOutMemory {\\n        address tokenIn;\\n        address tokenOut;\\n        uint256 amtOutAdjusted;\\n        address withdrawTo;\\n        address borrowTo;\\n        uint price; // price of pool after swap\\n        uint fee;\\n        uint revenueCut; // revenue cut of pool\\n        bool swap0to1;\\n        int swapRoutingAmt;\\n        bytes data; // just added to avoid stack-too-deep error\\n        uint msgValue;\\n    }\\n\\n    struct DepositColMemory {\\n        uint256 token0AmtAdjusted;\\n        uint256 token1AmtAdjusted;\\n        uint256 token0ReservesInitial;\\n        uint256 token1ReservesInitial;\\n    }\\n\\n    struct WithdrawColMemory {\\n        uint256 token0AmtAdjusted;\\n        uint256 token1AmtAdjusted;\\n        uint256 token0ReservesInitial;\\n        uint256 token1ReservesInitial;\\n        address to;\\n    }\\n\\n    struct BorrowDebtMemory {\\n        uint256 token0AmtAdjusted;\\n        uint256 token1AmtAdjusted;\\n        uint256 token0DebtInitial;\\n        uint256 token1DebtInitial;\\n        address to;\\n    }\\n\\n    struct PaybackDebtMemory {\\n        uint256 token0AmtAdjusted;\\n        uint256 token1AmtAdjusted;\\n        uint256 token0DebtInitial;\\n        uint256 token1DebtInitial;\\n    }\\n\\n    struct OraclePriceMemory {\\n        uint lowestPrice1by0;\\n        uint highestPrice1by0;\\n        uint oracleSlot;\\n        uint oracleMap;\\n        uint oracle;\\n    }\\n\\n    struct Oracle {\\n        uint twap1by0; // TWAP price\\n        uint lowestPrice1by0; // lowest price point\\n        uint highestPrice1by0; // highest price point\\n        uint twap0by1; // TWAP price\\n        uint lowestPrice0by1; // lowest price point\\n        uint highestPrice0by1; // highest price point\\n    }\\n\\n    struct Implementations {\\n        address shift;\\n        address admin;\\n        address colOperations;\\n        address debtOperations;\\n        address perfectOperationsAndSwapOut;\\n    }\\n\\n    struct ConstantViews {\\n        uint256 dexId;\\n        address liquidity;\\n        address factory;\\n        Implementations implementations;\\n        address deployerContract;\\n        address token0;\\n        address token1;\\n        bytes32 supplyToken0Slot;\\n        bytes32 borrowToken0Slot;\\n        bytes32 supplyToken1Slot;\\n        bytes32 borrowToken1Slot;\\n        bytes32 exchangePriceToken0Slot;\\n        bytes32 exchangePriceToken1Slot;\\n        uint256 oracleMapping;\\n    }\\n\\n    struct ConstantViews2 {\\n        uint token0NumeratorPrecision;\\n        uint token0DenominatorPrecision;\\n        uint token1NumeratorPrecision;\\n        uint token1DenominatorPrecision;\\n    }\\n}\\n\",\"keccak256\":\"0x1cccc3a9ff4f07f159ac2aebf969c2a714a6f912ef0e86b76362bf45a5ecb8be\",\"license\":\"BUSL-1.1\"},\"solmate/src/utils/FixedPointMathLib.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Arithmetic library with operations for fixed-point numbers.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\\n/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)\\nlibrary FixedPointMathLib {\\n    /*//////////////////////////////////////////////////////////////\\n                    SIMPLIFIED FIXED POINT OPERATIONS\\n    //////////////////////////////////////////////////////////////*/\\n\\n    uint256 internal constant MAX_UINT256 = 2**256 - 1;\\n\\n    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\\n\\n    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\\n        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\\n    }\\n\\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\\n        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\\n    }\\n\\n    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\\n        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\\n    }\\n\\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\\n        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\\n    }\\n\\n    /*//////////////////////////////////////////////////////////////\\n                    LOW LEVEL FIXED POINT OPERATIONS\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function mulDivDown(\\n        uint256 x,\\n        uint256 y,\\n        uint256 denominator\\n    ) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\\n                revert(0, 0)\\n            }\\n\\n            // Divide x * y by the denominator.\\n            z := div(mul(x, y), denominator)\\n        }\\n    }\\n\\n    function mulDivUp(\\n        uint256 x,\\n        uint256 y,\\n        uint256 denominator\\n    ) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))\\n            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {\\n                revert(0, 0)\\n            }\\n\\n            // If x * y modulo the denominator is strictly greater than 0,\\n            // 1 is added to round up the division of x * y by the denominator.\\n            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))\\n        }\\n    }\\n\\n    function rpow(\\n        uint256 x,\\n        uint256 n,\\n        uint256 scalar\\n    ) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            switch x\\n            case 0 {\\n                switch n\\n                case 0 {\\n                    // 0 ** 0 = 1\\n                    z := scalar\\n                }\\n                default {\\n                    // 0 ** n = 0\\n                    z := 0\\n                }\\n            }\\n            default {\\n                switch mod(n, 2)\\n                case 0 {\\n                    // If n is even, store scalar in z for now.\\n                    z := scalar\\n                }\\n                default {\\n                    // If n is odd, store x in z for now.\\n                    z := x\\n                }\\n\\n                // Shifting right by 1 is like dividing by 2.\\n                let half := shr(1, scalar)\\n\\n                for {\\n                    // Shift n right by 1 before looping to halve it.\\n                    n := shr(1, n)\\n                } n {\\n                    // Shift n right by 1 each iteration to halve it.\\n                    n := shr(1, n)\\n                } {\\n                    // Revert immediately if x ** 2 would overflow.\\n                    // Equivalent to iszero(eq(div(xx, x), x)) here.\\n                    if shr(128, x) {\\n                        revert(0, 0)\\n                    }\\n\\n                    // Store x squared.\\n                    let xx := mul(x, x)\\n\\n                    // Round to the nearest number.\\n                    let xxRound := add(xx, half)\\n\\n                    // Revert if xx + half overflowed.\\n                    if lt(xxRound, xx) {\\n                        revert(0, 0)\\n                    }\\n\\n                    // Set x to scaled xxRound.\\n                    x := div(xxRound, scalar)\\n\\n                    // If n is even:\\n                    if mod(n, 2) {\\n                        // Compute z * x.\\n                        let zx := mul(z, x)\\n\\n                        // If z * x overflowed:\\n                        if iszero(eq(div(zx, x), z)) {\\n                            // Revert if x is non-zero.\\n                            if iszero(iszero(x)) {\\n                                revert(0, 0)\\n                            }\\n                        }\\n\\n                        // Round to the nearest number.\\n                        let zxRound := add(zx, half)\\n\\n                        // Revert if zx + half overflowed.\\n                        if lt(zxRound, zx) {\\n                            revert(0, 0)\\n                        }\\n\\n                        // Return properly scaled zxRound.\\n                        z := div(zxRound, scalar)\\n                    }\\n                }\\n            }\\n        }\\n    }\\n\\n    /*//////////////////////////////////////////////////////////////\\n                        GENERAL NUMBER UTILITIES\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            let y := x // We start y at x, which will help us make our initial estimate.\\n\\n            z := 181 // The \\\"correct\\\" value is 1, but this saves a multiplication later.\\n\\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\\n\\n            // We check y >= 2^(k + 8) but shift right by k bits\\n            // each branch to ensure that if x >= 256, then y >= 256.\\n            if iszero(lt(y, 0x10000000000000000000000000000000000)) {\\n                y := shr(128, y)\\n                z := shl(64, z)\\n            }\\n            if iszero(lt(y, 0x1000000000000000000)) {\\n                y := shr(64, y)\\n                z := shl(32, z)\\n            }\\n            if iszero(lt(y, 0x10000000000)) {\\n                y := shr(32, y)\\n                z := shl(16, z)\\n            }\\n            if iszero(lt(y, 0x1000000)) {\\n                y := shr(16, y)\\n                z := shl(8, z)\\n            }\\n\\n            // Goal was to get z*z*y within a small factor of x. More iterations could\\n            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\\n            // We ensured y >= 256 so that the relative difference between y and y+1 is small.\\n            // That's not possible if x < 256 but we can just verify those cases exhaustively.\\n\\n            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\\n            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\\n            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\\n\\n            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\\n            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\\n\\n            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\\n            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\\n\\n            // There is no overflow risk here since y < 2^136 after the first branch above.\\n            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\\n\\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n            z := shr(1, add(z, div(x, z)))\\n\\n            // If x+1 is a perfect square, the Babylonian method cycles between\\n            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\\n            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\\n            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\\n            z := sub(z, lt(div(x, z), z))\\n        }\\n    }\\n\\n    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Mod x by y. Note this will return\\n            // 0 instead of reverting if y is zero.\\n            z := mod(x, y)\\n        }\\n    }\\n\\n    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Divide x by y. Note this will return\\n            // 0 instead of reverting if y is zero.\\n            r := div(x, y)\\n        }\\n    }\\n\\n    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Add 1 to x * y if x % y > 0. Note this will\\n            // return 0 instead of reverting if y is zero.\\n            z := add(gt(mod(x, y), 0), div(x, y))\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x1b62af9baf5b8e991ed7531bc87f45550ba9d61e8dbff5caf237ccaf3a3fd843\",\"license\":\"AGPL-3.0-only\"}},\"version\":1}","userdoc":{"kind":"user","errors":{"FluidDexSwapResult(uint256)":[{"notice":"used to simulate swap to find the output amount"}]},"events":{"LogArbitrage(int256,uint256)":{"notice":"Emitted when internal arbitrage between 2 pools happen"},"Swap(bool,uint256,uint256,address)":{"notice":"Emitted on token swaps"},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with specified token0 & token1 amount"},"LogDepositColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is deposited with specified token0 & token1 amount"},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with specified token0 & token1 amount"},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with specified token0 & token1 amount"},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified from one token only."},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified into one token only."},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is borrowed with shares specified."},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is added with shares specified."},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is paid back with shares specified."},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"notice":"Emitted when liquidity is withdrawn with shares specified."}},"notice":"Implements core logics for Fluid Dex protocol. Note Token transfers happen directly from user to Liquidity contract and vice-versa.","methods":{"constantsView()":{"notice":"returns all Vault constants"},"constantsView2()":{"notice":"returns all Vault constants"},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the debt reserves for both tokens"},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"notice":"Calculates the real and imaginary reserves for collateral tokens"}},"version":1},"devdoc":{"kind":"dev","title":"FluidDexT1","events":{"LogArbitrage(int256,uint256)":{"params":{"amtOut":"if routing is positive then token1 withdraw & payback amount else token1 deposit & borrow","routing":"if positive then routing is amtIn of token0 in deposit & borrow else token0 withdraw & payback"}},"Swap(bool,uint256,uint256,address)":{"params":{"to":"Recepient of swapped tokens.","amountIn":"The amount of tokens to be sent to the vault to swap.","swap0to1":"Indicates whether the swap is from token0 to token1 or vice-versa.","amountOut":"The amount of tokens user got from the swap."}},"LogBorrowDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares minted.","amount0":"Amount of token0 borrowed.","amount1":"Amount of token1 borrowed."}},"LogDepositColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares minted.","amount0":"Amount of token0 deposited.","amount1":"Amount of token1 deposited."}},"LogPaybackDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares burned.","amount0":"Amount of token0 paid back.","amount1":"Amount of token1 paid back."}},"LogWithdrawColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Amount of shares burned.","amount0":"Amount of token0 withdrawn.","amount1":"Amount of token1 withdrawn."}},"LogPaybackDebtInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogWithdrawColInOneToken(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}},"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares minted","token0Amt":"Amount of token0 borrowed.","token1Amt":"Amount of token1 borrowed."}},"LogDepositPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"Expected exact shares to be received.","token0Amt":"Amount of token1 deposited."}},"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 paid back.","token1Amt":"Amount of token1 paid back."}},"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)":{"params":{"shares":"shares burned","token0Amt":"Amount of token0 withdrawn.","token1Amt":"Amount of token1 withdrawn."}}},"methods":{"oraclePrice(uint256[])":{"params":{"secondsAgos_":"array of seconds ago for which TWAP is needed. If user sends [10, 30, 60] then twaps_ will return [10-0, 30-10, 60-30]"},"details":"the oracle assumes last set price of pool till the next swap happens. There's a possibility that during that time some interest is generated hence the last stored price is not the 100% correct price for the whole duration but the difference due to interest will be super low so this difference is ignored For example 2 swaps happened 10min (600 seconds) apart and 1 token has 10% higher interest than other. then that token will accrue about 10% * 600 / secondsInAYear = ~0.0002%","returns":{"twaps_":"twap price, lowest price (aka minima) & highest price (aka maxima) between secondsAgo checkpoints","currentPrice_":"price of pool after the most recent swap"}},"swapIn(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_","amountIn_":"The exact amount of tokens to swap in","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOutMin_":"The minimum amount of tokens to receive after swap"},"details":"Swap tokens with perfect amount in","returns":{"amountOut_":"The amount of output tokens received from the swap"}},"deposit(uint256,uint256,uint256,bool)":{"params":{"estimate_":"If true, function will revert with estimated shares without executing the deposit","token0Amt_":"The amount of token0 to deposit","token1Amt_":"The amount of token1 to deposit","minSharesAmt_":"The minimum amount of shares the user expects to receive"},"details":"This function allows users to deposit tokens in any proportion into the col pool","returns":{"shares_":"The amount of shares minted for the deposit"}},"payback(uint256,uint256,uint256,bool)":{"params":{"estimate_":"If true, function will revert with estimated shares without executing the payback","token0Amt_":"The amount of token0 to payback","token1Amt_":"The amount of token1 to payback","minSharesAmt_":"The minimum amount of shares the user expects to burn"},"details":"This function allows users to payback tokens in any proportion to the debt pool","returns":{"shares_":"The amount of borrow shares burned for the payback"}},"swapOut(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOut_":"The exact amount of tokens to receive after swap","amountInMax_":"Maximum amount of tokens to swap in"},"details":"Swap tokens with perfect amount out","returns":{"amountIn_":"The amount of input tokens used for the swap"}},"borrow(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to borrow","token1Amt_":"The amount of token1 to borrow","maxSharesAmt_":"The maximum amount of shares the user is willing to receive"},"details":"This function allows users to borrow tokens in any proportion from the debt pool","returns":{"shares_":"The amount of borrow shares minted to represent the borrowed amount"}},"liquidityCallback(address,uint256,bytes)":{"details":"liquidity callback for cheaper token transfers in case of deposit or payback. only callable by Liquidity during an operation."},"withdraw(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with shares_","token0Amt_":"The amount of token0 to withdraw","token1Amt_":"The amount of token1 to withdraw","maxSharesAmt_":"The maximum number of shares the user is willing to burn"},"details":"This function allows users to withdraw tokens in any proportion from the col pool","returns":{"shares_":"The number of shares burned for the withdrawal"}},"depositPerfect(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to mint","estimate_":"If true, function will revert with estimated deposit amounts without executing the deposit","maxToken0Deposit_":"Maximum amount of token0 to deposit","maxToken1Deposit_":"Maximum amount of token1 to deposit"},"details":"Deposit tokens in equal proportion to the current pool ratio","returns":{"token0Amt_":"Amount of token0 deposited","token1Amt_":"Amount of token1 deposited"}},"paybackPerfect(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to pay back","estimate_":"If true, function will revert with estimated payback amounts without executing the payback","maxToken0Payback_":"Maximum amount of token0 to pay back","maxToken1Payback_":"Maximum amount of token1 to pay back"},"details":"This function allows users to pay back borrowed tokens in equal proportion to the current debt pool ratio","returns":{"token0Amt_":"Amount of token0 paid back","token1Amt_":"Amount of token1 paid back"}},"borrowPerfect(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of borrowed tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_","shares_":"The number of shares to borrow","minToken0Borrow_":"Minimum amount of token0 to borrow","minToken1Borrow_":"Minimum amount of token1 to borrow"},"details":"This function allows users to borrow tokens in equal proportion to the current debt pool ratio","returns":{"token0Amt_":"Amount of token0 borrowed","token1Amt_":"Amount of token1 borrowed"}},"swapInWithCallback(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountOut_","amountIn_":"The exact amount of tokens to swap in","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOutMin_":"The minimum amount of tokens to receive after swap"},"details":"Swap tokens with perfect amount in and callback functionality","returns":{"amountOut_":"The amount of output tokens received from the swap"}},"withdrawPerfect(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with token0Amt_ & token1Amt_","shares_":"The number of shares to withdraw","minToken0Withdraw_":"The minimum amount of token0 the user is willing to accept","minToken1Withdraw_":"The minimum amount of token1 the user is willing to accept"},"details":"This function allows users to withdraw a perfect amount of collateral liquidity","returns":{"token0Amt_":"The amount of token0 withdrawn","token1Amt_":"The amount of token1 withdrawn"}},"swapOutWithCallback(bool,uint256,uint256,address)":{"params":{"to_":"Recipient of swapped tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with amountIn_","swap0to1_":"Direction of swap. If true, swaps token0 for token1; if false, swaps token1 for token0","amountOut_":"The exact amount of tokens to receive after swap","amountInMax_":"Maximum amount of tokens to swap in"},"details":"Swap tokens with perfect amount out and callback functionality","returns":{"amountIn_":"The amount of input tokens used for the swap"}},"paybackPerfectInOneToken(uint256,uint256,uint256,bool)":{"params":{"shares_":"The number of shares to burn for payback","estimate_":"If true, the function will revert with the estimated payback amount without executing the payback","maxToken0_":"The maximum amount of token0 the user is willing to pay (set to 0 if paying back in token1)","maxToken1_":"The maximum amount of token1 the user is willing to pay (set to 0 if paying back in token0)"},"details":"This function allows users to payback their debt with perfect shares in one token","returns":{"paybackAmt_":"The amount of tokens paid back in the chosen token"}},"getDebtReserves(uint256,uint256,uint256,uint256,uint256)":{"params":{"lowerRange_":"The lower price range","upperRange_":"The upper price range","geometricMean_":"The geometric mean of the upper and lower price ranges","token0BorrowExchangePrice_":"The exchange price of token0 from liquidity layer","token1BorrowExchangePrice_":"The exchange price of token1 from liquidity layer"},"returns":{"d_":"The calculated debt reserves for both tokens, containing:         - token0Debt: The debt amount of token0         - token1Debt: The debt amount of token1         - token0RealReserves: The real reserves of token0 derived from token1 debt         - token1RealReserves: The real reserves of token1 derived from token0 debt         - token0ImaginaryReserves: The imaginary debt reserves of token0         - token1ImaginaryReserves: The imaginary debt reserves of token1"}},"withdrawPerfectInOneToken(uint256,uint256,uint256,address)":{"params":{"to_":"Recipient of withdrawn tokens. If to_ == address(0) then out tokens will be sent to msg.sender. If to_ == ADDRESS_DEAD then function will revert with withdrawAmt_","shares_":"The number of shares to burn for withdrawal","minToken0_":"The minimum amount of token0 the user expects to receive (set to 0 if withdrawing in token1)","minToken1_":"The minimum amount of token1 the user expects to receive (set to 0 if withdrawing in token0)"},"details":"This function allows users to withdraw their collateral with perfect shares in one token","returns":{"withdrawAmt_":"The amount of tokens withdrawn in the chosen token"}},"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)":{"params":{"lowerRange_":"The lower price range","upperRange_":"The upper price range","geometricMean_":"The geometric mean of the token prices","token0SupplyExchangePrice_":"The exchange price for token0 from liquidity layer","token1SupplyExchangePrice_":"The exchange price for token1 from liquidity layer"},"details":"This function retrieves the supply of both tokens from the liquidity layer,      adjusts them based on exchange prices, and calculates imaginary reserves      based on the geometric mean and price range","returns":{"c_":"A struct containing the calculated real and imaginary reserves for both tokens:         - token0RealReserves: The real reserves of token0         - token1RealReserves: The real reserves of token1         - token0ImaginaryReserves: The imaginary reserves of token0         - token1ImaginaryReserves: The imaginary reserves of token1"}}},"version":1},"storageLayout":{"types":{"t_address":{"label":"address","encoding":"inplace","numberOfBytes":"20"},"t_uint128":{"label":"uint128","encoding":"inplace","numberOfBytes":"16"},"t_uint256":{"label":"uint256","encoding":"inplace","numberOfBytes":"32"},"t_mapping(t_address,t_uint256)":{"key":"t_address","label":"mapping(address => uint256)","value":"t_uint256","encoding":"mapping","numberOfBytes":"32"},"t_mapping(t_uint256,t_uint256)":{"key":"t_uint256","label":"mapping(uint256 => uint256)","value":"t_uint256","encoding":"mapping","numberOfBytes":"32"}},"storage":[{"slot":"0","type":"t_uint256","astId":3893,"label":"dexVariables","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"1","type":"t_uint256","astId":3896,"label":"dexVariables2","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"2","type":"t_uint256","astId":3899,"label":"_totalSupplyShares","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"3","type":"t_mapping(t_address,t_uint256)","astId":3904,"label":"_userSupplyData","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"4","type":"t_uint256","astId":3907,"label":"_totalBorrowShares","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"5","type":"t_mapping(t_address,t_uint256)","astId":3912,"label":"_userBorrowData","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"6","type":"t_mapping(t_uint256,t_uint256)","astId":3917,"label":"_oracle","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"7","type":"t_uint128","astId":3920,"label":"_rangeShift","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"7","type":"t_uint128","astId":3923,"label":"_thresholdShift","offset":16,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"},{"slot":"8","type":"t_uint256","astId":3926,"label":"_centerPriceShift","offset":0,"contract":"contracts/protocols/dex/poolT1/coreModule/core/main.sol:FluidDexT1"}]},"transientStorageLayout":null,"evm":{"bytecode":{"object":"6103606040523480156200001257600080fd5b5060405162005f4938038062005f49833981016040819052620000359162000518565b3060e052805160805260208101516001600160a01b0390811661018052604082015181166101a05260a08083015182169081905260c080840151909216918290528291829110620000a2576040516317f71f0760e11b815261c76160048201526024015b60405180910390fd5b60a051620000b09062000313565b610120526101005260c051620000c69062000313565b61016052610140526060810151516001600160a01b031615620000fc576060810151516001600160a01b03166101c05262000102565b306101c0525b6060810151602001516001600160a01b03161562000136576060810151602001516001600160a01b03166101e0526200013c565b306101e0525b6060810151604001516001600160a01b03161562000170576060810151604001516001600160a01b03166102005262000176565b30610200525b60608082015101516001600160a01b031615620001a85760608082015101516001600160a01b031661022052620001ae565b30610220525b6060810151608001516001600160a01b031615620001e2576060810151608001516001600160a01b031661024052620001e8565b30610240525b60808101516001600160a01b03166102605260e0810151610280526101008101516102a0526101208101516102c0526101408101516102e05261016081015161030052610180810151610320526101a081015161ffff101562000263576040516317f71f0760e11b815261c762600482015260240162000099565b6101a0015161034052506060810151516001600160a01b031615806200029857506060810151602001516001600160a01b0316155b80620002b357506060810151604001516001600160a01b0316155b80620002cd575060608082015101516001600160a01b0316155b80620002e857506060810151608001516001600160a01b0316155b156200030c576040516317f71f0760e11b815261c772600482015260240162000099565b5062000771565b6000808062000322846200037b565b9050600c8111156200035457600192506200033f600c8262000624565b6200034c90600a62000737565b915062000375565b6200036181600c62000624565b6200036e90600a62000737565b9250600191505b50915091565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146200041057816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040791906200074c565b60ff1662000413565b60125b92915050565b6040516101c081016001600160401b03811182821017156200044b57634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b03811681146200046957600080fd5b919050565b600060a082840312156200048157600080fd5b60405160a081016001600160401b0381118282101715620004b257634e487b7160e01b600052604160045260246000fd5b604052905080620004c38362000451565b8152620004d36020840162000451565b6020820152620004e66040840162000451565b6040820152620004f96060840162000451565b60608201526200050c6080840162000451565b60808201525092915050565b600061024082840312156200052c57600080fd5b6200053662000419565b82518152620005486020840162000451565b60208201526200055b6040840162000451565b60408201526200056f84606085016200046e565b60608201526101006200058481850162000451565b60808301526101206200059981860162000451565b60a0840152610140620005ae81870162000451565b60c08501526101608087015160e086015261018080880151858701526101a0945084880151848701526101c0880151838701526101e088015182870152610200880151818701525050505061022084015181830152508091505092915050565b634e487b7160e01b600052601160045260246000fd5b818103818111156200041357620004136200060e565b600181815b808511156200067b5781600019048211156200065f576200065f6200060e565b808516156200066d57918102915b93841c93908002906200063f565b509250929050565b600082620006945750600162000413565b81620006a35750600062000413565b8160018114620006bc5760028114620006c757620006e7565b600191505062000413565b60ff841115620006db57620006db6200060e565b50506001821b62000413565b5060208310610133831016604e8410600b84101617156200070c575081810a62000413565b6200071883836200063a565b80600019048211156200072f576200072f6200060e565b029392505050565b600062000745838362000683565b9392505050565b6000602082840312156200075f57600080fd5b815160ff811681146200074557600080fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e05161030051610320516103405161551062000a3960003960008181610ff0015281816112690152818161131a01528181613dba01528181613e230152613ed0015260008181610fc9015281816129c5015261311f015260008181610fa20152818161298e015261303d015260008181610f7b0152611936015260008181610f540152612ae4015260008181610f2d0152611906015260008181610f070152612ab4015260008181610edf01528181612cdc0152613823015260008181610856015281816108ba0152610eb60152600081816107970152610e8f01526000818161093d0152610e640152600081816105f50152610e39015260008181610e12015281816145330152818161463301526146c4015260008181610429015281816104e30152610d8f015260008181610a9401528181610c5e01528181610d63015281816127c2015281816128650152818161306701528181613149015281816132b50152613a2401526000818161076901528181611c5f0152818161249a015281816124ee0152818161254a015281816125a1015261335f01526000818161074301528181611c8001528181612479015281816124cd015281816125260152818161257d015261338001526000818161071d01528181611ba2015281816123ef01528181612446015281816125f50152818161264901526133b60152600081816106fa01528181611bc3015281816123cb01528181612422015281816125d40152818161262801526133d701526000505060008181610de301528181611b5601528181611c3b01526138bc015260008181610dbb01528181611b7e01528181611c1301526138940152600081816103d90152610d2b01526155106000f3fe6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201527f0000000000000000000000000000000000000000000000000000000000000000606082015290565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f0000000000000000000000000000000000000000000000000000000000000000866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166020808401919091527f000000000000000000000000000000000000000000000000000000000000000082166040808501919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08501527f0000000000000000000000000000000000000000000000000000000000000000831660c0850152606080850180517f00000000000000000000000000000000000000000000000000000000000000008616905280517f0000000000000000000000000000000000000000000000000000000000000000861694019390935282517f0000000000000000000000000000000000000000000000000000000000000000851692019190915281517f00000000000000000000000000000000000000000000000000000000000000008416910152517f000000000000000000000000000000000000000000000000000000000000000082166080918201527f0000000000000000000000000000000000000000000000000000000000000000909116908201527f000000000000000000000000000000000000000000000000000000000000000060e08201527f00000000000000000000000000000000000000000000000000000000000000006101008201527f00000000000000000000000000000000000000000000000000000000000000006101208201527f00000000000000000000000000000000000000000000000000000000000000006101408201527f00000000000000000000000000000000000000000000000000000000000000006101608201527f00000000000000000000000000000000000000000000000000000000000000006101808201527f00000000000000000000000000000000000000000000000000000000000000006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b9050600061195d7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000006124147f00000000000000000000000000000000000000000000000000000000000000008861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000061246b7f00000000000000000000000000000000000000000000000000000000000000008661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000061256f7f00000000000000000000000000000000000000000000000000000000000000008861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000006125c67f00000000000000000000000000000000000000000000000000000000000000008661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129e9565b6129e96103ff60ee8b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b90506000612b0b7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000000000000000000000000000000000000000000000826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526130ed907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015261318d907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000000000000000000000000000000000000000000000856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660448301527f00000000000000000000000000000000000000000000000000000000000000008116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000000006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000000000000000000000000000000000000000000000907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","sourceMap":"797:42753:18:-:0;;;878:610;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3051:4:21;3027:29;;3076:16;;3067:25;;3130:20;;;;-1:-1:-1;;;;;3102:49:21;;;;;3192:18;;;;3161:50;;;;3232:17;;;;;3222:27;;;;;;3269:17;;;;;3259:27;;;;;;;939:14:18;;;;3301:18:21;3297:95;;3328:64;;-1:-1:-1;;;3328:64:21;;3722:5:13;3328:64:21;;;2930:25:25;2903:18;;3328:64:21;;;;;;;;3297:95;3495:7;;3466:37;;:28;:37::i;:::-;3403:100;;;;3605:7;;3576:37;;:28;:37::i;:::-;3513:100;;;;3628:26;;;;:32;-1:-1:-1;;;;;3628:46:21;;3624:199;;3713:26;;;;:32;-1:-1:-1;;;;;3690:55:21;;;3624:199;;;3807:4;3776:36;;3624:199;3836:26;;;;:32;;;-1:-1:-1;;;;;3836:46:21;;3832:199;;3921:26;;;;:32;;;-1:-1:-1;;;;;3898:55:21;;;3832:199;;;4015:4;3984:36;;3832:199;4044:26;;;;:40;;;-1:-1:-1;;;;;4044:54:21;;4040:233;;4146:26;;;;:40;;;-1:-1:-1;;;;;4114:72:21;;;4040:233;;;4257:4;4217:45;;4040:233;4286:26;;;;;:41;;-1:-1:-1;;;;;4286:55:21;;4282:237;;4390:26;;;;;:41;;-1:-1:-1;;;;;4357:74:21;;;4282:237;;;4503:4;4462:46;;4282:237;4532:26;;;;:54;;;-1:-1:-1;;;;;4532:68:21;;4528:295;;4665:26;;;;:54;;;-1:-1:-1;;;;;4616:103:21;;;4528:295;;;4807:4;4750:62;;4528:295;4853:27;;;;-1:-1:-1;;;;;4833:47:21;;;4913:27;;;;4891:49;;4972:27;;;;4950:49;;5031:27;;;;5009:49;;5090:27;;;;5068:49;;5157:34;;;;5127:64;;5231:34;;;;5201:64;;5280:24;;;;1551:6:16;-1:-1:-1;5276:97:21;;;5319:54;;-1:-1:-1;;;5319:54:21;;3791:5:13;5319:54:21;;;2930:25:25;2903:18;;5319:54:21;2784:177:25;5276:97:21;5407:24;;;5384:47;;-1:-1:-1;1032:30:18::1;::::0;::::1;::::0;:36;-1:-1:-1;;;;;1032:50:18::1;::::0;;:116:::1;;-1:-1:-1::0;1098:30:18::1;::::0;::::1;::::0;:36:::1;;::::0;-1:-1:-1;;;;;1098:50:18::1;::::0;1032:116:::1;:190;;;-1:-1:-1::0;1164:30:18::1;::::0;::::1;::::0;:44:::1;;::::0;-1:-1:-1;;;;;1164:58:18::1;::::0;1032:190:::1;:265;;;-1:-1:-1::0;1238:30:18::1;::::0;;::::1;::::0;:45:::1;::::0;-1:-1:-1;;;;;1238:59:18::1;::::0;1032:265:::1;:353;;;-1:-1:-1::0;1313:30:18::1;::::0;::::1;::::0;:58:::1;;::::0;-1:-1:-1;;;;;1313:72:18::1;::::0;1032:353:::1;1015:467;;;1417:54;::::0;-1:-1:-1;;;1417:54:18;;5162:5:13::1;1417:54:18;::::0;::::1;2930:25:25::0;2903:18;;1417:54:18::1;2784:177:25::0;1015:467:18::1;878:610:::0;797:42753;;2496:470:21;2586:18;;;2658:17;2668:6;2658:9;:17::i;:::-;2638:37;;843:2:16;2689:9:21;:37;2685:275;;;2755:1;;-1:-1:-1;2792:37:21;843:2:16;2792:9:21;:37;:::i;:::-;2785:45;;:2;:45;:::i;:::-;2770:60;;2685:275;;;2881:37;2909:9;843:2:16;2881:37:21;:::i;:::-;2874:45;;:2;:45;:::i;:::-;2861:58;;2948:1;2933:16;;2685:275;2628:338;2496:470;;;:::o;3655:175:16:-;3713:7;-1:-1:-1;;;;;3740:22:16;;594:42;3740:22;3739:84;;3805:6;-1:-1:-1;;;;;3790:31:16;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3739:84;;;;;692:2;3739:84;3732:91;3655:175;-1:-1:-1;;3655:175:16:o;14:347:25:-;81:2;75:9;123:6;111:19;;-1:-1:-1;;;;;145:34:25;;181:22;;;142:62;139:185;;;246:10;241:3;237:20;234:1;227:31;281:4;278:1;271:15;309:4;306:1;299:15;139:185;340:2;333:22;14:347;:::o;366:177::-;445:13;;-1:-1:-1;;;;;487:31:25;;477:42;;467:70;;533:1;530;523:12;467:70;366:177;;;:::o;548:873::-;621:5;669:4;657:9;652:3;648:19;644:30;641:50;;;687:1;684;677:12;641:50;720:2;714:9;762:4;750:17;;-1:-1:-1;;;;;782:34:25;;818:22;;;779:62;776:185;;;883:10;878:3;874:20;871:1;864:31;918:4;915:1;908:15;946:4;943:1;936:15;776:185;977:2;970:22;1010:6;-1:-1:-1;1010:6:25;1040:40;1070:9;1040:40;:::i;:::-;1032:6;1025:56;1114:49;1159:2;1148:9;1144:18;1114:49;:::i;:::-;1109:2;1101:6;1097:15;1090:74;1197:49;1242:2;1231:9;1227:18;1197:49;:::i;:::-;1192:2;1184:6;1180:15;1173:74;1280:49;1325:2;1314:9;1310:18;1280:49;:::i;:::-;1275:2;1267:6;1263:15;1256:74;1364:50;1409:3;1398:9;1394:19;1364:50;:::i;:::-;1358:3;1350:6;1346:16;1339:76;;548:873;;;;:::o;1426:1353::-;1527:6;1580:3;1568:9;1559:7;1555:23;1551:33;1548:53;;;1597:1;1594;1587:12;1548:53;1623:17;;:::i;:::-;1669:9;1663:16;1656:5;1649:31;1712:49;1757:2;1746:9;1742:18;1712:49;:::i;:::-;1707:2;1700:5;1696:14;1689:73;1794:49;1839:2;1828:9;1824:18;1794:49;:::i;:::-;1789:2;1782:5;1778:14;1771:73;1876;1941:7;1936:2;1925:9;1921:18;1876:73;:::i;:::-;1871:2;1864:5;1860:14;1853:97;1969:3;2006:49;2051:2;2040:9;2036:18;2006:49;:::i;:::-;1999:4;1992:5;1988:16;1981:75;2075:3;2112:49;2157:2;2146:9;2142:18;2112:49;:::i;:::-;2105:4;2098:5;2094:16;2087:75;2181:3;2218:49;2263:2;2252:9;2248:18;2218:49;:::i;:::-;2211:4;2204:5;2200:16;2193:75;2287:3;2345:2;2334:9;2330:18;2324:25;2317:4;2310:5;2306:16;2299:51;2369:3;2425:2;2414:9;2410:18;2404:25;2399:2;2392:5;2388:14;2381:49;2449:3;2439:13;;2505:2;2494:9;2490:18;2484:25;2479:2;2472:5;2468:14;2461:49;2563:6;2552:9;2548:22;2542:29;2537:2;2530:5;2526:14;2519:53;2625:3;2614:9;2610:19;2604:26;2599:2;2592:5;2588:14;2581:50;2684:3;2673:9;2669:19;2663:26;2658:2;2651:5;2647:14;2640:50;;;;;2743:3;2732:9;2728:19;2722:26;2717:2;2710:5;2706:14;2699:50;;2768:5;2758:15;;;1426:1353;;;;:::o;2966:127::-;3027:10;3022:3;3018:20;3015:1;3008:31;3058:4;3055:1;3048:15;3082:4;3079:1;3072:15;3098:128;3165:9;;;3186:11;;;3183:37;;;3200:18;;:::i;3231:422::-;3320:1;3363:5;3320:1;3377:270;3398:7;3388:8;3385:21;3377:270;;;3457:4;3453:1;3449:6;3445:17;3439:4;3436:27;3433:53;;;3466:18;;:::i;:::-;3516:7;3506:8;3502:22;3499:55;;;3536:16;;;;3499:55;3615:22;;;;3575:15;;;;3377:270;;;3381:3;3231:422;;;;;:::o;3658:806::-;3707:5;3737:8;3727:80;;-1:-1:-1;3778:1:25;3792:5;;3727:80;3826:4;3816:76;;-1:-1:-1;3863:1:25;3877:5;;3816:76;3908:4;3926:1;3921:59;;;;3994:1;3989:130;;;;3901:218;;3921:59;3951:1;3942:10;;3965:5;;;3989:130;4026:3;4016:8;4013:17;4010:43;;;4033:18;;:::i;:::-;-1:-1:-1;;4089:1:25;4075:16;;4104:5;;3901:218;;4203:2;4193:8;4190:16;4184:3;4178:4;4175:13;4171:36;4165:2;4155:8;4152:16;4147:2;4141:4;4138:12;4134:35;4131:77;4128:159;;;-1:-1:-1;4240:19:25;;;4272:5;;4128:159;4319:34;4344:8;4338:4;4319:34;:::i;:::-;4389:6;4385:1;4381:6;4377:19;4368:7;4365:32;4362:58;;;4400:18;;:::i;:::-;4438:20;;3658:806;-1:-1:-1;;;3658:806:25:o;4469:131::-;4529:5;4558:36;4585:8;4579:4;4558:36;:::i;:::-;4549:45;4469:131;-1:-1:-1;;;4469:131:25:o;4605:273::-;4673:6;4726:2;4714:9;4705:7;4701:23;4697:32;4694:52;;;4742:1;4739;4732:12;4694:52;4774:9;4768:16;4824:4;4817:5;4813:16;4806:5;4803:27;4793:55;;4844:1;4841;4834:12;4605:273;797:42753:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"6080604052600436106101845760003560e01c80636560abaa116100d6578063be17c79c1161007f578063e27203cd11610059578063e27203cd1461027f578063e980e1eb146103b9578063f4b9a3fb146103c7576101bd565b8063be17c79c14610378578063d331bef7146102b4578063d811b2ce1461038b576101bd565b8063ad207501116100b0578063ad20750114610317578063b5c736e414610337578063b7791bf214610356576101bd565b80636560abaa146102e25780636876698114610271578063916cef4e14610302576101bd565b806330acd6fd116101385780634d9036de116101125780634d9036de146102d45780635b3d38d7146102d4578063653295aa1461025e576101bd565b806330acd6fd1461027157806335f0df981461027f5780634c89bfd4146102b4576101bd565b8063242011d511610169578063242011d51461021d5780632668dfaa1461024b578063286f0e611461025e576101bd565b806305d455a9146101c55780631595cbd3146101fb576101bd565b366101bd577fffffffff0000000000000000000000000000000000000000000000000000000060003516156101bb576101bb6103fb565b005b6101bb6103fb565b3480156101d157600080fd5b506101e56101e0366004614b99565b61067d565b6040516101f29190614bd4565b60405180910390f35b34801561020757600080fd5b506102106106cd565b6040516101f29190614c17565b34801561022957600080fd5b5061023d610238366004614c67565b610790565b6040519081526020016101f2565b61023d610259366004614cb6565b61080f565b61023d61026c366004614cb6565b61084f565b61023d610238366004614cf5565b34801561028b57600080fd5b5061029f61029a366004614c67565b6108b2565b604080519283526020830191909152016101f2565b3480156102c057600080fd5b5061023d6102cf366004614c67565b610936565b61029f61029a366004614cf5565b3480156102ee57600080fd5b506102106102fd366004614b99565b610999565b34801561030e57600080fd5b506101bb6109d1565b34801561032357600080fd5b506101bb610332366004614d2b565b610a7c565b34801561034357600080fd5b5061023d610352366004614db4565b5490565b34801561036257600080fd5b5061036b610c8c565b6040516101f29190614dcd565b61023d610386366004614cb6565b611018565b34801561039757600080fd5b506103ab6103a6366004614f8e565b611058565b6040516101f292919061505e565b61023d6102cf366004614cf5565b3480156103d357600080fd5b5061023d7f000000000000000000000000000000000000000000000000000000000000000081565b6040517f4502d0630000000000000000000000000000000000000000000000000000000081523360048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634502d06390602401602060405180830381865afa158015610485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a991906150e5565b8061056357506040517ffbeeca2c0000000000000000000000000000000000000000000000000000000081523060048201523360248201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063fbeeca2c90604401602060405180830381865afa15801561053f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056391906150e5565b6105a2576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73a60048201526024015b60405180910390fd5b600054600180821690036105e6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b806001176000819055506106517f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b5050600080547ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe169055565b6106b66040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6106c386868686866118c6565b9695505050505050565b6106f86040518060800160405280600081526020016000815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201527f0000000000000000000000000000000000000000000000000000000000000000606082015290565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b8060200190518101906108069190615102565b95945050505050565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160001515815250611a0e565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6000806109167f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b806020019051810190610929919061511b565b9150915094509492505050565b60006107f37f00000000000000000000000000000000000000000000000000000000000000006000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061188092505050565b6109c46040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c38686868686612a82565b6000546001546109e18282612bbd565b60006109f1600054600154612c48565b604080517f23bfdd3b0000000000000000000000000000000000000000000000000000000081528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a082015160a482015260c082015160c482015260e082015160e482015261010082015161010482015290915061012401610599565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610aef576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75d6004820152602401610599565b600054600116600003610b32576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c75e6004820152602401610599565b60608114610b70576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7746004820152602401610599565b60008080610b808486018661513f565b92509250925085831015610bc4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7756004820152602401610599565b8115610c57576040517f9410ae8800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015260248201859052821690639410ae8890604401600060405180830381600087803b158015610c3a57600080fd5b505af1158015610c4e573d6000803e3d6000fd5b50505050610c83565b610c8387827f0000000000000000000000000000000000000000000000000000000000000000866131a5565b50505050505050565b610d29604080516101c08101825260008082526020808301829052828401829052835160a08101855282815290810182905292830181905260608381018290526080840191909152909190820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b7f0000000000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166020808401919091527f000000000000000000000000000000000000000000000000000000000000000082166040808501919091527f0000000000000000000000000000000000000000000000000000000000000000831660a08501527f0000000000000000000000000000000000000000000000000000000000000000831660c0850152606080850180517f00000000000000000000000000000000000000000000000000000000000000008616905280517f0000000000000000000000000000000000000000000000000000000000000000861694019390935282517f0000000000000000000000000000000000000000000000000000000000000000851692019190915281517f00000000000000000000000000000000000000000000000000000000000000008416910152517f000000000000000000000000000000000000000000000000000000000000000082166080918201527f0000000000000000000000000000000000000000000000000000000000000000909116908201527f000000000000000000000000000000000000000000000000000000000000000060e08201527f00000000000000000000000000000000000000000000000000000000000000006101008201527f00000000000000000000000000000000000000000000000000000000000000006101208201527f00000000000000000000000000000000000000000000000000000000000000006101408201527f00000000000000000000000000000000000000000000000000000000000000006101608201527f00000000000000000000000000000000000000000000000000000000000000006101808201527f00000000000000000000000000000000000000000000000000000000000000006101a082015290565b6000610806858560405180606001604052808673ffffffffffffffffffffffffffffffffffffffff16815260200187815260200160011515815250611a0e565b6060600061108e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000805490600160c383901c1690036110d7576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c77a6004820152602401610599565b845167ffffffffffffffff8111156110f1576110f1614f5f565b60405190808252806020026020018201604052801561115b57816020015b6111486040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b81526020019060019003908161110f5790505b5093506000806000808860008151811061117757611177615181565b602090810291909101810151603187901c63ffffffff16602988901c60ff161b808952918801829052600760b088901c811660408a0181905261ffff60b38a901c1660608b0152929950909250889160009182918291116111d95760006111ee565b60608a01516000908152600660205260409020545b60808b01526000804260798c901c6401ffffffff1610156112255761121e60798c901c6401ffffffff16426151df565b9850611231565b61122e836151f2565b92505b8260020361146e578b6040018051611248906151f2565b908190526008036112bc57600060408d0181905260608d0151900361128e577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516112a19061522a565b90819052815260208101919091526040016000205460808d01525b63ffffffff8c6040015160206112d2919061525f565b60808e0151901c1691508115611438576101ff82169850886000036113ad57600982901c98508b6040015160070361137b57600060408d0181905260608d0151900361133f577f000000000000000000000000000000000000000000000000000000000000000060608d01525b600660008d60600180516113529061522a565b90819052815260208101919091526040016000205460808d0181905263ffffffff1691506113ad565b8b604001805161138a906151f2565b905260408c015163ffffffff906113a290602061525f565b8d60800151901c1691505b50600a81901c623fffff6113c88266b1a2bc2ec5000061525f565b6113d291906152a5565b9050600982901c60011660010361141157670de0b6b3a76400006113f6828861525f565b61140091906152a5565b61140a90876151df565b95506114bc565b670de0b6b3a7640000611424828861525f565b61142e91906152a5565b61140a90876152b9565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76a6004820152602401610599565b826001036114a857609a8b901c623fffff16985063ffffffff60098c901c1660ff60018d901c161b95506114a1836151f2565b92506114bc565b826000036114bc576114b9836151f2565b92505b6114c6898b6152b9565b9950858c6000015111156114d857858c525b858c6020015110156114ec5760208c018690525b868a1015611547576114fe898761525f565b61150890866152b9565b94508861152c87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b611536919061525f565b61154090856152b9565b9350611231565b89611552888b6152b9565b61155c91906151df565b9850611568898761525f565b61157290866152b9565b94508861159687760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6115a0919061525f565b6115aa90856152b9565b93506115b687866152a5565b94506115c287856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061161691906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061164291906152a5565b8152508e898151811061165757611657615181565b602090810291909101810191909152868d528c018690525b8e5161167a896151f2565b98508810156118625761168d878b6151df565b99508998508e61169e60018a6151df565b815181106116ae576116ae615181565b60200260200101518f89815181106116c8576116c8615181565b60200260200101516116da91906151df565b9650868a1015611756576116ee898761525f565b94508861171287760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b61171c919061525f565b935088600003611751577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c52600060208d01525b611862565b89611761888b6152b9565b61176b91906151df565b9850611777898761525f565b94508861179b87760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6117a5919061525f565b93506117b187866152a5565b94506117bd87856152a5565b93506040518060c001604052808681526020018d6000015181526020018d6020015181526020018581526020018d60200151760a70c3c40a64e6c51999090b65f67d924000000000000061181191906152a5565b81526020018d60000151760a70c3c40a64e6c51999090b65f67d924000000000000061183d91906152a5565b8152508e898151811061185257611852615181565b602002602001018190525061166f565b8e51880361187b57505050505050505050505050915091565b611231565b6060600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e816118be57806000803e806000fd5b505092915050565b6118ff6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600061192d7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b9050600061195d7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b8284526020840181905290506b033b2e3c9fd0803ce80000008810156119a2576119898887848461340f565b60a0870152608086015260608501526040840152611a03565b6119ee6119c689760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b6119e789760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b838561340f565b608087015260a0860152604085015260608401525b505095945050505050565b60008054600180549060ff82901c9003611a58576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7636004820152602401610599565b611a628282612bbd565b835173ffffffffffffffffffffffffffffffffffffffff16611a82573384525b611b39604051806101600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160001515815260200160008152602001606081525090565b8615611bfc5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611bf157611bf1615276565b046040820152611cb5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660208301527f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000870281611cae57611cae615276565b0460408201525b611cc3816040015187613621565b6000611ccf8484612c48565b90503415611d7c57863414611d14576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73f6004820152602401610599565b815173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611d7c576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7406004820152602401610599565b6201ffff600284901c16607f601385901c1681026305f5e1000360e0840152620f424081900360c0840152604080516080810182526000808252602082018190529181018290526060810182905260018087169387821c909116929091611e126040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b85600103611e97576000611e3d886080015189604001518a606001518b60a001518c60e00151612a82565b90508e15611e6c5780516020808301516040808501516060808701519089015290870152908501528352611e95565b602080820151825160608085015160408087015192890192909252908701529185019190915283525b505b84600103611f48576000611ec3886080015189604001518a606001518b60c001518c61010001516118c6565b90508e15611f0657805160208083015160408085015160608087015160808089015160a0808b0151908c0152908a01529088015290860152908401528252611f46565b602080820151825160608085015160408087015160a0808901516080808b0151928c0192909252908a015292880192909252908601529184019190915282525b505b6002816080015183604001510181611f6257611f62615276565b0488604001511115611fa4576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7656004820152602401610599565b856001148015611fb45750846001145b15611fe157611fda8860400151836060015184604001518460a0015185608001516136a1565b6101208901525b8761012001518860400151138015611ffe57506000886101200151135b156120495761012088015160408901518d5173ffffffffffffffffffffffffffffffffffffffff90811660608c01528e511660808b0152909650600095508690039350849250612130565b856001148015612057575084155b8061206b5750876040015188610120015112155b156120a35760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660608a0152955060009450849350839250612130565b851580156120b15750846001145b806120c25750600088610120015113155b156120fa5760408801518c5173ffffffffffffffffffffffffffffffffffffffff1660808a0152600096508695509350849250612130565b6040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7416004820152602401610599565b85156121cd57612166620f42408960c001518861214d919061525f565b61215791906152a5565b83604001518460600151613728565b94508d61219f5761219a85836020015161218091906151df565b835161218d9089906152b9565b896020015161271061374a565b6121cd565b81516121cd906121b09088906152b9565b8684602001516121c091906151df565b89602001516127106137b7565b831561225557612203620f42408960c00151866121ea919061525f565b6121f491906152a5565b82608001518360a00151613728565b92508d6122325761222d83826060015161221d91906151df565b85836040015161218d91906152b9565b612255565b61225584826040015161224591906152b9565b8483606001516121c091906151df565b6305f5e1008860e001518761226a919061525f565b61227491906152a5565b95506305f5e1008860e001518561228b919061525f565b61229591906152a5565b935083861115612333578d6122e9578482606001516122b491906151df565b8683604001516122c491906152b9565b6122da906b033b2e3c9fd0803ce800000061525f565b6122e491906152a5565b612329565b8582604001516122f991906152b9565b85836060015161230991906151df565b61231f906b033b2e3c9fd0803ce800000061525f565b61232991906152a5565b60a08901526123c3565b8d61237d57828160a0015161234891906151df565b84826080015161235891906152b9565b61236e906b033b2e3c9fd0803ce800000061525f565b61237891906152a5565b6123bd565b83816080015161238d91906152b9565b838260a0015161239d91906151df565b6123b3906b033b2e3c9fd0803ce800000061525f565b6123bd91906152a5565b60a08901525b8d15612524577f00000000000000000000000000000000000000000000000000000000000000006124147f00000000000000000000000000000000000000000000000000000000000000008861525f565b61241e91906152a5565b95507f000000000000000000000000000000000000000000000000000000000000000061246b7f00000000000000000000000000000000000000000000000000000000000000008661525f565b61247591906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008602816124c8576124c8615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161251c5761251c615276565b04925061267b565b7f000000000000000000000000000000000000000000000000000000000000000061256f7f00000000000000000000000000000000000000000000000000000000000000008861525f565b61257991906152a5565b95507f00000000000000000000000000000000000000000000000000000000000000006125c67f00000000000000000000000000000000000000000000000000000000000000008661525f565b6125d091906152a5565b93507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000086028161262357612623615276565b0494507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084028161267757612677615276565b0492505b8b518386019b5073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016126f3576040517fb3bfda99000000000000000000000000000000000000000000000000000000008152600481018c9052602401610599565b8b602001518b1015612735576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7426004820152602401610599565b8c8c604001513360405160200161277593929190928352901515602083015273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052610140890152875173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad967e15903490896127f5896152cc565b6000808f61014001516040518863ffffffff1660e01b815260040161281f96959493929190615304565b604080518083038185885af115801561283c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612861919061511b565b50507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ad967e158960200151876128ae906152cc565b60608c015160808d0151604080516000815260208101918290527fffffffff0000000000000000000000000000000000000000000000000000000060e088901b169091526129059493928a92909160248101615304565b60408051808303816000875af1158015612923573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612947919061511b565b5050608e89901c633fffffff169550851561297b578d1515610100890181905260a089015161297b9188916001919061381e565b8d6129b7576129b26103ff60e48b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129e9565b6129e96103ff60ee8b901c167f00000000000000000000000000000000000000000000000000000000000000006139c5565b6129fc8860a0015188602001518c613adb565b6000819055507fdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f78e8e8d8f60000151604051612a69949392919093151584526020840192909252604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b60405180910390a1505050505050505050509392505050565b612aad6040518060800160405280600081526020016000815260200160008152602001600081525090565b6000612adb7f000000000000000000000000000000000000000000000000000000000000000085600161326c565b90506000612b0b7f000000000000000000000000000000000000000000000000000000000000000085600061326c565b90506b033b2e3c9fd0803ce8000000881015612b3c57612b2d88888484613fa0565b60608501526040840152612b93565b612b88612b6089760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b612b8188760a70c3c40a64e6c51999090b65f67d92400000000000006152a5565b8385613fa0565b604085015260608401525b81835260208301819052604083018051909201909152606082018051909101905295945050505050565b81600116600103612bfe576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7396004820152602401610599565b80600316600003612c3f576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73d6004820152602401610599565b50600117600055565b612c976040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b600060f883901c600116600003612d7857633fffffff607084901c16905080600003612cd7575063ffffffff605984901c1660ff605185901c161b612d85565b612d017f0000000000000000000000000000000000000000000000000000000000000000826140ad565b73ffffffffffffffffffffffffffffffffffffffff1663f763f7a66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d719190615102565b9050612d85565b612d828484614519565b90505b63ffffffff603185901c1660ff602986901c161b601b84901c620fffff90811690602f86901c166001601a87901c81169003612dce57612dc682828861460e565b975090925090505b81620f424003620f4240850281612de757612de7615276565b049150620f42409081038402046000620fffff604488901c1615612eed57604487901c6103ff90811690604e89901c16605889901c62ffffff16600160438b901c81169003612e4357612e3b83838361469f565b919450925090505b6103e888870384820302048801871115612e985760798b901c6401ffffffff16420381811015612e8a5781818a89030281612e8057612e80615276565b0489019850612e8e565b8698505b6001945050612ee9565b6103e885890383820302048803871015612ee95760798b901c6401ffffffff16420381811015612edf578181878b030281612ed557612ed5615276565b0489039850612ee3565b8598505b60019450505b5050505b620fffff60b488901c1660ff60ac89901c161b80861115612f145780955060019150612f38565b50620fffff60d088901c1660ff60c889901c161b80861015612f3857809550600191505b8115612fa157620fffff601b89901c169350620fffff602f89901c169250601a88901c600116600103612f7857612f7084848a61460e565b995090945092505b83620f424003620f4240870281612f9157612f91615276565b049350620f424083810387020492505b8487526020870186905260408701849052606087018390526f4b3b4ca85a86c47a098a224000000000841015612fe657612fdc83850261470e565b6080880152613015565b613005670de0b6b3a76400008404670de0b6b3a764000086040261470e565b670de0b6b3a76400000260808801525b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201526130ed907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024015b602060405180830381865afa1580156130c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130e89190615102565b6147c0565b60c089015260a08801526040517fb5c736e40000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015261318d907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063b5c736e4906024016130a7565b61010089015260e08801525094979650505050505050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080613265576040517fdee51a8a000000000000000000000000000000000000000000000000000000008152620115596004820152602401610599565b5050505050565b6040517fb5c736e400000000000000000000000000000000000000000000000000000000815260048101849052600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa1580156132fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133209190615102565b905067ffffffffffffffff600182901c16915060ff8216600883901c901b9150806001166001036133585764e8d4a510008285020491505b826133b4577f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008302816133ae576133ae615276565b04610806565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000083028161340557613405615276565b0495945050505050565b6000808080806b06765c793fa10079d0000000613438876b033b2e3c9fd0803ce800000061525f565b6134428b8a61525f565b61344c91906153b1565b61345691906153d8565b90506000613464878961525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106134a857886134996b033b2e3c9fd0803ce8000000836152a5565b6134a3919061525f565b6134c9565b6b033b2e3c9fd0803ce80000006134bf8a8361525f565b6134c991906152a5565b90506134e76134d88380615440565b6134e290836152b9565b61470e565b6134f1908361548c565b94506134fd898961525f565b613513866b033b2e3c9fd0803ce800000061525f565b61351d91906151df565b9250620f4240831015613560576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76d6004820152602401610599565b6a084595161401484a0000008510156135a5578261357e868061525f565b613594906b033b2e3c9fd0803ce800000061525f565b61359e91906152a5565b92506135d2565b6135bb6b033b2e3c9fd0803ce8000000846152a5565b6135c5868061525f565b6135cf91906152a5565b92505b87856135de828661525f565b6135e891906152a5565b6135f291906151df565b93506135fe87846152b9565b613608888661525f565b61361291906152a5565b95505050945094509450949050565b620f424082108061363d57506bffffffffffffffffffffffff82115b806136485750606481105b8061366257506fffffffffffffffffffffffffffffffff81115b1561369d576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7696004820152602401610599565b5050565b6000806136c36136b1868861525f565b6134e290670de0b6b3a764000061525f565b905060006136d46136b1858761525f565b90506136e081836152b9565b6136ea828861525f565b6136f4848b61525f565b6136fe858861525f565b61370891906152b9565b61371291906153b1565b61371c91906153d8565b98975050505050505050565b600083820283850180828161373f5761373f615276565b049695505050505050565b613754818361525f565b61376a846b033b2e3c9fd0803ce800000061525f565b61377491906152a5565b8410156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b50505050565b6137cd816b033b2e3c9fd0803ce800000061525f565b6137d7838661525f565b6137e191906152a5565b8310156137b1576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c73e6004820152602401610599565b6138487f0000000000000000000000000000000000000000000000000000000000000000856140ad565b6040517fd1f9be4e00000000000000000000000000000000000000000000000000000000815260048101859052831515602482015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660448301527f00000000000000000000000000000000000000000000000000000000000000008116606483015260848201849052919091169063d1f9be4e9060a4016020604051808303816000875af1925050508015613950575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261394d918101906150e5565b60015b61398a573d80801561397e576040519150601f19603f3d011682016040523d82523d6000602084013e613983565b606091505b50506137b1565b80613265576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7446004820152602401610599565b6103e882101561369d576139da82600a61525f565b6040517fb5c736e40000000000000000000000000000000000000000000000000000000081526004810183905290925060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063b5c736e490602401602060405180830381865afa158015613a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8f9190615102565b601e1c613fff16905082811115613ad6576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7436004820152602401610599565b505050565b600080613af3607984901c6401ffffffff16426151df565b9050600080600083600003613bdb5763ffffffff605987901c1660ff605188901c161b92506305f5e1006305f5e0ff840204871080613b3d57506305f5e1006305f5e10184020487115b15613b78576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c76c6004820152602401610599565b63ffffffff600987901c1660ff600188901c161b9250613b9883896149ce565b506029613baa89602060086000614a70565b901b867ffffffffffffffffffffffffffffffffffffffffffffe0000000001ffffffffff1617945050505050613f99565b60c386901c600116600003613c755763ffffffff603187901c1660ff602988901c161b9250613c0a83896149ce565b504260791b6051613c2089602060086000614a70565b901b6029613c338b602060086000614a70565b7ffffffffffffffffffffffffffc000000000000000000000000000000000000018a166501fffffffffe60288c901c1617911b1717179450613f999350505050565b63ffffffff600987901c811660ff600189901c81169190911b9450603188901c909116602988901c9091161b91506000613caf838a6149ce565b905082670de0b6b3a7640000850281613cca57613cca615276565b04670de0b6b3a76400000390506000811215613d0a57600166b1a2bc2ec50000623fffff836000030281613d0057613d00615276565b04901b9150613d23565b600166b1a2bc2ec50000623fffff830204901b60011791505b623fffff851115613d3557623fffff94505b609a87901c623fffff16935060b087901c60071660b388901c61ffff166101ff861115613e70578115613e015760299390931b600986901b1792613d788261522a565b9150613d8582602061525f565b600082815260066020526040902080549186901b90911790558115613db457613dad8261522a565b9150613f13565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613dea57613dea615276565b066000818152600660205260408120559050613f13565b6000818152600660208190526040909120805460099690961b958617905591507f00000000000000000000000000000000000000000000000000000000000000006001820181613e5357613e53615276565b06600081815260066020526040902060e988901b90559050613f13565b85600985901b1793506007821015613ea5576000818152600660209081526040909120805491840286901b9091179055613ebb565b600081815260066020526040902060e085901b90555b8115613eca57613dad8261522a565b600791507f00000000000000000000000000000000000000000000000000000000000000008160010181613f0057613f00615276565b0660008181526006602052604081205590505b8a955089945088935060b381901b60b083901b609a89901b4260791b6051613f408a602060086000614a70565b901b6029613f538c602060086000614a70565b901b600164ffffffffff60298c901c16901b8a7ffffffffffffffff800000000000000000000000000000000000000000000000116171717171717179750505050505050505b9392505050565b60008080613fae87876151df565b90506000613fbd82600261525f565b613fd3866b033b2e3c9fd0803ce800000061525f565b613fdd888b61525f565b613fe791906152b9565b613ff191906152a5565b90506000613fff868861525f565b905074446c3b15f9926687d2c40534fdb56400000000000081106140425761402783826152a5565b61403d906b033b2e3c9fd0803ce800000061525f565b614063565b82614059826b033b2e3c9fd0803ce800000061525f565b61406391906152a5565b90506140726134d8838061525f565b61407c90836152b9565b94506b033b2e3c9fd0803ce80000006140958a8761525f565b61409f91906152a5565b935050505094509492505050565b60006060826000036140c3576000915050614513565b607f831161418c576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050614508565b60ff8311614269576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801614176565b61ffff8311614347576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901614176565b62ffffff8311614426576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01614176565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012090505b92915050565b60405160248101839052604481018290526000906145fb907f0000000000000000000000000000000000000000000000000000000000000000907f2f850fb300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611880565b806020019051810190613f999190615102565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907f0d7cf0ab0000000000000000000000000000000000000000000000000000000090608401614579565b80602001905181019061469091906154ac565b92509250925093509350939050565b6040516024810184905260448101839052606481018290526000908190819061467d907f0000000000000000000000000000000000000000000000000000000000000000907fe8518a660000000000000000000000000000000000000000000000000000000090608401614579565b60b5817101000000000000000000000000000000000081106147355760409190911b9060801c5b690100000000000000000081106147515760209190911b9060401c5b6501000000000081106147695760109190911b9060201c5b6301000000811061477f5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b67ffffffffffffffff605b82901c811690609b83901c168115806147e2575080155b1561481e576040517fd50d7512000000000000000000000000000000000000000000000000000000008152620111716004820152602401610599565b61ffff8316603a84901c6401ffffffff16428181039160ea87901c617fff16911480614848575082155b806148535750806001145b1561486057505050915091565b64496cebb80084840283020484019350617fff60db87901c1692508260010361488b57505050915091565b826001166001036148e05760019290921c91826c7e37be2022c0914b2680000000816148b9576148b9615276565b049250612710601e87901c613fff166b033b2e3c9fd0803ce800000085010204925061490d565b60019290921c916305f5e100601e87901c613fff166127108501026b033b2e3c9fd0803ce8000000020492505b806001166001036149445760011c61271081016b033b2e3c9fd0803ce800000082028161493c5761493c615276565b04905061497a565b60011c61271081016b033b2e3c9fd0803ce800000082028161496857614968615276565b046b033b2e3c9fd0803ce80000000390505b760a70c3c40a64e6c51999090b65f67d92400000000000008382026127100261ffff881691900402601087901c613fff16612710030292506801b5a660ea44b8000085840283020485019450505050915091565b6000816149e3670de0b6b3a76400008561525f565b6149ed91906152a5565b6149ff90670de0b6b3a76400006153b1565b905066b1a2bc2ec50000811380614a3557507fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b000081125b15614513576040517f2fee3e0e00000000000000000000000000000000000000000000000000000000815261c7606004820152602401610599565b600080856fffffffffffffffffffffffffffffffff811115614a935760809150811c5b67ffffffffffffffff811115614aab576040918201911c5b63ffffffff811115614abf576020918201911c5b61ffff811115614ad1576010918201911c5b60ff811115614ae2576008918201911c5b600f811115614af3576004918201911c5b6003811115614b04576002918201911c5b6001811115614b14576001820191505b8015614b21576001820191505b5084811015614b2d5750835b848103905085811c60008211841615614b7c57600181019050806001871b03614b7c57506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210614b8b57600080fd5b90931b909201949350505050565b600080600080600060a08688031215614bb157600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60c081016145138284805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b8151815260208083015190820152604080830151908201526060808301519082015260808101614513565b73ffffffffffffffffffffffffffffffffffffffff81168114614c6457600080fd5b50565b60008060008060808587031215614c7d57600080fd5b8435935060208501359250604085013591506060850135614c9d81614c42565b939692955090935050565b8015158114614c6457600080fd5b60008060008060808587031215614ccc57600080fd5b8435614cd781614ca8565b935060208501359250604085013591506060850135614c9d81614c42565b60008060008060808587031215614d0b57600080fd5b8435935060208501359250604085013591506060850135614c9d81614ca8565b60008060008060608587031215614d4157600080fd5b8435614d4c81614c42565b935060208501359250604085013567ffffffffffffffff80821115614d7057600080fd5b818701915087601f830112614d8457600080fd5b813581811115614d9357600080fd5b886020828501011115614da557600080fd5b95989497505060200194505050565b600060208284031215614dc657600080fd5b5035919050565b81518152602080830151610240830191614dfe9084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151614e26604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614e84606084018273ffffffffffffffffffffffffffffffffffffffff808251168352806020830151166020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b506080830151610100614eae8185018373ffffffffffffffffffffffffffffffffffffffff169052565b60a08501519150610120614ed98186018473ffffffffffffffffffffffffffffffffffffffff169052565b60c08601519250610140614f048187018573ffffffffffffffffffffffffffffffffffffffff169052565b60e0870151610160878101919091529287015161018080880191909152918701516101a080880191909152908701516101c0870152918601516101e08601528501516102008501529093015161022090920191909152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020808385031215614fa157600080fd5b823567ffffffffffffffff80821115614fb957600080fd5b818501915085601f830112614fcd57600080fd5b813581811115614fdf57614fdf614f5f565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561502257615022614f5f565b60405291825284820192508381018501918883111561504057600080fd5b938501935b8285101561371c57843584529385019392850192615045565b604080825283519082018190526000906020906060840190828701845b828110156150d6576150c3848351805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a08301525050565b60c093909301929084019060010161507b565b50505092019290925292915050565b6000602082840312156150f757600080fd5b8151613f9981614ca8565b60006020828403121561511457600080fd5b5051919050565b6000806040838503121561512e57600080fd5b505080516020909101519092909150565b60008060006060848603121561515457600080fd5b83359250602084013561516681614ca8565b9150604084013561517681614c42565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115614513576145136151b0565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615223576152236151b0565b5060010190565b600081615239576152396151b0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b8082028115828204841417614513576145136151b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826152b4576152b4615276565b500490565b80820180821115614513576145136151b0565b60007f800000000000000000000000000000000000000000000000000000000000000082036152fd576152fd6151b0565b5060000390565b600073ffffffffffffffffffffffffffffffffffffffff8089168352602088818501528760408501528187166060850152818616608085015260c060a0850152845191508160c085015260005b8281101561536d5785810182015185820160e001528101615351565b5050600060e0828501015260e07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050979650505050505050565b81810360008312801583831316838312821617156153d1576153d16151b0565b5092915050565b6000826153e7576153e7615276565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561543b5761543b6151b0565b500590565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615478576154786151b0565b8181058314821517614513576145136151b0565b80820182811260008312801582168215821617156118be576118be6151b0565b6000806000606084860312156154c157600080fd5b835192506020840151915060408401519050925092509256fea2646970667358221220e36e1d99152573d8e2f0228a17cd27411093a7af47d613a737f2515e954138b764736f6c63430008150033","sourceMap":"797:42753:18:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38672:7;;;;:21;38668:63;;38709:11;:9;:11::i;:::-;797:42753;;38607:11;:9;:11::i;43065:483::-;;;;;;;;;;-1:-1:-1;43065:483:18;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40119:423;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;25047:246::-;;;;;;;;;;-1:-1:-1;25047:246:18;;;;;:::i;:::-;;:::i;:::-;;;2429:25:25;;;2417:2;2402:18;25047:246:18;2283:177:25;16567:263:18;;;;;;:::i;:::-;;:::i;18250:280::-;;;;;;:::i;:::-;;:::i;27572:273::-;;;;;;:::i;20865:310::-;;;;;;;;;;-1:-1:-1;20865:310:18;;;;;:::i;:::-;;:::i;:::-;;;;3737:25:25;;;3793:2;3778:18;;3771:34;;;;3710:18;20865:310:18;3563:248:25;26706:263:18;;;;;;;;;;-1:-1:-1;26706:263:18;;;;;:::i;:::-;;:::i;19897:318::-;;;;;;:::i;41597:501::-;;;;;;;;;;-1:-1:-1;41597:501:18;;;;;:::i;:::-;;:::i;36902:346::-;;;;;;;;;;;;;:::i;27998:826::-;;;;;;;;;;-1:-1:-1;27998:826:18;;;;;:::i;:::-;;:::i;186:186:9:-;;;;;;;;;;-1:-1:-1;186:186:9;;;;;:::i;:::-;308:12;;186:186;38787:1282:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;17422:274::-;;;;;;:::i;:::-;;:::i;29694:7202::-;;;;;;;;;;-1:-1:-1;29694:7202:18;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;23419:257::-;;;;;;:::i;685:31:21:-;;;;;;;;;;;;;;;37849:714:18;37894:36;;;;;37919:10;37894:36;;;9567:74:25;37894:11:18;:24;;;;;9540:18:25;;37894:36:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:88;;;-1:-1:-1;37934:48:18;;;;;37964:4;37934:48;;;10137:34:25;37971:10:18;10187:18:25;;;10180:43;37934:11:18;:21;;;;;10049:18:25;;37934:48:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37888:171;;38006:42;;;;;359:5:13;38006:42:18;;;2429:25:25;2402:18;;38006:42:18;;;;;;;;37888:171;38069:18;38090:12;38132:1;38116:17;;;:22;;38112:82;;38147:47;;;;;302:5:13;38147:47:18;;;2429:25:25;2402:18;;38147:47:18;2283:177:25;38112:82:18;38251:13;38267:1;38251:17;38236:12;:32;;;;38343:38;38350:20;38372:8;;38343:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38343:6:18;;-1:-1:-1;;;38343:38:18:i;:::-;-1:-1:-1;;38533:12:18;;;38548:8;38533:23;38518:38;;37849:714::o;43065:483::-;43280:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43280:22:18;43333:208;43367:14;43399:11;43428;43457:26;43501;43333:16;:208::i;:::-;43314:227;43065:483;-1:-1:-1;;;;;;43065:483:18:o;40119:423::-;40168:37;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40168:37:18;40260:27;40217:70;;40342:29;40297:42;;;:74;40424:27;40381:40;;;:70;40506:29;40461:42;;;:74;40217:15;40119:423::o;25047:246::-;25184:12;25226:48;25233:30;25265:8;;25226:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25226:6:18;;-1:-1:-1;;;25226:48:18:i;:::-;25215:71;;;;;;;;;;;;:::i;:::-;25208:78;25047:246;-1:-1:-1;;;;;25047:246:18:o;16567:263::-;16716:18;16753:70;16761:9;16772;16783:39;;;;;;;;16796:3;16783:39;;;;;;16801:13;16783:39;;;;16816:5;16783:39;;;;;16753:7;:70::i;18250:280::-;18400:17;18447:64;18454:46;18502:8;;18447:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18447:6:18;;-1:-1:-1;;;18447:64:18:i;20865:310::-;21021:15;21038;21083:64;21090:46;21138:8;;21083:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21083:6:18;;-1:-1:-1;;;21083:64:18:i;:::-;21072:96;;;;;;;;;;;;:::i;:::-;21065:103;;;;20865:310;;;;;;;:::o;26706:263::-;26856:17;26903:47;26910:29;26941:8;;26903:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26903:6:18;;-1:-1:-1;;;26903:47:18:i;41597:501::-;41818:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41818:28:18;41877:214;41917:14;41949:11;41978;42007:26;42051;41877:22;:214::i;36902:346::-;36957:18;36978:12;37022:13;;37046:37;36978:12;37022:13;37046:6;:37::i;:::-;37094:34;37131:56;37159:12;;37173:13;;37131:27;:56::i;:::-;37205:36;;;;;;10918:13:25;;37205:36:18;;;10900:32:25;10988:4;10976:17;;10970:24;10948:20;;;10941:54;11039:17;;;11033:24;11011:20;;;11004:54;11114:4;11102:17;;11096:24;11074:20;;;11067:54;11177:4;11165:17;;11159:24;11137:20;;;11130:54;11240:4;11228:17;;11222:24;11200:20;;;11193:54;11303:4;11291:17;;11285:24;11263:20;;;11256:54;11366:4;11354:17;;11348:24;11326:20;;;11319:54;11392:6;11440:15;;11434:22;11414:18;;;11407:50;37094:93:18;;-1:-1:-1;10872:19:25;;37205:36:18;10673:790:25;27998:826:18;28100:10;:32;28122:9;28100:32;;28096:99;;28141:54;;;;;3185:5:13;28141:54:18;;;2429:25:25;2402:18;;28141:54:18;2283:177:25;28096:99:18;28209:12;;28224:1;28209:16;28229:1;28209:21;28205:90;;28239:56;;;;;3313:5:13;28239:56:18;;;2429:25:25;2402:18;;28239:56:18;2283:177:25;28205:90:18;28325:2;28309:18;;28305:83;;28336:52;;;;;5300:5:13;28336:52:18;;;2429:25:25;2402:18;;28336:52:18;2283:177:25;28305:83:18;28400:18;;;28455:40;;;;28466:5;28455:40;:::i;:::-;28399:96;;;;;;28526:7;28510:13;:23;28506:95;;;28542:59;;;;;5374:5:13;28542:59:18;;;2429:25:25;2402:18;;28542:59:18;2283:177:25;28506:95:18;28616:11;28612:206;;;28643:54;;;;;:31;12123:55:25;;;28643:54:18;;;12105:74:25;12195:18;;;12188:34;;;28643:31:18;;;;;12078:18:25;;28643:54:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28612:206;;;28728:79;28758:6;28766:5;28781:9;28793:13;28728:29;:79::i;:::-;28086:738;;;27998:826;;;;:::o;38787:1282::-;38835:35;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38835:35:18;38905:6;38882:29;;38921:45;38956:9;38921:45;;:24;;;;:45;;;;39009:11;38976:45;;:22;;;;:45;;;;39055:7;39031:31;;:21;;;:31;39096:7;39072:31;;:21;;;:31;39113:30;;;;;;39152:20;39113:59;;;;39182:30;;39221:20;39182:59;;:36;;:59;;;;39251:30;;39298:29;39251:76;;:44;;:76;;;;39337:30;;39385;39337:78;;:45;;:78;39425:30;39486:46;39425:107;;:58;;;;:107;39576:17;39542:51;;;:31;;;:51;39637:19;39603:31;;;:53;39700:19;39666:31;;;:53;39763:19;39729:31;;;:53;39826:19;39792:31;;;:53;39896:27;39855:38;;;:68;39974:27;39933:38;;;:68;40042:20;40011:28;;;:51;38882:14;38787:1282::o;17422:274::-;17583:18;17620:69;17628:9;17639;17650:38;;;;;;;;17663:3;17650:38;;;;;;17668:13;17650:38;;;;17683:4;17650:38;;;;;17620:7;:69::i;29694:7202::-;29780:22;29804:18;29834:27;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29834:27:18;29872:18;29893:12;;;29945:1;29938:3;29921:20;;;29920:26;:31;;29916:117;;29974:48;;;;;5713:5:13;29974:48:18;;;2429:25:25;2402:18;;29974:48:18;2283:177:25;29916:117:18;30065:12;:19;30052:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30052:33:18;;;;;;;;;;;;;;;;;30043:42;;30096:15;30121:10;30142:6;30158:16;30177:12;30190:1;30177:15;;;;;;;;:::i;:::-;;;;;;;;;;;;30273:38;;;;;;30237:2;30220:19;;;1133:4:16;30317:37:18;30272:83;30402:34;;;30446:19;;;:35;;;1215:3:16;30592::18;30575:20;;;30574:27;;30558:13;;;:43;;;1551:6:16;30644:3:18;30627:20;;;30626:28;30611:12;;;:43;30272:83;;-1:-1:-1;30177:15:18;;-1:-1:-1;30272:83:18;;-1:-1:-1;;;;;;;30767:45:18;;30811:1;30767:45;;;30795:12;;;;30787:21;;;;:7;:21;;;;;;30767:45;30755:9;;;:57;30823:14;;30912:15;30898:3;30881:20;;;2011:11:16;30880:28:18;30879:48;30875:427;;;31085:48;31122:3;31105:20;;;2011:11:16;31104:28:18;31085:15;:48;:::i;:::-;31077:56;;30875:427;;;31288:3;;;:::i;:::-;;;30875:427;31343:1;31348;31343:6;31339:2481;;31375:2;:13;;31373:15;;;;;:::i;:::-;;;;;31392:1;31373:20;31369:269;;31433:1;31417:13;;;:17;;;31460:12;;;;:17;;31456:107;;31520:20;31505:12;;;:35;31456:107;31596:7;:23;31606:2;:12;;31604:14;;;;;:::i;:::-;;;;;31596:23;;;;;;;;;;;-1:-1:-1;31596:23:18;;31584:9;;;:35;31369:269;1963:10:16;31683:2:18;:13;;;31699:2;31683:18;;;;:::i;:::-;31669:9;;;;:33;;31668:41;;-1:-1:-1;31731:13:18;;31727:1723;;1378:5:16;31776:9:18;:14;31768:22;;31816:5;31825:1;31816:10;31812:801;;31935:1;31922:9;:14;;31914:22;;32062:2;:13;;;32079:1;32062:18;32058:533;;32128:1;32112:13;;;:17;;;32163:12;;;;:17;;32159:123;;32231:20;32216:12;;;:35;32159:123;32323:7;:23;32333:2;:12;;32331:14;;;;;:::i;:::-;;;;;32323:23;;;;;;;;;;;-1:-1:-1;32323:23:18;;32311:9;;;:35;;;1963:10:16;32388:15:18;;-1:-1:-1;32058:533:18;;;32468:2;:13;;32466:15;;;;;:::i;:::-;;;32538:13;;;;1963:10:16;;32538:18:18;;32554:2;32538:18;:::i;:::-;32524:2;:9;;;:33;;32523:41;32511:53;;32058:533;-1:-1:-1;32662:2:18;32649:15;;;1730:8:16;32702:27:18;32649:15;2789:8:16;32702:27:18;:::i;:::-;32701:35;;;;:::i;:::-;32686:50;;32777:1;32764:9;:14;;32782:1;32763:20;32787:1;32763:25;32758:443;;2730:4:16;32931:21:18;32940:12;32931:6;:21;:::i;:::-;32930:42;;;;:::i;:::-;32921:51;;:6;:51;:::i;:::-;32912:60;;31339:2481;;32758:443;2730:4:16;33137:21:18;33146:12;33137:6;:21;:::i;:::-;33136:42;;;;:::i;:::-;33127:51;;:6;:51;:::i;31727:1723::-;33376:55;;;;;4578:5:13;33376:55:18;;;2429:25:25;2402:18;;33376:55:18;2283:177:25;31339:2481:18;33474:1;33479;33474:6;33470:350;;33720:3;33703:20;;;1730:8:16;33702:28:18;;-1:-1:-1;33608:31:18;;;;;;1133:4:16;33572:1:18;33555:18;;;33645:30;33607:69;;-1:-1:-1;33748:3:18;;;:::i;:::-;;;33470:350;;;33776:1;33781;33776:6;33772:48;;33802:3;;;:::i;:::-;;;33772:48;33834:19;33848:5;33834:19;;:::i;:::-;;;33892:6;33871:2;:18;;;:27;33867:60;;;33900:27;;;33867:60;33967:6;33945:2;:19;;;:28;33941:62;;;33975:19;;;:28;;;33941:62;34034:11;34021:10;:24;34017:2863;;;34078:14;34087:5;34078:6;:14;:::i;:::-;34065:27;;;;:::i;:::-;;-1:-1:-1;34141:5:18;34124:13;34131:6;34124:4;:13;:::i;:::-;34123:23;;;;:::i;:::-;34110:36;;;;:::i;:::-;;;31312:5578;;34017:2863;34215:10;34193:19;34201:11;34193:5;:19;:::i;:::-;:32;;;;:::i;:::-;34185:40;-1:-1:-1;34256:14:18;34185:40;34256:6;:14;:::i;:::-;34243:27;;;;:::i;:::-;;-1:-1:-1;34319:5:18;34302:13;34309:6;34302:4;:13;:::i;:::-;34301:23;;;;:::i;:::-;34288:36;;;;:::i;:::-;;-1:-1:-1;34427:23:18;34439:11;34427:9;:23;:::i;:::-;34415:35;-1:-1:-1;34480:23:18;34492:11;34480:9;:23;:::i;:::-;34468:35;;34534:266;;;;;;;;34562:9;34534:266;;;;34593:2;:18;;;34534:266;;;;34633:2;:19;;;34534:266;;;;34674:9;34534:266;;;;34713:2;:19;;;34706:4;:26;;;;:::i;:::-;34534:266;;;;34763:2;:18;;;34756:4;:25;;;;:::i;:::-;34534:266;;;34522:6;34529:1;34522:9;;;;;;;;:::i;:::-;;;;;;;;;;;:278;;;;34886:27;;;34931:19;;:28;;;34978:1789;34991:19;;34985:3;;;:::i;:::-;;;;:25;34978:1789;;;35091:24;35104:11;35091:10;:24;:::i;:::-;35083:32;-1:-1:-1;35083:32:18;;-1:-1:-1;35362:12:18;35375:5;35379:1;35375;:5;:::i;:::-;35362:19;;;;;;;;:::i;:::-;;;;;;;35344:12;35357:1;35344:15;;;;;;;;:::i;:::-;;;;;;;:37;;;;:::i;:::-;35330:51;;35420:11;35407:10;:24;35403:1346;;;35471:14;35480:5;35471:6;:14;:::i;:::-;35459:26;-1:-1:-1;35541:5:18;35524:13;35531:6;35524:4;:13;:::i;:::-;35523:23;;;;:::i;:::-;35511:35;;35734:5;35743:1;35734:10;35730:161;;35797:14;35776:35;;:18;35841:19;;;:23;35730:161;35916:5;;35403:1346;36006:10;35984:19;35992:11;35984:5;:19;:::i;:::-;:32;;;;:::i;:::-;35976:40;-1:-1:-1;36105:14:18;35976:40;36105:6;:14;:::i;:::-;36093:26;-1:-1:-1;36239:5:18;36222:13;36229:6;36222:4;:13;:::i;:::-;36221:23;;;;:::i;:::-;36209:35;-1:-1:-1;36282:23:18;36294:11;36282:9;:23;:::i;:::-;36270:35;-1:-1:-1;36343:23:18;36355:11;36343:9;:23;:::i;:::-;36331:35;;36404:322;;;;;;;;36440:9;36404:322;;;;36479:2;:18;;;36404:322;;;;36527:2;:19;;;36404:322;;;;36576:9;36404:322;;;;36623:2;:19;;;36616:4;:26;;;;:::i;:::-;36404:322;;;;36681:2;:18;;;36674:4;:25;;;;:::i;:::-;36404:322;;;36392:6;36399:1;36392:9;;;;;;;;:::i;:::-;;;;;;:334;;;;34978:1789;;;36793:12;:19;36788:1;:24;36784:60;;36814:30;;;;;;;;;;;;29694:7202;;;:::o;36784:60::-;31312:5578;;2660:667:20;2731:22;2869:1;2866;2858:5;2852:12;2845:4;2838:5;2834:16;2825:7;2818:5;2805:66;2896:16;2945:4;2939:11;2926:24;;3027:4;3023:9;3016:4;3009;3003;2999:15;2995:26;2991:42;2980:9;2976:58;2970:4;2963:72;3066:4;3055:9;3048:23;3124:4;3121:1;3114:4;3103:9;3099:20;3084:45;3153:9;3143:168;;3257:4;3251;3245;3230:32;3292:4;3286;3279:18;3143:168;;;2660:667;;;;:::o;36559:1446::-;36777:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36777:22:20;36811:16;36830:72;36848:19;36869:26;36897:4;36830:17;:72::i;:::-;36811:91;;36912:16;36931:73;36949:19;36970:26;36998:5;36931:17;:73::i;:::-;37015:27;;;37052:13;;;:27;;;36912:92;-1:-1:-1;37111:4:20;37094:21;;37090:909;;;37314:77;37337:14;37353:11;37366;37379;37314:22;:77::i;:::-;37271:26;;;37131:260;37227:26;;;37131:260;37188:21;;;37131:260;37149:21;;;37131:260;37090:909;;;37893:95;37917:21;37924:14;37917:4;:21;:::i;:::-;37942:18;37949:11;37942:4;:18;:::i;:::-;37963:11;37976;37893:22;:95::i;:::-;37850:26;;;37710:278;37806:26;;;37710:278;37767:21;;;37710:278;37728:21;;;37710:278;37090:909;36801:1204;;36559:1446;;;;;;;:::o;2381:13621:18:-;2510:18;2561:12;;2605:13;;;;2652:3;2634:21;;;2633:28;;2629:96;;2670:55;;;;;3971:5:13;2670:55:18;;;2429:25:25;2402:18;;2670:55:18;2283:177:25;2629:96:18;2736:37;2743:13;2758:14;2736:6;:37::i;:::-;2788:10;;:24;;2784:53;;2827:10;2814:23;;2784:53;2848:22;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2848:22:18;2885:9;2881:459;;;2910:46;2948:7;2910:46;;2923:11;;;2910:46;2939:7;2910:46;;;3061:29;3030:27;3018:39;;3061:29;3017:73;;;;:::i;:::-;;2998:16;;;:92;2881:459;;;3135:46;3173:7;3135:46;;3148:11;;;3135:46;3164:7;3135:46;;;3286:29;3255:27;3243:39;;3286:29;3242:73;;;;:::i;:::-;;3223:16;;;:92;2881:459;3350:60;3382:2;:16;;;3400:9;3350:31;:60::i;:::-;3421:34;3458:58;3486:13;3501:14;3458:27;:58::i;:::-;3421:95;-1:-1:-1;3531:9:18;:13;3527:243;;3577:9;3564;:22;3560:90;;3595:55;;;;;695:5:13;3595:55:18;;;2429:25:25;2402:18;;3595:55:18;2283:177:25;3560:90:18;3668:10;;:26;;594:42:16;3668:26:18;3664:95;;3703:56;;;;;766:5:13;3703:56:18;;;2429:25:25;2402:18;;3703:56:18;2283:177:25;3664:95:18;1595:7:16;4051:1:18;4033:19;;;4032:27;1296:4:16;4312:2:18;4294:20;;;4293:27;4292:38;;2569:3:16;4273:59:18;4257:13;;;:75;2517:3:16;4501:21:18;;;4492:6;;;:30;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3854:1:18;3837:18;;;;3918:19;;;3917:25;;;;4032:27;;4586;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4586:27:18;4627:5;4636:1;4627:10;4623:1431;;4714:28;4745:258;4789:4;:18;;;4829:4;:15;;;4866:4;:15;;;4903:4;:30;;;4955:4;:30;;;4745:22;:258::i;:::-;4714:289;;5025:9;5021:1009;;;5317:21;;5364;;;;;5411:26;;;;;5463;;;;;5237:29;;;5058:453;5183:28;;;5058:453;5133:24;;;5058:453;;;5021:1009;;;5817:21;;;;;5864;;5911:26;;;;;5963;;;;;5737:29;;;5558:453;;;;5683:28;;;5558:453;5633:24;;;5558:453;;;;;;5021:1009;4696:1348;4623:1431;6068:6;6078:1;6068:11;6064:1736;;6150:22;6175:252;6213:4;:18;;;6253:4;:15;;;6290:4;:15;;;6327:4;:30;;;6379:4;:30;;;6175:16;:252::i;:::-;6150:277;;6449:9;6445:1331;;;6824:13;;6863;;;;;6902:21;;;;;6949;;;;;6996:26;;;;;7048;;;;;6744:29;;;6482:614;6690:28;;;6482:614;6640:24;;;6482:614;6591:23;;;6482:614;6549:16;;;6482:614;;;6445:1331;;;7485:13;;;;;7524;;7563:21;;;;;7610;;;;;7657:26;;;;;7709;;;;;7405:29;;;7143:614;;;;7351:28;;;7143:614;7301:24;;;7143:614;;;;7252:23;;;7143:614;7210:16;;;7143:614;;;;;;6445:1331;6132:1658;6064:1736;8578:1;8546:3;:28;;;8515:3;:28;;;:59;8514:65;;;;;:::i;:::-;;8494:2;:16;;;:86;8490:169;;;8605:54;;;;;4165:5:13;8605:54:18;;;2429:25:25;2402:18;;8605:54:18;2283:177:25;8490:169:18;8684:5;8693:1;8684:10;:25;;;;;8698:6;8708:1;8698:11;8684:25;8680:397;;;8818:248;8850:2;:16;;;8884:3;:29;;;8931:3;:28;;;8977:3;:29;;;9024:3;:28;;;8818:14;:248::i;:::-;8798:17;;;:268;8680:397;9295:2;:17;;;9275:2;:16;;;9271:41;:66;;;;;9336:1;9316:2;:17;;;:21;9271:66;9267:1495;;;9453:17;;;;9564:16;;;;9755:10;;9739:26;;;;:13;;;:26;9793:10;;9779:24;:11;;;:24;9453:17;;-1:-1:-1;9637:1:18;;-1:-1:-1;9564:24:18;;;;-1:-1:-1;9637:1:18;;-1:-1:-1;9267:1495:18;;;9825:5;9834:1;9825:10;:25;;;;-1:-1:-1;9839:11:18;;9825:25;9824:75;;;;9881:2;:16;;;9856:2;:17;;;:42;;9824:75;9820:942;;;10012:16;;;;10197:10;;10181:26;;:13;;;:26;10012:16;-1:-1:-1;10030:1:18;;-1:-1:-1;10030:1:18;;-1:-1:-1;10030:1:18;;-1:-1:-1;9820:942:18;;;10229:10;;:25;;;;;10243:6;10253:1;10243:11;10229:25;10228:55;;;;10281:1;10260:2;:17;;;:22;;10228:55;10224:538;;;10396:16;;;;10579:10;;10565:24;;:11;;;:24;10390:1;;-1:-1:-1;10390:1:18;;-1:-1:-1;10396:16:18;-1:-1:-1;10390:1:18;;-1:-1:-1;10224:538:18;;;10707:44;;;;;825:5:13;10707:44:18;;;2429:25:25;2402:18;;10707:44:18;2283:177:25;10224:538:18;10776:9;;10772:785;;10848:171;2517:3:16;10889:2:18;:6;;;10881:5;:14;;;;:::i;:::-;10880:31;;;;:::i;:::-;10930:3;:28;;;10976:3;:29;;;10848:13;:171::i;:::-;10839:180;;11033:9;:513;;11313:233;11384:6;11357:3;:24;;;:33;;;;:::i;:::-;11414:23;;:31;;11440:5;;11414:31;:::i;:::-;11468:4;:16;;;3059:3:16;11313:21:18;:233::i;:::-;11033:513;;;11105:23;;11061:233;;11105:31;;11131:5;;11105:31;:::i;:::-;11187:6;11160:3;:24;;;:33;;;;:::i;:::-;11216:4;:16;;;3059:3:16;11061:21:18;:233::i;:::-;11570:10;;11566:790;;11644:172;2517:3:16;11686:2:18;:6;;;11677;:15;;;;:::i;:::-;11676:32;;;;:::i;:::-;11727:3;:28;;;11773:3;:29;;;11644:13;:172::i;:::-;11635:181;;11830:9;:515;;12111:234;12182:6;12155:3;:24;;;:33;;;;:::i;:::-;12238:6;12212:3;:23;;;:32;;;;:::i;12111:234::-;11830:515;;;11858:234;11928:6;11902:3;:23;;;:32;;;;:::i;:::-;11985:6;11958:3;:24;;;:33;;;;:::i;11858:234::-;2569:3:16;12513:2:18;:13;;;12505:5;:21;;;;:::i;:::-;12504:40;;;;:::i;:::-;12496:48;;2569:3:16;12573:2:18;:13;;;12564:6;:22;;;;:::i;:::-;12563:41;;;;:::i;:::-;12554:50;;12792:6;12784:5;:14;12780:643;;;12869:9;:227;;13089:6;13057:3;:29;;;:38;;;;:::i;:::-;13039:5;13008:3;:28;;;:36;;;;:::i;:::-;13007:45;;13048:4;13007:45;:::i;:::-;13006:90;;;;:::i;:::-;12869:227;;;12981:5;12950:3;:28;;;:36;;;;:::i;:::-;12931:6;12899:3;:29;;;:38;;;;:::i;:::-;12898:47;;12941:4;12898:47;:::i;:::-;12897:90;;;;:::i;:::-;12858:8;;;:238;12780:643;;;13183:9;:229;;13405:6;13373:3;:29;;;:38;;;;:::i;:::-;13354:6;13323:3;:28;;;:37;;;;:::i;:::-;13322:46;;13364:4;13322:46;:::i;:::-;13321:91;;;;:::i;:::-;13183:229;;;13295:6;13264:3;:28;;;:37;;;;:::i;:::-;13245:6;13213:3;:29;;;:38;;;;:::i;:::-;13212:47;;13255:4;13212:47;:::i;:::-;13211:91;;;;:::i;:::-;13172:8;;;:240;12780:643;13485:9;13481:989;;;13561:27;13520:37;13528:29;13520:5;:37;:::i;:::-;13519:69;;;;:::i;:::-;13510:79;-1:-1:-1;13656:27:18;13614:38;13623:29;13614:6;:38;:::i;:::-;13613:70;;;;:::i;:::-;13603:81;;13828:27;13795:29;13786:6;:38;13785:70;;;;;:::i;:::-;;13775:81;;13927:27;13894:29;13885:6;:38;13884:70;;;;;:::i;:::-;;13874:81;;13481:989;;;14051:27;14010:37;14018:29;14010:5;:37;:::i;:::-;14009:69;;;;:::i;:::-;14000:79;-1:-1:-1;14146:27:18;14104:38;14113:29;14104:6;:38;:::i;:::-;14103:70;;;;:::i;:::-;14093:81;;14318:27;14285:29;14276:6;:38;14275:70;;;;;:::i;:::-;;14265:81;;14417:27;14384:29;14375:6;:38;14374:70;;;;;:::i;:::-;;14364:81;;13481:989;14614:10;;14517:15;;;;-1:-1:-1;14614:26:18;;;;14610:69;;14649:30;;;;;;;;2429:25:25;;;2402:18;;14649:30:18;2283:177:25;14610:69:18;14707:7;:20;;;14694:10;:33;14690:97;;;14736:51;;;;;891:5:13;14736:51:18;;;2429:25:25;2402:18;;14736:51:18;2283:177:25;14690:97:18;14959:9;14970:7;:18;;;14990:10;14948:53;;;;;;;;;13958:25:25;;;14026:14;;14019:22;14014:2;13999:18;;13992:50;14090:42;14078:55;14073:2;14058:18;;14051:83;13946:2;13931:18;;13762:378;14948:53:18;;;;;;;;;;;;;;14938:7;;;:63;15184:10;;15146:17;:9;:17;;;;15172:9;;15200:5;15208:12;15213:6;15208:12;:::i;:::-;15230:1;15242;15246:2;:7;;;15146:108;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;15316:9;:17;;;15334:2;:11;;;15352:6;15347:12;;;:::i;:::-;15374:13;;;;15389:11;;;;15402:12;;;15412:1;15402:12;;;;;;;;;15316:99;;;;;;;;;;;;;15365:6;;15374:13;;15316:99;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;15497:3:18;15479:21;;;1915:10:16;15478:29:18;;-1:-1:-1;15521:9:18;;15517:121;;15546:23;;;:11;;;:23;;;15618:8;;;;15583:44;;15595:5;;15602:1;;15546:23;15583:11;:44::i;:::-;15648:9;:199;;15767:80;1421:5:16;15806:3:18;15788:14;:21;;15787:29;15819:27;15767:18;:80::i;:::-;15648:199;;;15672:80;1421:5:16;15711:3:18;15693:14;:21;;15692:29;15724:27;15672:18;:80::i;:::-;15873:56;15887:2;:8;;;15897:4;:16;;;15915:13;15873;:56::i;:::-;15858:12;:71;;;;15945:50;15950:9;15961;15972:10;15984:7;:10;;;15945:50;;;;;;;;15647:14:25;;15640:22;15622:41;;15694:2;15679:18;;15672:34;;;;15737:2;15722:18;;15715:34;15797:42;15785:55;15780:2;15765:18;;15758:83;15609:3;15594:19;;15397:450;15945:50:18;;;;;;;;2530:13472;;;;;;;;;;2381:13621;;;;;:::o;28430:1570:20:-;28654:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28654:28:20;28694:18;28715:78;28739:19;28760:26;28788:4;28715:23;:78::i;:::-;28694:99;;28803:18;28824:79;28848:19;28869:26;28897:5;28824:23;:79::i;:::-;28803:100;;28935:4;28918:14;:21;28914:841;;;29014:167;29062:14;29094:11;29123:13;29154;29014:30;:167::i;:::-;28984:26;;;28955:226;28956:26;;;28955:226;28914:841;;;29559:185;29608:21;29615:14;29608:4;:21;:::i;:::-;29649:18;29656:11;29649:4;:18;:::i;:::-;29686:13;29717;29559:30;:185::i;:::-;29529:26;;;29500:244;29501:26;;;29500:244;28914:841;29765:37;;;29812:21;;;:37;;;29883:26;;;:43;;;;;;;;29940:26;;;:43;;;;;;;29765:2;28430:1570;-1:-1:-1;;;;;28430:1570:20:o;8773:336::-;8853:13;8869:1;8853:17;8874:1;8853:22;8849:82;;8884:47;;;;;302:5:13;8884:47:20;;;2429:25:25;2402:18;;8884:47:20;2283:177:25;8849:82:20;8945:14;8962:1;8945:18;8967:1;8945:23;8941:87;;8977:51;;;;;558:5:13;8977:51:20;;;2429:25:25;2402:18;;8977:51:20;2283:177:25;8941:87:20;-1:-1:-1;9101:1:20;9085:17;9070:12;:32;8773:336::o;16348:7349::-;16466:34;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16466:34:20;16512:17;16564:3;16546:14;:21;;16571:1;16545:27;16577:1;16544:34;16540:883;;1915:10:16;16677:3:20;16659:14;:21;;16658:29;16643:44;;16705:12;16721:1;16705:17;16701:563;;-1:-1:-1;16818:37:20;;;;;;1133:4:16;16775:2:20;16758:19;;;16861:36;16817:81;16540:883;;16701:563;17177:57;17202:17;17221:12;17177:24;:57::i;:::-;17164:83;;;:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17149:100;;16540:883;;;17365:47;17382:13;17397:14;17365:16;:47::i;:::-;17350:62;;16540:883;17514:41;;;;;;1133:4:16;17475:2:20;17458:19;;;17561:40;17513:89;17652:2;17634:20;;;1685:7:16;17633:28:20;;;;17711:2;17693:20;;;17692:28;17761:1;17755:2;17737:20;;;17736:26;;17735:33;;17731:218;;17878:60;17897:11;17910;17923:14;17878:18;:60::i;:::-;17833:105;-1:-1:-1;17833:105:20;;-1:-1:-1;17833:105:20;-1:-1:-1;17731:218:20;18185:11;2517:3:16;18170:26:20;2517:3:16;18138:12:20;:27;18137:60;;;;;:::i;:::-;;;-1:-1:-1;2517:3:16;18278:26:20;;;18262:43;;18261:60;18342:13;1685:7:16;18587:2:20;18569:20;;;18568:28;18567:34;18563:2384;;18663:2;18645:20;;;1421:5:16;18644:28:20;;;;18732:2;18714:20;;;18713:28;18799:2;18781:20;;;1822:8:16;18780:28:20;18856:1;18850:2;18832:20;;;18831:26;;18830:33;;18826:397;;19039:165;19087:15;19128;19169:13;19039:22;:165::i;:::-;18987:217;;-1:-1:-1;18987:217:20;-1:-1:-1;18987:217:20;-1:-1:-1;18826:397:20;2365:3:16;19391:26:20;;;19422:32;;;19390:65;19389:112;19346:12;:155;19302:16;:200;19273:1642;;;19608:3;19591:20;;;2011:11:16;19590:28:20;19571:15;:48;19711:28;;;19707:321;;;19849:13;19833:12;19817;19803:11;:26;19802:43;19801:61;;;;;:::i;:::-;;19786:12;:76;19771:91;;19707:321;;;19990:11;19975:26;;19707:321;20064:4;20053:15;;19525:566;19273:1642;;;2365:3:16;20215:26:20;;;20246:32;;;20214:65;20213:112;20170:12;:155;20126:16;:200;20097:818;;;20432:3;20415:20;;;2011:11:16;20414:28:20;20395:15;:48;20535:28;;;20531:321;;;20673:13;20657:12;20642:11;20627:12;:26;20626:43;20625:61;;;;;:::i;:::-;;20610:12;:76;20595:91;;20531:321;;;20814:11;20799:26;;20531:321;20888:4;20877:15;;20349:566;20097:818;18603:2344;;;18563:2384;21065:30;;;;;;1133:4:16;21036:3:20;21018:21;;;21101:29;21064:67;21145:20;;;21141:554;;;21260:5;21245:20;;21290:4;21279:15;;21141:554;;;-1:-1:-1;21493:30:20;;;;;;1133:4:16;21460:3:20;21442:21;;;21529:29;21492:67;21577:20;;;21573:112;;;21632:5;21617:20;;21666:4;21655:15;;21573:112;21792:8;21788:820;;;1685:7:16;21850:2:20;21832:14;:20;;21831:28;21816:44;;1685:7:16;21908:2:20;21890:14;:20;;21889:28;21874:44;;21956:2;21938:14;:20;;21962:1;21937:26;21968:1;21936:33;21932:255;;22034:138;22074:11;22107;22140:14;22034:18;:138::i;:::-;21989:183;-1:-1:-1;21989:183:20;;-1:-1:-1;21989:183:20;-1:-1:-1;21932:255:20;22439:11;2517:3:16;22424:26:20;2517:3:16;22392:12:20;:27;22391:60;;;;;:::i;:::-;;;-1:-1:-1;2517:3:16;22540:26:20;;;22524:43;;22523:60;22509:74;;21788:820;22618:39;;;22667:16;;;:31;;;22708:15;;;:29;;;22747:15;;;:29;;;22829:4;22815:18;;22811:430;;;22946:49;22983:11;22969;:25;22946:22;:49::i;:::-;22925:18;;;:70;22811:430;;;23152:67;23213:4;23199:11;:18;23190:4;23176:11;:18;23175:43;23152:22;:67::i;:::-;23222:4;23152:74;23131:18;;;:95;22811:430;23437:54;;;;;23463:27;23437:54;;;2429:25:25;23390:111:20;;23437:9;:25;;;;;2402:18:25;;23437:54:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23390:33;:111::i;:::-;23356:30;;;23323:178;23324:30;;;23323:178;23626:54;;;;;23652:27;23626:54;;;2429:25:25;23579:111:20;;23626:9;:25;;;;;2402:18:25;;23626:54:20;2283:177:25;23579:111:20;23545:30;;;23512:178;23513:30;;;23512:178;-1:-1:-1;23513:4:20;;16348:7349;-1:-1:-1;;;;;;;16348:7349:20:o;873:1832:8:-;979:13;1150:4;1144:11;1292:66;1273:17;1266:93;1417:42;1410:5;1406:54;1402:1;1383:17;1379:25;1372:89;1559:42;1554:3;1550:52;1545:2;1526:17;1522:26;1515:88;1690:7;1685:2;1666:17;1662:26;1655:43;2548:2;2545:1;2540:3;2521:17;2518:1;2510:6;2503:5;2498:53;2066:16;2059:24;2053:2;2035:16;2032:24;2028:1;2024;2018:8;2015:15;2011:46;2008:76;1808:757;1796:769;;;2590:8;2585:114;;2621:67;;;;;995:5:5;2621:67:8;;;2429:25:25;2402:18;;2621:67:8;2283:177:25;2585:114:8;969:1736;873:1832;;;;:::o;34691:901:20:-;34890:43;;;;;;;;2429:25:25;;;34839:15:20;;;;34890:25;:9;:25;;;;2402:18:25;;34890:43:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34866:67;;2110:18:16;4646:1:7;34958:16:20;:62;;34957:70;34944:83;;1337:4:16;35072:10:20;:15;35065:1;35051:10;:15;;35050:38;;35037:51;;35103:16;35122:1;35103:20;35127:1;35103:25;35099:230;;762:4:6;35228:32:20;;;35227:77;35214:90;;35099:230;35376:9;:199;;35545:29;35514:27;35501:10;:40;35500:74;;;;;:::i;:::-;;35376:199;;;35450:29;35419:27;35406:10;:40;35405:74;;;;;:::i;:::-;;35363:212;34691:901;-1:-1:-1;;;;;34691:901:20:o;30723:3569::-;30856:8;;;;;33006;32990:10;:3;32996:4;32990:10;:::i;:::-;32973:9;32979:3;32973;:9;:::i;:::-;32969:32;;;;:::i;:::-;32968:47;;;;:::i;:::-;32958:57;-1:-1:-1;33025:8:20;33037:9;33043:3;33037;:9;:::i;:::-;33025:22;;33069:4;33063:3;:10;:52;;33112:3;33098:10;33104:4;33098:3;:10;:::i;:::-;33097:18;;;;:::i;:::-;33063:52;;;33090:4;33077:9;33083:3;33077;:9;:::i;:::-;33076:18;;;;:::i;:::-;33057:58;-1:-1:-1;33146:47:20;33181:9;33187:3;;33181:9;:::i;:::-;33170:21;;:3;:21;:::i;:::-;33146:22;:47::i;:::-;33136:58;;:3;:58;:::i;:::-;33125:70;-1:-1:-1;33522:9:20;33528:3;33522;:9;:::i;:::-;33507:10;:3;33513:4;33507:10;:::i;:::-;33506:26;;;;:::i;:::-;33498:35;;2517:3:16;33547:4:20;:19;33543:168;;;33649:51;;;;;4785:5:13;33649:51:20;;;2429:25:25;2402:18;;33649:51:20;2283:177:25;33543:168:20;33730:4;33724:3;:10;33720:234;;;33778:4;33758:9;33764:3;;33758:9;:::i;:::-;:16;;33770:4;33758:16;:::i;:::-;33757:25;;;;:::i;:::-;33750:32;;33720:234;;;33931:11;33938:4;33931;:11;:::i;:::-;33917:9;33923:3;;33917:9;:::i;:::-;33916:27;;;;:::i;:::-;33909:34;;33720:234;34145:3;34138;34124:10;34145:3;34124:4;:10;:::i;:::-;34123:18;;;;:::i;:::-;34122:26;;;;:::i;:::-;34115:33;-1:-1:-1;34274:10:20;34281:3;34274:4;:10;:::i;:::-;34259;34266:3;34259:4;:10;:::i;:::-;34258:27;;;;:::i;:::-;34252:33;;30898:3394;;30723:3569;;;;;;;;;:::o;10183:475::-;2517:3:16;10459:15:20;:30;:55;;;;2166:26:16;10493:15:20;:21;10459:55;:81;;;;2313:3:16;10518:7:20;:22;10459:81;:99;;;;2231:34:16;10544:7:20;:14;10459:99;10455:196;;;10579:72;;;;;4508:5:13;10579:72:20;;;2429:25:25;2402:18;;10579:72:20;2283:177:25;10455:196:20;10183:475;;:::o;5631:664::-;5720:6;;6090:36;6113:5;6117:1;6113;:5;:::i;:::-;:12;;6121:4;6113:12;:::i;6090:36::-;6075:51;-1:-1:-1;6136:14:20;6153:38;6176:7;6181:2;6176;:7;:::i;6153:38::-;6136:55;-1:-1:-1;6268:19:20;6136:55;6268:7;:19;:::i;:::-;6246:13;6250:9;6246:1;:13;:::i;:::-;6227:11;6231:7;6227:1;:11;:::i;:::-;6212:12;6217:7;6212:2;:12;:::i;:::-;:26;;;;:::i;:::-;6208:52;;;;:::i;:::-;6207:81;;;;:::i;:::-;6202:86;5631:664;-1:-1:-1;;;;;;;;5631:664:20:o;3641:538::-;3773:18;3938:24;;;3999:23;;;;3938:24;3999:23;4137:25;;;;:::i;:::-;;;3641:538;-1:-1:-1;;;;;;3641:538:20:o;9290:353::-;9520:28;9535:13;9520:12;:28;:::i;:::-;9493:22;:15;9511:4;9493:22;:::i;:::-;9492:57;;;;:::i;:::-;9472:15;9471:79;9466:171;;;9574:52;;;;;625:5:13;9574:52:20;;;2429:25:25;2402:18;;9574:52:20;2283:177:25;9466:171:20;9290:353;;;;:::o;9824:::-;10062:20;10069:13;10062:4;:20;:::i;:::-;10027:30;10045:12;10027:15;:30;:::i;:::-;10026:57;;;;:::i;:::-;10006:15;10005:79;10000:171;;;10108:52;;;;;625:5:13;10108:52:20;;;2429:25:25;2402:18;;10108:52:20;2283:177:25;45968:549:20;46090:57;46115:17;46134:12;46090:24;:57::i;:::-;46084:211;;;;;;;;17323:25:25;;;17391:14;;17384:22;17364:18;;;17357:50;46084:73:20;46225:7;17504:15:25;;17484:18;;;17477:43;46250:7:20;17556:15:25;;17536:18;;;17529:43;17588:19;;;17581:35;;;46084:73:20;;;;;;;17295:19:25;;46084:211:20;;;;;;;;;;;;;;;;;;;-1:-1:-1;46084:211:20;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;46068:443;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46420:91;46068:443;;;46344:5;46339:69;;46358:50;;;;;1044:5:13;46358:50:20;;;2429:25:25;2402:18;;46358:50:20;2283:177:25;7672:1095:20;2365:3:16;7780:17:20;:34;7776:985;;;7850:22;:17;7870:2;7850:22;:::i;:::-;7988:45;;;;;;;;2429:25:25;;;7830:42:20;;-1:-1:-1;7954:31:20;;7988:25;:9;:25;;;;2402:18:25;;7988:45:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2197:2:7;8093:81:20;1507:6:16;8092:105:20;;-1:-1:-1;8606:46:20;;;8602:148;;;8677:73;;;;;979:5:13;8677:73:20;;;2429:25:25;2402:18;;8677:73:20;2283:177:25;8602:148:20;7816:945;7672:1095;;:::o;38845:7117::-;38941:4;;39029:48;39066:3;39049:20;;;2011:11:16;39048:28:20;39029:15;:48;:::i;:::-;39012:65;;39087:10;39107:11;39128;39154:9;39167:1;39154:14;39150:1349;;39375:30;;;;;;1133:4:16;39343:2:20;39326:19;;;39411:29;39374:67;;-1:-1:-1;2569:3:16;39672:18:20;39671:28;;39670:47;39654:12;:64;39653:156;;;-1:-1:-1;2569:3:16;39762:18:20;39761:28;;39760:47;39744:12;:64;39653:156;39628:302;;;39857:54;;;;;4719:5:13;39857:54:20;;;2429:25:25;2402:18;;39857:54:20;2283:177:25;39628:302:20;40051:30;;;;;;1133:4:16;40020:1:20;40003:18;;;40087:29;40050:67;;-1:-1:-1;40132:33:20;40050:67;40155:9;40132:15;:33::i;:::-;-1:-1:-1;40484:2:20;40424:56;:9;40446:2;40450:1;998:5:2;40424:21:20;:56::i;:::-;:62;;40321:13;40337:66;40321:82;40320:167;40312:176;;;;;;;;39150:1349;40532:3;40515:13;:20;;40539:1;40514:26;40545:1;40513:33;40509:5447;;40702:30;;;;;;1133:4:16;40669:2:20;40652:19;;;40738:29;40701:67;;-1:-1:-1;40783:33:20;40701:67;40806:9;40783:15;:33::i;:::-;-1:-1:-1;41179:15:20;41198:3;41179:22;41156:2;41093:59;:12;41118:2;41122:1;998:5:2;41093:24:20;:59::i;:::-;:65;;41070:2;41010:56;:9;41032:2;41036:1;998:5:2;41010:21:20;:56::i;:::-;40868:66;40852:82;;40955:34;;;;;;40851:139;41010:62;;40851:222;:308;:351;;-1:-1:-1;40843:360:20;;-1:-1:-1;;;;40843:360:20;40509:5447;41380:30;;;;;;;1133:4:16;41349:1:20;41332:18;;;41416:29;;41379:67;;;;;-1:-1:-1;41556:31:20;;;;;;;41523:2;41506:19;;;41593:30;;;41555:69;;-1:-1:-1;41639:14:20;41656:34;41555:69;41680:9;41656:15;:34::i;:::-;41639:51;;41850:6;2730:4:16;41822:5:20;:24;41821:35;;;;;:::i;:::-;;2730:4:16;41793:64:20;41780:77;;42067:1;42054:10;:14;42050:300;;;42147:1;2789:8:16;1730;42109:10:20;42108:11;;42103:23;42102:40;;;;;:::i;:::-;;42101:47;;42092:56;;42050:300;;;42325:1;2789:8:16;1730;42282:22:20;;42281:39;42280:46;;42330:1;42279:52;42270:61;;42050:300;1730:8:16;42382:9:20;:15;42378:237;;;1730:8:16;42585:15:20;;42378:237;42693:3;42676:20;;;1730:8:16;42675:28:20;;-1:-1:-1;42759:3:20;42742:20;;;1215:3:16;42741:27:20;42819:3;42802:20;;;1551:6:16;42801:28:20;1378:5:16;42847:10:20;;42843:2404;;;42881:19;;42877:1628;;43102:2;43092:12;;;;43118:1;43109:10;;;43091:29;;43198:17;;;:::i;:::-;;-1:-1:-1;43198:22:20;:17;43218:2;43198:22;:::i;:::-;43164:19;;;;:7;:19;;;;;;;43187:34;;;;43164:58;;;43142:80;;43248:19;;43244:466;;43295:17;;;:::i;:::-;;;42843:2404;;43244:466;43493:1;43475:19;;43592:20;43574:10;43587:1;43574:14;43573:39;;;;;:::i;:::-;;43686:1;43664:19;;;:7;:19;;;;;:23;43573:39;-1:-1:-1;42843:2404:20;;42877:1628;44076:19;;;;:7;:19;;;;;;;;;;44031:1;44021:11;;;;44076:28;;;44054:50;;44076:7;-1:-1:-1;44289:20:20;-1:-1:-1;44271:14:20;;44289:20;44270:39;;;;:::i;:::-;;44441:19;;;;:7;:19;;;;;44473:12;44463:23;;;44441:45;;44270:39;-1:-1:-1;42843:2404:20;;;44568:5;44563:1;44553:6;:11;;44552:21;44543:30;;44645:1;44627:15;:19;44623:249;;;44696:19;;;;:7;44748:2;44696:19;;;;;;;;;44730:20;;;44719:32;;;44696:56;;;44674:78;;44623:249;;;44807:19;;;;:7;:19;;;;;44841:6;44829:20;;;44807:42;;44623:249;44911:19;;44907:326;;44954:17;;;:::i;44907:326::-;45036:1;45018:19;;45127:20;45109:10;45122:1;45109:14;45108:39;;;;;:::i;:::-;;45213:1;45191:19;;;:7;:19;;;;;:23;45108:39;-1:-1:-1;44907:326:20;45358:9;;-1:-1:-1;45390:12:20;;-1:-1:-1;45425:13:20;;-1:-1:-1;45940:3:20;45926:17;;;45902:3;45883:22;;;45859:3;45846:16;;;45803:15;45822:3;45803:22;45780:2;45723:53;45390:12;45742:2;45746:1;998:5:2;45723:18:20;:53::i;:::-;:59;;45700:2;45644:52;:5;45662:2;45666:1;998:5:2;45644:17:20;:52::i;:::-;:58;;45622:1;2060:12:16;45608:2:20;45598:6;:12;;45597:20;45596:27;;45500:6;45509:66;45500:75;45499:125;:204;:284;:327;:364;:407;:445;45491:454;;;;;;;;;38845:7117;;;;;;:::o;23991:2027::-;24132:8;;;25625:9;25631:3;25625;:9;:::i;:::-;25614:20;-1:-1:-1;25644:8:20;25687:7;25614:20;25687:1;:7;:::i;:::-;25671:10;:3;25677:4;25671:10;:::i;:::-;25657:9;25663:3;25657;:9;:::i;:::-;25656:26;;;;:::i;:::-;25655:40;;;;:::i;:::-;25644:51;-1:-1:-1;25705:8:20;25716:9;25722:3;25716;:9;:::i;:::-;25705:20;;25780:4;25774:3;:10;25773:56;;25812:9;25818:3;25812;:9;:::i;:::-;25811:18;;25825:4;25811:18;:::i;:::-;25773:56;;;25804:3;25790:10;:3;25796:4;25790:10;:::i;:::-;25789:18;;;;:::i;:::-;25767:62;-1:-1:-1;25934:43:20;25965:9;25971:3;;25965:9;:::i;25934:43::-;25928:49;;:3;:49;:::i;:::-;25922:55;-1:-1:-1;26007:4:20;25994:9;26000:3;25922:55;25994:9;:::i;:::-;25993:18;;;;:::i;:::-;25987:24;;24152:1866;;;23991:2027;;;;;;;:::o;548:1201:1:-;628:17;889;920:6;930:4;920:14;916:767;;965:1;950:17;;;;;916:767;998:4;988:6;:14;984:699;;1025:74;;1042:12;1025:74;;;17917:28:25;1056:12:1;17961:11:25;;;17954:36;18040:66;18027:2;18023:15;;;18019:88;18006:11;;;17999:109;18146:3;18142:16;;;17842:66;18138:25;18124:12;;;18117:47;18180:12;;1025:74:1;;;;;;;;;;;;;1018:81;;984:699;;;1130:4;1120:6;:14;1116:567;;1157:88;;1174:12;1157:88;;;18519:28:25;1188:12:1;18563:11:25;;;18556:36;18642:66;18629:2;18625:15;;;18621:88;18608:11;;;18601:109;1217:12:1;18726::25;;;18719:37;18794:3;18790:16;;;18444:66;18786:25;18772:12;;;18765:47;18828:12;;1157:88:1;18203:643:25;1116:567:1;1276:6;1266;:16;1262:421;;1305:89;;1322:12;1305:89;;;19169:28:25;1336:12:1;19213:11:25;;;19206:36;19292:66;19279:2;19275:15;;;19271:88;19258:11;;;19251:109;1365:12:1;19376::25;;;19369:37;19458:66;19444:3;19440:16;;;19436:89;19422:12;;;19415:111;19542:12;;1305:89:1;18851:709:25;1262:421:1;1425:8;1415:6;:18;1411:272;;1456:89;;1473:12;1456:89;;;19883:28:25;1487:12:1;19927:11:25;;;19920:36;20006:66;19993:2;19989:15;;;19985:88;19972:11;;;19965:109;1516:12:1;20090::25;;;20083:37;20172:66;20158:3;20154:16;;;20150:89;20136:12;;;20129:111;20256:12;;1456:89:1;19565:709:25;1411:272:1;1583:89;;1600:12;1583:89;;;20597:28:25;1614:12:1;20641:11:25;;;20634:36;20720:66;20707:2;20703:15;;;20699:88;20686:11;;;20679:109;1643:12:1;20804::25;;;20797:37;20886:66;20872:3;20868:16;;;20864:89;20850:12;;;20843:111;20970:12;;1583:89:1;;;;;;;;;;;;1576:96;;1411:272;1724:15;;;;;;;;-1:-1:-1;548:1201:1;;;;;:::o;14087:387:20:-;14321:90;;;;;3737:25:25;;;3778:18;;;3771:34;;;14172:20:20;;14251:178;;14279:20;;14344:35;;3710:18:25;;14321:90:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14251:6;:178::i;:::-;14223:244;;;;;;;;;;;;:::i;11208:574::-;11486:221;;;;;21195:25:25;;;21236:18;;;21229:34;;;21279:18;;;21272:34;;;11341:4:20;;;;;;11416:309;;11444:20;;11534:37;;21168:18:25;;11486:221:20;20993:319:25;11416:309:20;11388:387;;;;;;;;;;;;:::i;:::-;11369:406;;;;;;11208:574;;;;;;;:::o;12342:598::-;12632:233;;;;;21195:25:25;;;21236:18;;;21229:34;;;21279:18;;;21272:34;;;12487:4:20;;;;;;12562:321;;12590:20;;12680:41;;21168:18:25;;12632:233:20;20993:319:25;5746:3396:24;5976:3;5890:1;6425:37;6419:44;;6409:136;;6525:2;6521:10;;;;;6492:3;6488:11;6409:136;6574:21;6571:1;6568:28;6558:119;;6657:2;6653:10;;;;;6625:2;6621:10;6558:119;6706:13;6703:1;6700:20;6690:111;;6781:2;6777:10;;;;;6749:2;6745:10;6690:111;6830:9;6827:1;6824:16;6814:106;;6901:1;6897:9;;;;;6869:2;6865:10;6814:106;8137:5;8130:13;8123:21;8119:2;8115:30;8325:9;;;8318:17;8315:1;8311:25;;;8368:9;;;8361:17;8354:25;;8411:9;;;8404:17;8397:25;;8454:9;;;8447:17;8440:25;;8497:9;;;8490:17;8483:25;;8540:9;;;8533:17;8526:25;;8583:9;;;8576:17;8569:25;;9112:9;;;;9109:16;-1:-1:-1;9102:24:24;;;5746:3396::o;2065:10605:6:-;1457:18;2422:2:7;2308:89:6;;;2307:109;;;2501:3:7;2462:89:6;;;2461:109;2585:25;;;:54;;-1:-1:-1;2614:25:6;;2585:54;2581:162;;;2662:70;;;;;395:5:5;2662:70:6;;;2429:25:25;2402:18;;2662:70:6;2283:177:25;2581:162:6;1273:6;2769:30;;2343:2:7;2987:82:6;;;1408:11;2986:90;2951:15;:126;;;;2643:3:7;3116:80:6;;;1229:6;3115:104;;3237:28;;:42;;-1:-1:-1;3269:10:6;;3237:42;:63;;;;3283:12;3299:1;3283:17;3237:63;3233:377;;;3544:51;;;2065:10605;;;:::o;3233:377::-;3990:32;3915:28;;;:54;;3914:109;3874:149;;;;1229:6;2572:3:7;6250:24:6;:80;;6249:88;6241:96;;6356:5;6365:1;6356:10;6352:283;;6569:51;;;2065:10605;;;:::o;6352:283::-;6780:5;6788:1;6780:9;6793:1;6780:14;6776:2287;;6930:1;6921:10;;;;;;7586:20;6921:10;7585:30;;;;:::i;:::-;;;-1:-1:-1;1090:3:6;2197:2:7;7851:79:6;;;1185:6;7850:87;7966:4;:12;;7849:130;7848:244;7755:337;;6776:2287;;;8341:1;8332:10;;;;;8936:29;2197:2:7;8700:79:6;;;1185:6;8699:87;1090:3;8889:21;;8667:244;:4;:244;8666:300;8566:400;;6776:2287;9303:12;9318:1;9303:16;9323:1;9303:21;9299:1880;;9474:1;9458:17;1090:3;10238:28;;10229:4;10214:19;;10238:28;10213:54;;;;:::i;:::-;;10198:69;;9299:1880;;;10552:1;10536:17;1090:3;10830:28;;10821:4;10806:19;;10830:28;10805:54;;;;:::i;:::-;;10797:4;:63;10781:80;;9299:1880;11439:4;11399:36;;;1090:3;11399:36;1273:6;11979:30;;11398:45;;;11978:71;2128:2:7;12107:71:6;;;1185:6;12106:79;1090:3;12089:97;11978:209;;-1:-1:-1;12470:64:6;12395:28;;;:54;;12394:141;12369:167;;;;2832:9832;;2224:10446;2065:10605;;;:::o;38011:828:20:-;38091:14;38305:9;38273:28;2730:4:16;38273:9:20;:28;:::i;:::-;38272:42;;;;:::i;:::-;38244:71;;2730:4:16;38244:71:20;:::i;:::-;38231:84;;2789:8:16;38355:10:20;:30;38354:69;;;-1:-1:-1;38404:18:20;38391:31;;38354:69;38350:473;;;38751:57;;;;;3643:5:13;38751:57:20;;;2429:25:25;2402:18;;38751:57:20;2283:177:25;2369:2808:2;2528:17;2580:12;2620:6;2654:34;2645:7;2642:47;2639:145;;;2723:4;;-1:-1:-1;2719:18:2;;2639:145;2812:18;2803:7;2800:31;2797:144;;;2865:4;2908:19;;;;2861:18;2797:144;2969:10;2960:7;2957:23;2954:136;;;3014:4;3057:19;;;;3010:18;2954:136;3118:6;3109:7;3106:19;3103:132;;;3159:4;3202:19;;;;3155:18;3103:132;3263:4;3254:7;3251:17;3248:128;;;3302:3;3344:18;;;;3298:17;3248:128;3404:3;3395:7;3392:16;3389:127;;;3442:3;3484:18;;;;3438:17;3389:127;3544:3;3535:7;3532:16;3529:127;;;3582:3;3624:18;;;;3578:17;3529:127;3684:3;3675:7;3672:16;3669:80;;;3733:1;3723:8;3719:16;3707:28;;3669:80;3765:14;;3762:78;;3824:1;3814:8;3810:16;3798:28;;3762:78;;3869:15;3859:8;3856:29;3853:131;;;-1:-1:-1;3955:15:2;3853:131;4027:15;4017:8;4013:30;3997:46;;4089:6;4079:8;4075:21;4138:1;4128:8;4125:15;4116:7;4112:29;4109:670;;;4319:1;4306:11;4302:19;4287:34;;4369:11;4365:1;4348:15;4344:23;4341:40;4338:427;;-1:-1:-1;4696:1:2;4731:16;;;;4671:23;;;4667:31;4338:427;4833:1;4819:12;4815:20;4805:8;4802:34;4792:263;;5039:1;5036;5029:12;4792:263;5081:30;;;5137:24;;;;;-1:-1:-1;;;;2369:2808:2:o;14:454:25:-;109:6;117;125;133;141;194:3;182:9;173:7;169:23;165:33;162:53;;;211:1;208;201:12;162:53;-1:-1:-1;;234:23:25;;;304:2;289:18;;276:32;;-1:-1:-1;355:2:25;340:18;;327:32;;406:2;391:18;;378:32;;-1:-1:-1;457:3:25;442:19;429:33;;-1:-1:-1;14:454:25;-1:-1:-1;14:454:25:o;855:262::-;1049:3;1034:19;;1062:49;1038:9;1093:6;557:5;551:12;546:3;539:25;613:4;606:5;602:16;596:23;589:4;584:3;580:14;573:47;669:4;662:5;658:16;652:23;645:4;640:3;636:14;629:47;725:4;718:5;714:16;708:23;701:4;696:3;692:14;685:47;781:4;774:5;770:16;764:23;757:4;752:3;748:14;741:47;837:4;830:5;826:16;820:23;813:4;808:3;804:14;797:47;;;473:377;1394:268;1202:12;;1190:25;;1264:4;1253:16;;;1247:23;1231:14;;;1224:47;1320:4;1309:16;;;1303:23;1287:14;;;1280:47;1376:4;1365:16;;;1359:23;1343:14;;;1336:47;1592:3;1577:19;;1605:51;1122:267;1667:154;1753:42;1746:5;1742:54;1735:5;1732:65;1722:93;;1811:1;1808;1801:12;1722:93;1667:154;:::o;1826:452::-;1912:6;1920;1928;1936;1989:3;1977:9;1968:7;1964:23;1960:33;1957:53;;;2006:1;2003;1996:12;1957:53;2042:9;2029:23;2019:33;;2099:2;2088:9;2084:18;2071:32;2061:42;;2150:2;2139:9;2135:18;2122:32;2112:42;;2204:2;2193:9;2189:18;2176:32;2217:31;2242:5;2217:31;:::i;:::-;1826:452;;;;-1:-1:-1;1826:452:25;;-1:-1:-1;;1826:452:25:o;2465:118::-;2551:5;2544:13;2537:21;2530:5;2527:32;2517:60;;2573:1;2570;2563:12;2588:519;2671:6;2679;2687;2695;2748:3;2736:9;2727:7;2723:23;2719:33;2716:53;;;2765:1;2762;2755:12;2716:53;2804:9;2791:23;2823:28;2845:5;2823:28;:::i;:::-;2870:5;-1:-1:-1;2922:2:25;2907:18;;2894:32;;-1:-1:-1;2973:2:25;2958:18;;2945:32;;-1:-1:-1;3029:2:25;3014:18;;3001:32;3042:33;3001:32;3042:33;:::i;3112:446::-;3195:6;3203;3211;3219;3272:3;3260:9;3251:7;3247:23;3243:33;3240:53;;;3289:1;3286;3279:12;3240:53;3325:9;3312:23;3302:33;;3382:2;3371:9;3367:18;3354:32;3344:42;;3433:2;3422:9;3418:18;3405:32;3395:42;;3487:2;3476:9;3472:18;3459:32;3500:28;3522:5;3500:28;:::i;4097:794::-;4185:6;4193;4201;4209;4262:2;4250:9;4241:7;4237:23;4233:32;4230:52;;;4278:1;4275;4268:12;4230:52;4317:9;4304:23;4336:31;4361:5;4336:31;:::i;:::-;4386:5;-1:-1:-1;4438:2:25;4423:18;;4410:32;;-1:-1:-1;4493:2:25;4478:18;;4465:32;4516:18;4546:14;;;4543:34;;;4573:1;4570;4563:12;4543:34;4611:6;4600:9;4596:22;4586:32;;4656:7;4649:4;4645:2;4641:13;4637:27;4627:55;;4678:1;4675;4668:12;4627:55;4718:2;4705:16;4744:2;4736:6;4733:14;4730:34;;;4760:1;4757;4750:12;4730:34;4805:7;4800:2;4791:6;4787:2;4783:15;4779:24;4776:37;4773:57;;;4826:1;4823;4816:12;4773:57;4097:794;;;;-1:-1:-1;;4857:2:25;4849:11;;-1:-1:-1;;;4097:794:25:o;4896:180::-;4955:6;5008:2;4996:9;4987:7;4983:23;4979:32;4976:52;;;5024:1;5021;5014:12;4976:52;-1:-1:-1;5047:23:25;;4896:180;-1:-1:-1;4896:180:25:o;5648:1616::-;5875:13;;5857:32;;5936:4;5924:17;;;5918:24;5844:3;5829:19;;;5951:54;;5984:20;;5918:24;5158:42;5147:54;5135:67;;5081:127;5951:54;;6054:4;6046:6;6042:17;6036:24;6069:56;6119:4;6108:9;6104:20;6088:14;5158:42;5147:54;5135:67;;5081:127;6069:56;;6174:4;6166:6;6162:17;6156:24;6189:71;6254:4;6243:9;6239:20;6223:14;5292:42;5373:2;5365:5;5359:12;5355:21;5350:3;5343:34;5438:2;5430:4;5423:5;5419:16;5413:23;5409:32;5402:4;5397:3;5393:14;5386:56;5503:2;5495:4;5488:5;5484:16;5478:23;5474:32;5467:4;5462:3;5458:14;5451:56;5568:2;5560:4;5553:5;5549:16;5543:23;5539:32;5532:4;5527:3;5523:14;5516:56;5633:2;5625:4;5618:5;5614:16;5608:23;5604:32;5597:4;5592:3;5588:14;5581:56;;5213:430;;;6189:71;;6309:4;6301:6;6297:17;6291:24;6334:6;6349:54;6399:2;6388:9;6384:18;6368:14;5158:42;5147:54;5135:67;;5081:127;6349:54;6452:4;6444:6;6440:17;6434:24;6412:46;;6477:6;6492:54;6542:2;6531:9;6527:18;6511:14;5158:42;5147:54;5135:67;;5081:127;6492:54;6595:4;6587:6;6583:17;6577:24;6555:46;;6620:6;6635:54;6685:2;6674:9;6670:18;6654:14;5158:42;5147:54;5135:67;;5081:127;6635:54;6726:4;6714:17;;6708:24;6751:6;6773:18;;;6766:30;;;;6821:15;;;6815:22;6856:6;6878:18;;;6871:30;;;;6926:15;;;6920:22;6961:6;6983:18;;;6976:30;;;;7052:15;;;7046:22;7037:6;7022:22;;7015:54;7115:15;;;7109:22;7100:6;7085:22;;7078:54;7178:15;;7172:22;7163:6;7148:22;;7141:54;7241:15;;;7235:22;7226:6;7211:22;;;7204:54;;;;5648:1616;;-1:-1:-1;5648:1616:25:o;7269:184::-;7321:77;7318:1;7311:88;7418:4;7415:1;7408:15;7442:4;7439:1;7432:15;7458:1174;7542:6;7573:2;7616;7604:9;7595:7;7591:23;7587:32;7584:52;;;7632:1;7629;7622:12;7584:52;7672:9;7659:23;7701:18;7742:2;7734:6;7731:14;7728:34;;;7758:1;7755;7748:12;7728:34;7796:6;7785:9;7781:22;7771:32;;7841:7;7834:4;7830:2;7826:13;7822:27;7812:55;;7863:1;7860;7853:12;7812:55;7899:2;7886:16;7921:2;7917;7914:10;7911:36;;;7927:18;;:::i;:::-;7973:2;7970:1;7966:10;8005:2;7999:9;8064:66;8059:2;8055;8051:11;8047:84;8039:6;8035:97;8182:6;8170:10;8167:22;8162:2;8150:10;8147:18;8144:46;8141:72;;;8193:18;;:::i;:::-;8229:2;8222:22;8279:18;;;8313:15;;;;-1:-1:-1;8355:11:25;;;8351:20;;;8383:19;;;8380:39;;;8415:1;8412;8405:12;8380:39;8439:11;;;;8459:142;8475:6;8470:3;8467:15;8459:142;;;8541:17;;8529:30;;8492:12;;;;8579;;;;8459:142;;8637:779;8903:2;8915:21;;;8985:13;;8888:18;;;9007:22;;;8855:4;;9082;;9060:2;9045:18;;;9109:15;;;8855:4;9152:195;9166:6;9163:1;9160:13;9152:195;;;9215:50;9261:3;9252:6;9246:13;557:5;551:12;546:3;539:25;613:4;606:5;602:16;596:23;589:4;584:3;580:14;573:47;669:4;662:5;658:16;652:23;645:4;640:3;636:14;629:47;725:4;718:5;714:16;708:23;701:4;696:3;692:14;685:47;781:4;774:5;770:16;764:23;757:4;752:3;748:14;741:47;837:4;830:5;826:16;820:23;813:4;808:3;804:14;797:47;;;473:377;9215:50;9294:4;9285:14;;;;;9322:15;;;;9188:1;9181:9;9152:195;;;-1:-1:-1;;;9383:18:25;;9376:34;;;;9364:3;8637:779;-1:-1:-1;;8637:779:25:o;9652:245::-;9719:6;9772:2;9760:9;9751:7;9747:23;9743:32;9740:52;;;9788:1;9785;9778:12;9740:52;9820:9;9814:16;9839:28;9861:5;9839:28;:::i;10234:184::-;10304:6;10357:2;10345:9;10336:7;10332:23;10328:32;10325:52;;;10373:1;10370;10363:12;10325:52;-1:-1:-1;10396:16:25;;10234:184;-1:-1:-1;10234:184:25:o;10423:245::-;10502:6;10510;10563:2;10551:9;10542:7;10538:23;10534:32;10531:52;;;10579:1;10576;10569:12;10531:52;-1:-1:-1;;10602:16:25;;10658:2;10643:18;;;10637:25;10602:16;;10637:25;;-1:-1:-1;10423:245:25:o;11468:458::-;11550:6;11558;11566;11619:2;11607:9;11598:7;11594:23;11590:32;11587:52;;;11635:1;11632;11625:12;11587:52;11671:9;11658:23;11648:33;;11731:2;11720:9;11716:18;11703:32;11744:28;11766:5;11744:28;:::i;:::-;11791:5;-1:-1:-1;11848:2:25;11833:18;;11820:32;11861:33;11820:32;11861:33;:::i;:::-;11913:7;11903:17;;;11468:458;;;;;:::o;12233:184::-;12285:77;12282:1;12275:88;12382:4;12379:1;12372:15;12406:4;12403:1;12396:15;12422:184;12474:77;12471:1;12464:88;12571:4;12568:1;12561:15;12595:4;12592:1;12585:15;12611:128;12678:9;;;12699:11;;;12696:37;;;12713:18;;:::i;12744:195::-;12783:3;12814:66;12807:5;12804:77;12801:103;;12884:18;;:::i;:::-;-1:-1:-1;12931:1:25;12920:13;;12744:195::o;12944:196::-;12983:3;13011:5;13001:39;;13020:18;;:::i;:::-;-1:-1:-1;13067:66:25;13056:78;;12944:196::o;13145:168::-;13218:9;;;13249;;13266:15;;;13260:22;;13246:37;13236:71;;13287:18;;:::i;13318:184::-;13370:77;13367:1;13360:88;13467:4;13464:1;13457:15;13491:4;13488:1;13481:15;13507:120;13547:1;13573;13563:35;;13578:18;;:::i;:::-;-1:-1:-1;13612:9:25;;13507:120::o;13632:125::-;13697:9;;;13718:10;;;13715:36;;;13731:18;;:::i;14145:191::-;14180:3;14211:66;14204:5;14201:77;14198:103;;14281:18;;:::i;:::-;-1:-1:-1;14321:1:25;14317:13;;14145:191::o;14341:1051::-;14587:4;14616:42;14697:2;14689:6;14685:15;14674:9;14667:34;14720:2;14758:6;14753:2;14742:9;14738:18;14731:34;14801:6;14796:2;14785:9;14781:18;14774:34;14856:2;14848:6;14844:15;14839:2;14828:9;14824:18;14817:43;14909:2;14901:6;14897:15;14891:3;14880:9;14876:19;14869:44;14950:3;14944;14933:9;14929:19;14922:32;14983:6;14977:13;14963:27;;15027:6;15021:3;15010:9;15006:19;14999:35;15052:1;15062:141;15076:6;15073:1;15070:13;15062:141;;;15172:14;;;15168:23;;15162:30;15137:17;;;15156:3;15133:27;15126:67;15091:10;;15062:141;;;15066:3;;15253:1;15247:3;15238:6;15227:9;15223:22;15219:32;15212:43;15382:3;15312:66;15307:2;15299:6;15295:15;15291:88;15280:9;15276:104;15272:114;15264:122;;;14341:1051;;;;;;;;;:::o;16034:200::-;16100:9;;;16073:4;16128:9;;16156:10;;16168:12;;;16152:29;16191:12;;;16183:21;;16149:56;16146:82;;;16208:18;;:::i;:::-;16146:82;16034:200;;;;:::o;16239:308::-;16278:1;16304;16294:35;;16309:18;;:::i;:::-;16426:66;16423:1;16420:73;16351:66;16348:1;16345:73;16341:153;16338:179;;;16497:18;;:::i;:::-;-1:-1:-1;16531:10:25;;16239:308::o;16552:292::-;16624:9;;;16591:7;16649:9;;16666:66;16660:73;;16645:89;16642:115;;;16737:18;;:::i;:::-;16810:1;16801:7;16796:16;16793:1;16790:23;16786:1;16779:9;16776:38;16766:72;;16818:18;;:::i;16849:216::-;16913:9;;;16941:11;;;16888:3;16971:9;;16999:10;;16995:19;;17024:10;;17016:19;;16992:44;16989:70;;;17039:18;;:::i;21317:306::-;21405:6;21413;21421;21474:2;21462:9;21453:7;21449:23;21445:32;21442:52;;;21490:1;21487;21480:12;21442:52;21519:9;21513:16;21503:26;;21569:2;21558:9;21554:18;21548:25;21538:35;;21613:2;21602:9;21598:18;21592:25;21582:35;;21317:306;;;;;:::o","linkReferences":{},"immutableReferences":{"9244":[{"start":985,"length":32},{"start":3371,"length":32}],"9247":[{"start":3515,"length":32},{"start":7038,"length":32},{"start":7187,"length":32},{"start":14484,"length":32}],"9250":[{"start":3555,"length":32},{"start":6998,"length":32},{"start":7227,"length":32},{"start":14524,"length":32}],"9254":[{"start":1786,"length":32},{"start":7107,"length":32},{"start":9163,"length":32},{"start":9250,"length":32},{"start":9684,"length":32},{"start":9768,"length":32},{"start":13271,"length":32}],"9256":[{"start":1821,"length":32},{"start":7074,"length":32},{"start":9199,"length":32},{"start":9286,"length":32},{"start":9717,"length":32},{"start":9801,"length":32},{"start":13238,"length":32}],"9258":[{"start":1859,"length":32},{"start":7296,"length":32},{"start":9337,"length":32},{"start":9421,"length":32},{"start":9510,"length":32},{"start":9597,"length":32},{"start":13184,"length":32}],"9260":[{"start":1897,"length":32},{"start":7263,"length":32},{"start":9370,"length":32},{"start":9454,"length":32},{"start":9546,"length":32},{"start":9633,"length":32},{"start":13151,"length":32}],"9264":[{"start":2708,"length":32},{"start":3166,"length":32},{"start":3427,"length":32},{"start":10178,"length":32},{"start":10341,"length":32},{"start":12391,"length":32},{"start":12617,"length":32},{"start":12981,"length":32},{"start":14884,"length":32}],"9268":[{"start":1065,"length":32},{"start":1251,"length":32},{"start":3471,"length":32}],"9271":[{"start":3602,"length":32},{"start":17715,"length":32},{"start":17971,"length":32},{"start":18116,"length":32}],"9274":[{"start":1525,"length":32},{"start":3641,"length":32}],"9277":[{"start":2365,"length":32},{"start":3684,"length":32}],"9280":[{"start":1943,"length":32},{"start":3727,"length":32}],"9283":[{"start":2134,"length":32},{"start":2234,"length":32},{"start":3766,"length":32}],"9286":[{"start":3807,"length":32},{"start":11484,"length":32},{"start":14371,"length":32}],"9289":[{"start":3847,"length":32},{"start":10932,"length":32}],"9291":[{"start":3885,"length":32},{"start":6406,"length":32}],"9293":[{"start":3924,"length":32},{"start":10980,"length":32}],"9295":[{"start":3963,"length":32},{"start":6454,"length":32}],"9297":[{"start":4002,"length":32},{"start":10638,"length":32},{"start":12349,"length":32}],"9299":[{"start":4041,"length":32},{"start":10693,"length":32},{"start":12575,"length":32}],"9301":[{"start":4080,"length":32},{"start":4713,"length":32},{"start":4890,"length":32},{"start":15802,"length":32},{"start":15907,"length":32},{"start":16080,"length":32}]}}}}}}},"signatures":{"function":[{"signature":"borrowPerfect(uint256,uint256,uint256,address)","signatureHash4":"0xe27203cd","signatureHash32":"0xe27203cdafb01e58dc1c6bf477cf1550e8b1a4f248552fff94345a366a766354"},{"signature":"borrow(uint256,uint256,uint256,address)","signatureHash4":"0x242011d5","signatureHash32":"0x242011d52fd7d4cb226afacc9ee864c5393d964c88e8c8659ef374d53c33d41c"},{"signature":"constantsView()","signatureHash4":"0xb7791bf2","signatureHash32":"0xb7791bf23cc665f13abd231aa948ad1cea19ae8e48abcac88eb2cfac0dc63c39"},{"signature":"constantsView2()","signatureHash4":"0x1595cbd3","signatureHash32":"0x1595cbd3cc32597aab468af1d7cf3809739fd568b750cbaaf5f8a5ee22057a59"},{"signature":"depositPerfect(uint256,uint256,uint256,bool)","signatureHash4":"0x4d9036de","signatureHash32":"0x4d9036de7296813879b80cb45afd5c1d8cd3eccad583cfa860b6abd955d2ca7b"},{"signature":"deposit(uint256,uint256,uint256,bool)","signatureHash4":"0xe980e1eb","signatureHash32":"0xe980e1ebef31343494e765a24ae0d87278dcb55229c523d4db6370cf5911e3f7"},{"signature":"DEX_ID()","signatureHash4":"0xf4b9a3fb","signatureHash32":"0xf4b9a3fb905bf0fe512ae06ac9cbd1c280edc455fd62caca5e33b55ac49f90e3"},{"signature":"getCollateralReserves(uint256,uint256,uint256,uint256,uint256)","signatureHash4":"0x6560abaa","signatureHash32":"0x6560abaa47f4921d3318df13d70c707cb5421f6ec8f41afd3a416dd95a0588ec"},{"signature":"getDebtReserves(uint256,uint256,uint256,uint256,uint256)","signatureHash4":"0x05d455a9","signatureHash32":"0x05d455a9f9ae0a984ef58e82d398ed12bdca753042fe17762e0b67ceca921e7e"},{"signature":"getPricesAndExchangePrices()","signatureHash4":"0x916cef4e","signatureHash32":"0x916cef4ec34a2977906529eae6dc007321bf9cdf389e2805617aac32ed118ff6"},{"signature":"liquidityCallback(address,uint256,bytes)","signatureHash4":"0xad207501","signatureHash32":"0xad207501ecf54a54feb1d6a8b828df14f4a57097e61a0fe37af8e0b2ac1215fc"},{"signature":"oraclePrice(uint256[])","signatureHash4":"0xd811b2ce","signatureHash32":"0xd811b2cedf7531ef752db158938d53134cac3acb6c15c7026ff845ba6cffa674"},{"signature":"paybackPerfectInOneToken(uint256,uint256,uint256,bool)","signatureHash4":"0x30acd6fd","signatureHash32":"0x30acd6fd101ba8134e5a83f1992a1287476ae3ac6d41c0b90bd8fc65102ea651"},{"signature":"paybackPerfect(uint256,uint256,uint256,bool)","signatureHash4":"0x5b3d38d7","signatureHash32":"0x5b3d38d7f73a0f3e0bad14f435b99218d5efc0f263c8dc4196e20a69c0bf9856"},{"signature":"payback(uint256,uint256,uint256,bool)","signatureHash4":"0x68766981","signatureHash32":"0x68766981ab45c4e6a3b58dc76cfd31717257baa2b8e4703a59357d3b6d16c06e"},{"signature":"readFromStorage(bytes32)","signatureHash4":"0xb5c736e4","signatureHash32":"0xb5c736e4b75365911fe27b3300139e6dc4188bed4564c8c6be46f70877b40aeb"},{"signature":"swapIn(bool,uint256,uint256,address)","signatureHash4":"0x2668dfaa","signatureHash32":"0x2668dfaab9be4a2db3428c213724e6d8e3d42a8c2b0314fd3a44844eb835e04c"},{"signature":"swapInWithCallback(bool,uint256,uint256,address)","signatureHash4":"0xbe17c79c","signatureHash32":"0xbe17c79c6c21aaee014c980d611989f240b1a1bca8d561eb7474e2081e5ab2d8"},{"signature":"swapOut(bool,uint256,uint256,address)","signatureHash4":"0x286f0e61","signatureHash32":"0x286f0e610ae8a472331a62329d325b17072097a6e9bddc9227871dce06de9bc2"},{"signature":"swapOutWithCallback(bool,uint256,uint256,address)","signatureHash4":"0x653295aa","signatureHash32":"0x653295aa19f2f7e4aa9ec9778caf76684477f180912c9cc6c2260117a640af06"},{"signature":"withdrawPerfectInOneToken(uint256,uint256,uint256,address)","signatureHash4":"0x4c89bfd4","signatureHash32":"0x4c89bfd4e8b7008360e5c3518d2f8ebed91914cad52c4a7a6537e33fee0b1ba0"},{"signature":"withdrawPerfect(uint256,uint256,uint256,address)","signatureHash4":"0x35f0df98","signatureHash32":"0x35f0df984811079a128c9235d8f2f1ae460d734ebd7a723b005f5a0a760825bd"},{"signature":"withdraw(uint256,uint256,uint256,address)","signatureHash4":"0xd331bef7","signatureHash32":"0xd331bef70ced690bc675dc7f13d09dced2c9f64d01d42d188b1e1a20727fc448"}],"event":[{"signature":"LogArbitrage(int256,uint256)","signatureHash4":"0x063def03","signatureHash32":"0x063def03d41a2957d43156b97c271f3e4adea600722defb2cf6ebf9a27650056"},{"signature":"LogBorrowDebtLiquidity(uint256,uint256,uint256)","signatureHash4":"0x7f81427b","signatureHash32":"0x7f81427bed699dc7e687c5ddae6061932938818f79fc0e68903d55ef75ca4561"},{"signature":"LogBorrowPerfectDebtLiquidity(uint256,uint256,uint256)","signatureHash4":"0x486d9919","signatureHash32":"0x486d991947a88580130ff5acd9ec54dc37fb8da4bf6ab78871d5cd6fa5816df7"},{"signature":"LogDepositColLiquidity(uint256,uint256,uint256)","signatureHash4":"0xbfea9209","signatureHash32":"0xbfea92097a2487d6a5ccf7b7adc36b6002238f3106568ba4359770f4b67365a4"},{"signature":"LogDepositPerfectColLiquidity(uint256,uint256,uint256)","signatureHash4":"0x255672ef","signatureHash32":"0x255672effa3d8ba46e409fc964ae332b84d3107ba3a5096b22734606519528a3"},{"signature":"LogPaybackDebtInOneToken(uint256,uint256,uint256)","signatureHash4":"0x97dfa84c","signatureHash32":"0x97dfa84cbffcf65b8d034f057439472bc93868a66cc0e728c2faffb00f8b4923"},{"signature":"LogPaybackDebtLiquidity(uint256,uint256,uint256)","signatureHash4":"0xb69f152a","signatureHash32":"0xb69f152a70520703fe7ab4872a0cb3928386b68cf3c6c83c5d1fc08d196991e8"},{"signature":"LogPaybackPerfectDebtLiquidity(uint256,uint256,uint256)","signatureHash4":"0x03b77b44","signatureHash32":"0x03b77b44c2fe8816d55a2e4f90a87538c48d4148e35224c07049fd2304fa3a30"},{"signature":"LogWithdrawColInOneToken(uint256,uint256,uint256)","signatureHash4":"0xc98f3791","signatureHash32":"0xc98f37914e06db36c18654484db85c4bb864575a1b9f8181133ff33dea2d34f3"},{"signature":"LogWithdrawColLiquidity(uint256,uint256,uint256)","signatureHash4":"0xb61c7f3b","signatureHash32":"0xb61c7f3b23fe9335cc6c6a6e7036457758470877e61a19a5b4924e1ff8289624"},{"signature":"LogWithdrawPerfectColLiquidity(uint256,uint256,uint256)","signatureHash4":"0x6f837572","signatureHash32":"0x6f837572c1ef6e010a841ff938d593ec054984fefe29df2a0634bbf01f4db35b"},{"signature":"Swap(bool,uint256,uint256,address)","signatureHash4":"0xdc004dbc","signatureHash32":"0xdc004dbca4ef9c966218431ee5d9133d337ad018dd5b5c5493722803f75c64f7"}],"error":[{"signature":"FluidDexError(uint256)","signatureHash4":"0x2fee3e0e","signatureHash32":"0x2fee3e0e24e979d36a151494e9412e73d52d8ebae00fcd431f9167a02e769b43"},{"signature":"FluidDexFactoryError(uint256)","signatureHash4":"0xaeae7c0d","signatureHash32":"0xaeae7c0de3248f316f271258224deaf80328a55dbfefbe1e024eae999149dc0b"},{"signature":"FluidDexLiquidityOutput(uint256)","signatureHash4":"0xe8d35d06","signatureHash32":"0xe8d35d06bcdd0e442ff319756f1d416e590fafa9df95973b2f70dab7318a3b43"},{"signature":"FluidDexPerfectLiquidityOutput(uint256,uint256)","signatureHash4":"0x1458577f","signatureHash32":"0x1458577f4b4c71134a4f31c8e949453afd740e9fb78b66d49229b40b0da64420"},{"signature":"FluidDexPricesAndExchangeRates((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))","signatureHash4":"0x23bfdd3b","signatureHash32":"0x23bfdd3bf1da85d08182f26ee6561136f0c8446450d0c9088cff6944ac66d694"},{"signature":"FluidDexSingleTokenOutput(uint256)","signatureHash4":"0x73999506","signatureHash32":"0x7399950693951016d6281bf41a4f1e6d2a4b40cbb5f91c486ff1b54dc76df778"},{"signature":"FluidDexSwapResult(uint256)","signatureHash4":"0xb3bfda99","signatureHash32":"0xb3bfda990c22e642b53725a4e3f2e34c88a6ceb8841c8f855e0fe4dc88de4156"},{"signature":"FluidLiquidityCalcsError(uint256)","signatureHash4":"0xd50d7512","signatureHash32":"0xd50d7512c26f53bf625bbee5b18e0137c79aae5a0925f004d69a1e2a8074b51e"},{"signature":"FluidSafeTransferError(uint256)","signatureHash4":"0xdee51a8a","signatureHash32":"0xdee51a8acd5096311d21b87fbd26a1b49807278ee775e77cfdfd73d9f30c6bdd"}]},"proxyResolution":{"isProxy":false,"proxyType":null,"implementations":[]},"match":"exact_match","chainId":"42161","address":"0x0B1a513ee24972DAEf112bC777a5610d4325C9e7"}