diff --git a/addresses/addresses-999.json b/addresses/addresses-999.json index e0b2821..cb3cdf0 100644 --- a/addresses/addresses-999.json +++ b/addresses/addresses-999.json @@ -1,5 +1,5 @@ { "fulfillmentVaultAddress": "0x8Bc1F48Ce0D241BB2B7EC05AF202B7dA9aaBd1d9", "rolloverVaultAddress": "0x5e4A85D1BaD334A2Fdd07856201136bC6eE2e302", - "routerAddress": "0x58B6943Ed3a48981eA58c0918830eFd4febbe5a1" + "routerAddress": "0x2A868EFd3cdF2bE83Ff63dECdfdc07A8dCAda316" } \ No newline at end of file diff --git a/broadcast/DeployRouter.s.sol/999/run-1766194143046.json b/broadcast/DeployRouter.s.sol/999/run-1766194143046.json new file mode 100644 index 0000000..034ad21 --- /dev/null +++ b/broadcast/DeployRouter.s.sol/999/run-1766194143046.json @@ -0,0 +1,253 @@ +{ + "transactions": [ + { + "hash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionType": "CREATE", + "contractName": "Router", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "function": null, + "arguments": [ + "0x5555555555555555555555555555555555555555", + "0xDF8023679fE964982bDb93956f96B01c25f33Da5", + "0x5e4A85D1BaD334A2Fdd07856201136bC6eE2e302", + "0x8Bc1F48Ce0D241BB2B7EC05AF202B7dA9aaBd1d9", + "0xe9d69CdD6Fe41e7B621B4A688C5D1a68cB5c8ADc" + ], + "transaction": { + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "gas": "0x49fa97", + "value": "0x0", + "input": "0x610180604052348015610010575f5ffd5b506040516146a83803806146a883398101604081905261002f916103b6565b6001600160a01b0380861661010052848116608081905284821660a05283821660c05290821660e0526040805163311176d760e01b8152905163311176d7916004808201926020929091908290030181865afa158015610091573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100b59190610417565b6001600160a01b0316610120816001600160a01b031681525050836001600160a01b031663eb91d0f56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012f9190610417565b6001600160a01b0316610140816001600160a01b031681525050836001600160a01b03166331d31efb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a99190610417565b6001600160a01b03908116610160526101005160805160405163095ea7b360e01b815290831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af1158015610203573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102279190610437565b50610120516101405160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561027c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a09190610437565b506101405160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af11580156102f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103189190610437565b506101205160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561036c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190610437565b505050505050610456565b80516001600160a01b03811681146103b1575f5ffd5b919050565b5f5f5f5f5f60a086880312156103ca575f5ffd5b6103d38661039b565b94506103e16020870161039b565b93506103ef6040870161039b565b92506103fd6060870161039b565b915061040b6080870161039b565b90509295509295909350565b5f60208284031215610427575f5ffd5b6104308261039b565b9392505050565b5f60208284031215610447575f5ffd5b81518015158114610430575f5ffd5b60805160a05160c05160e051610100516101205161014051610160516140616106475f395f818161029401528181612e4c01528181612ef80152612f9601525f8181610468015281816108a20152818161099601528181610aa301528181610b4001528181610bb201528181610beb01528181610e44015281816112260152818161135e01528181611db601528181611fb4015281816120a8015281816124eb01528181612527015281816125b8015261268e01525f818161026101528181610b0201528181610c1a01528181610c3f01528181610cea01528181610d6001528181610dce01528181611156015281816111cc0152818161128b0152818161132c01528181611834015281816118b0015281816121650152818161223f015281816125870152818161265f0152818161289701528181612907015281816129a201528181612caa01528181612d370152612dec01525f81816101c801528181612be50152612c2001525f818161049b01528181611702015261179101525f81816103c401526110ed01525f81816102fa01526122e601525f8181610391015281816108d60152818161103d01528181611557015281816115e701528181611ab501528181611bbe01528181611c7301528181611e9c01528181611fe80152818161234a015261244201526140615ff3fe608060405260043610610165575f3560e01c80637aea9eab116100c6578063b500cf771161007c578063ea81deb411610057578063ea81deb414610438578063eb91d0f514610457578063f98d06f01461048a575f5ffd5b8063b500cf77146103e6578063ca38e8cc14610405578063e2230a4214610424575f5ffd5b806389d7f33c116100ac57806389d7f33c1461036157806396ebfb89146103805780639a76c764146103b3575f5ffd5b80637aea9eab1461033b57806381f139f41461034e575f5ffd5b806331d31efb1161011b5780633e7e6927116101015780633e7e6927146102ca57806343d2c350146102e9578063623556381461031c575f5ffd5b806331d31efb1461028357806339b90b99146102b6575f5ffd5b806321679a2e1161014b57806321679a2e14610202578063248391ff14610223578063311176d714610250575f5ffd5b806307ecbf3c1461017057806317fcb39b146101b7575f5ffd5b3661016c57005b5f5ffd5b34801561017b575f5ffd5b5061018f61018a3660046132b8565b6104bd565b6040805194855260208501939093529183015260ff1660608201526080015b60405180910390f35b3480156101c2575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ae565b34801561020d575f5ffd5b5061022161021c366004613314565b61089b565b005b34801561022e575f5ffd5b5061024261023d366004613346565b610a80565b6040519081526020016101ae565b34801561025b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b34801561028e575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c1575f5ffd5b50610221610e41565b3480156102d5575f5ffd5b506102216102e4366004613384565b6110e8565b3480156102f4575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610327575f5ffd5b50610221610336366004613346565b611113565b61018f6103493660046133c6565b611451565b61018f61035c36600461342c565b6116fb565b34801561036c575f5ffd5b5061022161037b3660046134f0565b61182d565b34801561038b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103be575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f1575f5ffd5b50610221610400366004613522565b611ab2565b348015610410575f5ffd5b5061022161041f366004613314565b611fad565b34801561042f575f5ffd5b50610221612162565b348015610443575f5ffd5b50610221610452366004613384565b6122e1565b348015610462575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610495575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b5f8080806104cb8580613561565b6104dc90608081019060600161359d565b1561072d575f5b6104ed8680613561565b6104fb9060408101906135b8565b90508110156107275761050e8680613561565b61051c9060408101906135b8565b8281811061052c5761052c613623565b90506020020160208101906105419190613650565b6001600160a01b031663c6866922600261055b8980613561565b61056590806135b8565b8581811061057557610575613623565b9050602002013560016105889190613698565b61059291906136d8565b6040518263ffffffff1660e01b81526004016105b091815260200190565b602060405180830381865afa1580156105cb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ef91906136eb565b6105f99086613698565b94505f8061064c61061060608a0160408b01613650565b600261061c8b80613561565b61062690806135b8565b8781811061063657610636613623565b9050602002013561064791906136d8565b61230c565b9450915083905061065d8880613561565b61066b9060408101906135b8565b8481811061067b5761067b613623565b90506020020160208101906106909190613650565b6001600160a01b031663c6866922836040518263ffffffff1660e01b81526004016106bd91815260200190565b602060405180830381865afa1580156106d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fc91906136eb565b610707836002613702565b6107119190613719565b61071b9086613698565b945050506001016104e3565b50610894565b5f5b6107398680613561565b6107479060408101906135b8565b9050811015610892575f8061079561076560608a0160408b01613650565b61076f8a80613561565b61077990806135b8565b8681811061078957610789613623565b9050602002013561230c565b90925090506107a48286613698565b94509250826107b38880613561565b6107c19060408101906135b8565b848181106107d1576107d1613623565b90506020020160208101906107e69190613650565b6001600160a01b031663c68669226107ff6002856136d8565b6040518263ffffffff1660e01b815260040161081d91815260200190565b602060405180830381865afa158015610838573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085c91906136eb565b6108669087613698565b955061087360028361372c565b60010361088857610885600187613698565b95505b505060010161072f565b505b9193509193565b5f6108c7847f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506108d384826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610930573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610954919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156109de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a029190613770565b506040517ff9b1a9ad00000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0382169063f9b1a9ad906044015b5f604051808303815f87803b158015610a63575f5ffd5b505af1158015610a75573d5f5f3e3d5ffd5b505050505050505050565b5f826001600160a01b0316846001600160a01b031603610aa1575080610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610bb0576040517f4af218260000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03818116600484015260248301859052610ba99286917f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401602060405180830381865afa158015610b85573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023d91906136eb565b9050610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610ce8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396846de07f0000000000000000000000000000000000000000000000000000000000000000610c64877f000000000000000000000000000000000000000000000000000000000000000087610a80565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044015b602060405180830381865afa158015610cc4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906136eb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610d8f576040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018490527f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401610ca9565b6040517f96846de00000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906396846de090604401602060405180830381865afa158015610e13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3791906136eb565b90505b9392505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e9d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ec49190810190613813565b90505f5b81518110156110e457818181518110610ee357610ee3613623565b60209081029190910101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80294d930000000000000000000000000000000000000000000000000000000060048201526001600160a01b03909116906301ffc9a790602401602060405180830381865afa158015610f6a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190613770565b156110dc575f828281518110610fa657610fa6613623565b60200260200101516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100d919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529192509082169063095ea7b3906044016020604051808303815f875af11580156110b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110d99190613770565b50505b600101610ec8565b5050565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b816001600160a01b0316836001600160a01b03160361113157505050565b805f0361113d57505050565b611154335b6001600160a01b038516903084612b28565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611224576040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015f604051808303815f87803b15801561120d575f5ffd5b505af115801561121f573d5f5f3e3d5ffd5b505050505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036113b8576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156112d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112fc91906136eb565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906347e7ef24906044015f604051808303815f87803b1580156113a1575f5ffd5b505af11580156113b3573d5f5f3e3d5ffd5b505050505b61144c336040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015611417573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061143b91906136eb565b6001600160a01b0385169190612baa565b505050565b5f5f5f5f61145e876104bd565b9296509094509250905083156114f157848411156114d7576114866060880160408901613650565b6040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260248101859052604481018690526064015b60405180910390fd5b6114f16114ea6060890160408a01613650565b8588612bdb565b8215611554578483111561154a576040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b038916600482015260248101849052604481018690526064016114ce565b6115548884612ca8565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639cf42ffa478a6040518363ffffffff1660e01b81526004016115a29190613aaf565b60206040518083038185885af11580156115be573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906115e391906136eb565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611641573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611665919061374a565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018490526064015f604051808303815f87803b1580156116d9575f5ffd5b505af11580156116eb573d5f5f3e3d5ffd5b5050505050945094509450949050565b5f5f5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d47eed458c8c6040518363ffffffff1660e01b815260040161174e929190613ba1565b602060405180830381865afa158015611769573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178d91906136eb565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ef9e5e28828d8d6040518463ffffffff1660e01b81526004016117de929190613ba1565b5f604051808303818588803b1580156117f5575f5ffd5b505af1158015611807573d5f5f3e3d5ffd5b505050505061181889898989611451565b929e919d509b50909950975050505050505050565b5f611859837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90505f61186585612e1b565b90506118718483612ca8565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156118f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061191a9190613770565b506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b0382169063b6b55f25906024016020604051808303815f875af1158015611978573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199c91906136eb565b506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015611a02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a2691906136eb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611a86573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aaa9190613770565b505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b0f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b33919061374a565b6040517f581a7ab0000000000000000000000000000000000000000000000000000000008152600481018590529091505f906001600160a01b0383169063581a7ab0906024016102c060405180830381865afa158015611b95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bb99190613c61565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e78bede836040518263ffffffff1660e01b8152600401611c089190613e20565b602060405180830381865afa158015611c23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c479190613fa8565b61ffff1690505f611c65611c5a8461300f565b836127106001613066565b9050611c7187826124e9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ccd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf1919061374a565b6001600160a01b03166323b872dd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152306024820152604481018990526064015f604051808303815f87803b158015611d63575f5ffd5b505af1158015611d75573d5f5f3e3d5ffd5b50506040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018590527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303815f875af1158015611dfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e229190613770565b506040517f8fb702200000000000000000000000000000000000000000000000000000000081526004810187905260ff861660248201526001600160a01b03851690638fb70220906044015f604051808303815f87803b158015611e84575f5ffd5b505af1158015611e96573d5f5f3e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f1a919061374a565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018990526064015f604051808303815f87803b158015611f8e575f5ffd5b505af1158015611fa0573d5f5f3e3d5ffd5b5050505050505050505050565b5f611fd9847f000000000000000000000000000000000000000000000000000000000000000084610a80565b9050611fe584826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612042573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612066919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156120f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121149190613770565b506040517f40b369c100000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b038216906340b369c190604401610a4c565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa1580156121be573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e59190810190613813565b90505f5b81518110156110e45781818151811061220457612204613623565b60209081029190910101516040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529091169063095ea7b3906044016020604051808303815f875af11580156122b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d89190613770565b506001016121e9565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b6040517f013745180000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301525f91829182917f000000000000000000000000000000000000000000000000000000000000000090911690630137451890602401602060405180830381865afa158015612391573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123b5919061374a565b6040517f9097548d000000000000000000000000000000000000000000000000000000008152600481018690529091506001600160a01b03821690639097548d906024016040805180830381865afa158015612413573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124379190613fc1565b80935081945050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f43bde6d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561249c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c09190613fa8565b90506124de846124d283612710613ff0565b61ffff166127106130b1565b935050509250929050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612557576110e47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316333084612b28565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa1580156125ff573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262391906136eb565b905061262f8382612ca8565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015b5f604051808303815f87803b1580156126d0575f5ffd5b505af11580156126e2573d5f5f3e3d5ffd5b50505050505050565b826001600160a01b03166389f91ece6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612727573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061274b9190613770565b80156128485750826001600160a01b03166391d14854846001600160a01b0316637a997ab76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561279d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127c191906136eb565b336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612822573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128469190613770565b155b15612890576040517f876027c70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201523360248201526044016114ce565b5f6128bc837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506128c88382612ca8565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af115801561294d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129719190613770565b506040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390528516906347e7ef24906044015f604051808303815f87803b1580156129f2575f5ffd5b505af1158015612a04573d5f5f3e3d5ffd5b50505050836001600160a01b031663a9059cbb612a1e3390565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015612a79573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a9d91906136eb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015612afd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b219190613770565b5050505050565b6040516001600160a01b038481166024830152838116604483015260648201839052612ba49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613161565b50505050565b6040516001600160a01b0383811660248301526044820183905261144c91859182169063a9059cbb90606401612b5d565b808015612c1957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b15612c93577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004015f604051808303818588803b158015612c77575f5ffd5b505af1158015612c89573d5f5f3e3d5ffd5b5050505050505050565b61144c6001600160a01b038416333085612b28565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612cf6576110e46001600160a01b038316333084612b28565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa158015612d7e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da291906136eb565b9050612dad33611142565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044016126b9565b6040517f7fe9a7e6000000000000000000000000000000000000000000000000000000008152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637fe9a7e690602401602060405180830381865afa158015612e99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ebd919061374a565b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c3c5a54790602401602060405180830381865afa158015612f3f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f639190613770565b61300a576040517f22fa95c4000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906322fa95c4906024016020604051808303815f875af1158015612fe4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613008919061374a565b505b919050565b5f613030826101c00151836101a001516130299190613698565b83906131e6565b826101800151836101e0015184610160015161304c9190613719565b6130569190613719565b6130609190613719565b92915050565b5f61309361307383613230565b801561308e57505f8480613089576130896136ab565b868809115b151590565b61309e8686866130b1565b6130a89190613698565b95945050505050565b5f5f5f6130be868661325c565b91509150815f036130e2578381816130d8576130d86136ab565b0492505050610e3a565b8184116130f9576130f96003851502601118613297565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f5f60205f8451602086015f885af180613180576040513d5f823e3d81fd5b50505f513d915081156131975780600114156131a4565b6001600160a01b0384163b155b15612ba4576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016114ce565b5f8261014001515f036131fa57505f613060565b610e3a82846101800151856101e0015186610160015161321a9190613719565b6132249190613719565b8561014001515f613066565b5f600282600381111561324557613245613dba565b61324f919061400a565b60ff166001149050919050565b5f807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f60c08284031215613008575f5ffd5b5f602082840312156132c8575f5ffd5b813567ffffffffffffffff8111156132de575f5ffd5b6132ea848285016132a8565b949350505050565b6001600160a01b0381168114613306575f5ffd5b50565b803561300a816132f2565b5f5f5f60608486031215613326575f5ffd5b8335613331816132f2565b95602085013595506040909401359392505050565b5f5f5f60608486031215613358575f5ffd5b8335613363816132f2565b92506020840135613373816132f2565b929592945050506040919091013590565b5f5f60408385031215613395575f5ffd5b82356133a0816132f2565b946020939093013593505050565b8015158114613306575f5ffd5b803561300a816133ae565b5f5f5f5f608085870312156133d9575f5ffd5b84356133e4816132f2565b9350602085013567ffffffffffffffff8111156133ff575f5ffd5b61340b878288016132a8565b935050604085013561341c816133ae565b9396929550929360600135925050565b5f5f5f5f5f5f60a08789031215613441575f5ffd5b863567ffffffffffffffff811115613457575f5ffd5b8701601f81018913613467575f5ffd5b803567ffffffffffffffff81111561347d575f5ffd5b8960208260051b8401011115613491575f5ffd5b6020918201975095506134a5908801613309565b9350604087013567ffffffffffffffff8111156134c0575f5ffd5b6134cc89828a016132a8565b9350506134db606088016133bb565b95989497509295919493608090920135925050565b5f5f5f60608486031215613502575f5ffd5b833592506020840135613373816132f2565b60ff81168114613306575f5ffd5b5f5f5f60608486031215613534575f5ffd5b833561353f816132f2565b925060208401359150604084013561355681613514565b809150509250925092565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112613593575f5ffd5b9190910192915050565b5f602082840312156135ad575f5ffd5b8135610e3a816133ae565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126135eb575f5ffd5b83018035915067ffffffffffffffff821115613605575f5ffd5b6020019150600581901b360382131561361c575f5ffd5b9250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215613660575f5ffd5b8135610e3a816132f2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156130605761306061366b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826136e6576136e66136ab565b500490565b5f602082840312156136fb575f5ffd5b5051919050565b80820281158282048414176130605761306061366b565b818103818111156130605761306061366b565b5f8261373a5761373a6136ab565b500690565b805161300a816132f2565b5f6020828403121561375a575f5ffd5b8151610e3a816132f2565b805161300a816133ae565b5f60208284031215613780575f5ffd5b8151610e3a816133ae565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516102c0810167ffffffffffffffff811182821017156137dc576137dc61378b565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561380b5761380b61378b565b604052919050565b5f60208284031215613823575f5ffd5b815167ffffffffffffffff811115613839575f5ffd5b8201601f81018413613849575f5ffd5b805167ffffffffffffffff8111156138635761386361378b565b8060051b613873602082016137e2565b9182526020818401810192908101908784111561388e575f5ffd5b6020850194505b838510156138bc57845192506138aa836132f2565b82825260209485019490910190613895565b979650505050505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126138fa575f5ffd5b830160208101925035905067ffffffffffffffff811115613919575f5ffd5b8060051b360382131561361c575f5ffd5b8183526020830192505f815f5b8481101561396857813561394a816132f2565b6001600160a01b031686526020958601959190910190600101613937565b5093949350505050565b5f61397d82836138c7565b60a085528060a08601527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139b3575f5ffd5b60051b808260c08701378401905060208301356139cf81613514565b60ff1660208501526139e460408401846138c7565b60c08684030160408701526139fd60c08401828461392a565b92505050613a0d606084016133bb565b1515606085015260809283013592909301919091525090565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613a59575f5ffd5b830160208101925035905067ffffffffffffffff811115613a78575f5ffd5b80360382131561361c575f5ffd5b81835281816020850137505f602082840101525f6020601f19601f840116840101905092915050565b602081525f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61843603018112613ae5575f5ffd5b60c06020840152613afb60e08401858301613972565b9050613b0a6020850185613a26565b601f19858403016040860152613b21838284613a86565b92505050613b3160408501613309565b6001600160a01b038116606085015250613b4d60608501613309565b6001600160a01b038116608085015250613b6a60808501856138c7565b601f198584030160a0860152613b8183828461392a565b92505050613b9160a085016133bb565b80151560c0850152509392505050565b602080825281018290525f6040600584901b8301810190830185835b86811015613c18577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0868503018352613bf68289613a26565b613c01868284613a86565b955050506020928301929190910190600101613bbd565b50919695505050505050565b805161300a81613514565b805161ffff8116811461300a575f5ffd5b805163ffffffff8116811461300a575f5ffd5b80516003811061300a575f5ffd5b5f6102c0828403128015613c73575f5ffd5b50613c7c6137b8565b82518152613c8c6020840161373f565b6020820152613c9d60408401613c24565b60408201526060838101519082015260808084015190820152613cc260a0840161373f565b60a0820152613cd360c08401613c2f565b60c0820152613ce460e08401613c2f565b60e0820152613cf66101008401613c40565b610100820152613d096101208401613c40565b6101208201526101408381015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e0808401519082015261020080840151908201526102208084015190820152613d746102408401613c24565b610240820152613d876102608401613c24565b610260820152613d9a6102808401613765565b610280820152613dad6102a08401613c53565b6102a08201529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613e1c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b815181526020808301516102c0830191613e44908401826001600160a01b03169052565b506040830151613e59604084018260ff169052565b50606083015160608301526080830151608083015260a0830151613e8860a08401826001600160a01b03169052565b5060c0830151613e9e60c084018261ffff169052565b5060e0830151613eb460e084018261ffff169052565b50610100830151613ece61010084018263ffffffff169052565b50610120830151613ee861012084018263ffffffff169052565b506101408301516101408301526101608301516101608301526101808301516101808301526101a08301516101a08301526101c08301516101c08301526101e08301516101e0830152610200830151610200830152610220830151610220830152610240830151613f5f61024084018260ff169052565b50610260830151613f7661026084018260ff169052565b50610280830151613f8c61028084018215159052565b506102a0830151613fa16102a0840182613de7565b5092915050565b5f60208284031215613fb8575f5ffd5b610e3a82613c2f565b5f5f60408385031215613fd2575f5ffd5b82516020840151909250613fe581613514565b809150509250929050565b61ffff81811683821601908111156130605761306061366b565b5f60ff83168061401c5761401c6136ab565b8060ff8416069150509291505056fea264697066735822122022abdc8ba0aebea94b7a374b6e826fcb20c25c7c6b8182b86058e7dd0318f62964736f6c634300081e00330000000000000000000000005555555555555555555555555555555555555555000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da50000000000000000000000005e4a85d1bad334a2fdd07856201136bc6ee2e3020000000000000000000000008bc1f48ce0d241bb2b7ec05af202b7da9aabd1d9000000000000000000000000e9d69cdd6fe41e7b621b4a688c5d1a68cb5c8adc", + "nonce": "0x13c", + "chainId": "0x3e7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", + "transactionType": "CALL", + "contractName": "Router", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "function": "approveCollaterals()", + "arguments": [], + "transaction": { + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "gas": "0x13422", + "value": "0x0", + "input": "0x39b90b99", + "nonce": "0x13d", + "chainId": "0x3e7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionType": "CALL", + "contractName": "Router", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "function": "approveUsdTokens()", + "arguments": [], + "transaction": { + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "gas": "0x31824", + "value": "0x0", + "input": "0xe2230a42", + "nonce": "0x13e", + "chainId": "0x3e7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x53131a", + "logs": [ + { + "address": "0x5555555555555555555555555555555555555555", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x12", + "removed": false + }, + { + "address": "0x22632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x00000000000000000000000088e35cd2cc5845780058e997cbd3fd92e3345864" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x13", + "removed": false + }, + { + "address": "0x88e35cd2cc5845780058e997cbd3fd92e3345864", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x14", + "removed": false + }, + { + "address": "0x22632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x15", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000400000000000000001000000000000020000000000000000000000000020000000000000000000000000000200000000000000000020002000000000000000000000000000000000000000040000000010000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020200000000000000000000008001000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010002000080000000000000082000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "gasUsed": "0x38e826", + "effectiveGasPrice": "0x202190e5", + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "to": null, + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x53e5cb", + "logs": [ + { + "address": "0x5555555555555555555555555555555555555555", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", + "transactionIndex": "0x3", + "logIndex": "0x16", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000002000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000080000000000000082000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", + "transactionIndex": "0x3", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "gasUsed": "0xd2b1", + "effectiveGasPrice": "0x202190e5", + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "contractAddress": null + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x56036e", + "logs": [ + { + "address": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x17", + "removed": false + }, + { + "address": "0xb88339cb7199b77e23db6e890353e22632ba630f", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x18", + "removed": false + }, + { + "address": "0x111111a1a0667d36bd57c0a9f569b98057111111", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", + "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x19", + "removed": false + } + ], + "logsBloom": "0x00000080400000000000400000000000000400000000000000000000000000000000000000000000000004000000000000000000080000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000400000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000200000000000200010000000000000000000000080000000000000000000081000000000000000", + "type": "0x2", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "gasUsed": "0x21da3", + "effectiveGasPrice": "0x202190e5", + "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", + "contractAddress": null + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1766194143046, + "chain": 999, + "commit": "43573b1" +} \ No newline at end of file diff --git a/broadcast/DeployRouter.s.sol/999/run-latest.json b/broadcast/DeployRouter.s.sol/999/run-latest.json index 33e9da7..034ad21 100644 --- a/broadcast/DeployRouter.s.sol/999/run-latest.json +++ b/broadcast/DeployRouter.s.sol/999/run-latest.json @@ -1,10 +1,10 @@ { "transactions": [ { - "hash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", + "hash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", "transactionType": "CREATE", "contractName": "Router", - "contractAddress": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "function": null, "arguments": [ "0x5555555555555555555555555555555555555555", @@ -15,48 +15,48 @@ ], "transaction": { "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", - "gas": "0x48222a", + "gas": "0x49fa97", "value": "0x0", - "input": "0x610180604052348015610010575f5ffd5b506040516144f73803806144f783398101604081905261002f916103b6565b6001600160a01b0380861661010052848116608081905284821660a05283821660c05290821660e0526040805163311176d760e01b8152905163311176d7916004808201926020929091908290030181865afa158015610091573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100b59190610417565b6001600160a01b0316610120816001600160a01b031681525050836001600160a01b031663eb91d0f56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012f9190610417565b6001600160a01b0316610140816001600160a01b031681525050836001600160a01b03166331d31efb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a99190610417565b6001600160a01b03908116610160526101005160805160405163095ea7b360e01b815290831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af1158015610203573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102279190610437565b50610120516101405160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561027c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a09190610437565b506101405160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af11580156102f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103189190610437565b506101205160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561036c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190610437565b505050505050610456565b80516001600160a01b03811681146103b1575f5ffd5b919050565b5f5f5f5f5f60a086880312156103ca575f5ffd5b6103d38661039b565b94506103e16020870161039b565b93506103ef6040870161039b565b92506103fd6060870161039b565b915061040b6080870161039b565b90509295509295909350565b5f60208284031215610427575f5ffd5b6104308261039b565b9392505050565b5f60208284031215610447575f5ffd5b81518015158114610430575f5ffd5b60805160a05160c05160e05161010051610120516101405161016051613eb06106475f395f818161029401528181612c9b01528181612d470152612de501525f8181610468015281816108a20152818161099601528181610aa301528181610b4001528181610bb201528181610beb01528181610e44015281816112260152818161135e01528181611db601528181611fb4015281816120a8015281816124eb01528181612527015281816125b8015261268e01525f818161026101528181610b0201528181610c1a01528181610c3f01528181610cea01528181610d6001528181610dce01528181611156015281816111cc0152818161128b0152818161132c01528181611834015281816118b0015281816121650152818161223f015281816125870152818161265f015281816126f201528181612762015281816127fd01528181612af901528181612b860152612c3b01525f81816101c801528181612a340152612a6f01525f818161049b01528181611702015261179101525f81816103c401526110ed01525f81816102fa01526122e601525f8181610391015281816108d60152818161103d01528181611557015281816115e701528181611ab501528181611bbe01528181611c7301528181611e9c01528181611fe80152818161234a01526124420152613eb05ff3fe608060405260043610610165575f3560e01c80637aea9eab116100c6578063b500cf771161007c578063ea81deb411610057578063ea81deb414610438578063eb91d0f514610457578063f98d06f01461048a575f5ffd5b8063b500cf77146103e6578063ca38e8cc14610405578063e2230a4214610424575f5ffd5b806389d7f33c116100ac57806389d7f33c1461036157806396ebfb89146103805780639a76c764146103b3575f5ffd5b80637aea9eab1461033b57806381f139f41461034e575f5ffd5b806331d31efb1161011b5780633e7e6927116101015780633e7e6927146102ca57806343d2c350146102e9578063623556381461031c575f5ffd5b806331d31efb1461028357806339b90b99146102b6575f5ffd5b806321679a2e1161014b57806321679a2e14610202578063248391ff14610223578063311176d714610250575f5ffd5b806307ecbf3c1461017057806317fcb39b146101b7575f5ffd5b3661016c57005b5f5ffd5b34801561017b575f5ffd5b5061018f61018a366004613107565b6104bd565b6040805194855260208501939093529183015260ff1660608201526080015b60405180910390f35b3480156101c2575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ae565b34801561020d575f5ffd5b5061022161021c366004613163565b61089b565b005b34801561022e575f5ffd5b5061024261023d366004613195565b610a80565b6040519081526020016101ae565b34801561025b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b34801561028e575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c1575f5ffd5b50610221610e41565b3480156102d5575f5ffd5b506102216102e43660046131d3565b6110e8565b3480156102f4575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610327575f5ffd5b50610221610336366004613195565b611113565b61018f610349366004613215565b611451565b61018f61035c36600461327b565b6116fb565b34801561036c575f5ffd5b5061022161037b36600461333f565b61182d565b34801561038b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103be575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f1575f5ffd5b50610221610400366004613371565b611ab2565b348015610410575f5ffd5b5061022161041f366004613163565b611fad565b34801561042f575f5ffd5b50610221612162565b348015610443575f5ffd5b506102216104523660046131d3565b6122e1565b348015610462575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610495575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b5f8080806104cb85806133b0565b6104dc9060808101906060016133ec565b1561072d575f5b6104ed86806133b0565b6104fb906040810190613407565b90508110156107275761050e86806133b0565b61051c906040810190613407565b8281811061052c5761052c613472565b9050602002016020810190610541919061349f565b6001600160a01b031663c6866922600261055b89806133b0565b6105659080613407565b8581811061057557610575613472565b90506020020135600161058891906134e7565b6105929190613527565b6040518263ffffffff1660e01b81526004016105b091815260200190565b602060405180830381865afa1580156105cb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ef919061353a565b6105f990866134e7565b94505f8061064c61061060608a0160408b0161349f565b600261061c8b806133b0565b6106269080613407565b8781811061063657610636613472565b905060200201356106479190613527565b61230c565b9450915083905061065d88806133b0565b61066b906040810190613407565b8481811061067b5761067b613472565b9050602002016020810190610690919061349f565b6001600160a01b031663c6866922836040518263ffffffff1660e01b81526004016106bd91815260200190565b602060405180830381865afa1580156106d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fc919061353a565b610707836002613551565b6107119190613568565b61071b90866134e7565b945050506001016104e3565b50610894565b5f5b61073986806133b0565b610747906040810190613407565b9050811015610892575f8061079561076560608a0160408b0161349f565b61076f8a806133b0565b6107799080613407565b8681811061078957610789613472565b9050602002013561230c565b90925090506107a482866134e7565b94509250826107b388806133b0565b6107c1906040810190613407565b848181106107d1576107d1613472565b90506020020160208101906107e6919061349f565b6001600160a01b031663c68669226107ff600285613527565b6040518263ffffffff1660e01b815260040161081d91815260200190565b602060405180830381865afa158015610838573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085c919061353a565b61086690876134e7565b955061087360028361357b565b600103610888576108856001876134e7565b95505b505060010161072f565b505b9193509193565b5f6108c7847f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506108d384826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610930573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109549190613599565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156109de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0291906135bf565b506040517ff9b1a9ad00000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0382169063f9b1a9ad906044015b5f604051808303815f87803b158015610a63575f5ffd5b505af1158015610a75573d5f5f3e3d5ffd5b505050505050505050565b5f826001600160a01b0316846001600160a01b031603610aa1575080610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610bb0576040517f4af218260000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03818116600484015260248301859052610ba99286917f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401602060405180830381865afa158015610b85573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023d919061353a565b9050610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610ce8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396846de07f0000000000000000000000000000000000000000000000000000000000000000610c64877f000000000000000000000000000000000000000000000000000000000000000087610a80565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044015b602060405180830381865afa158015610cc4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba9919061353a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610d8f576040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018490527f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401610ca9565b6040517f96846de00000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906396846de090604401602060405180830381865afa158015610e13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e37919061353a565b90505b9392505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e9d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ec49190810190613662565b90505f5b81518110156110e457818181518110610ee357610ee3613472565b60209081029190910101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80294d930000000000000000000000000000000000000000000000000000000060048201526001600160a01b03909116906301ffc9a790602401602060405180830381865afa158015610f6a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e91906135bf565b156110dc575f828281518110610fa657610fa6613472565b60200260200101516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100d9190613599565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529192509082169063095ea7b3906044016020604051808303815f875af11580156110b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110d991906135bf565b50505b600101610ec8565b5050565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b816001600160a01b0316836001600160a01b03160361113157505050565b805f0361113d57505050565b611154335b6001600160a01b038516903084612977565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611224576040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015f604051808303815f87803b15801561120d575f5ffd5b505af115801561121f573d5f5f3e3d5ffd5b505050505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036113b8576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156112d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112fc919061353a565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906347e7ef24906044015f604051808303815f87803b1580156113a1575f5ffd5b505af11580156113b3573d5f5f3e3d5ffd5b505050505b61144c336040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015611417573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061143b919061353a565b6001600160a01b03851691906129f9565b505050565b5f5f5f5f61145e876104bd565b9296509094509250905083156114f157848411156114d757611486606088016040890161349f565b6040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260248101859052604481018690526064015b60405180910390fd5b6114f16114ea6060890160408a0161349f565b8588612a2a565b8215611554578483111561154a576040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b038916600482015260248101849052604481018690526064016114ce565b6115548884612af7565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639cf42ffa478a6040518363ffffffff1660e01b81526004016115a291906138fe565b60206040518083038185885af11580156115be573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906115e3919061353a565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611641573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116659190613599565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018490526064015f604051808303815f87803b1580156116d9575f5ffd5b505af11580156116eb573d5f5f3e3d5ffd5b5050505050945094509450949050565b5f5f5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d47eed458c8c6040518363ffffffff1660e01b815260040161174e9291906139f0565b602060405180830381865afa158015611769573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178d919061353a565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ef9e5e28828d8d6040518463ffffffff1660e01b81526004016117de9291906139f0565b5f604051808303818588803b1580156117f5575f5ffd5b505af1158015611807573d5f5f3e3d5ffd5b505050505061181889898989611451565b929e919d509b50909950975050505050505050565b5f611859837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90505f61186585612c6a565b90506118718483612af7565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156118f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061191a91906135bf565b506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b0382169063b6b55f25906024016020604051808303815f875af1158015611978573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199c919061353a565b506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015611a02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a26919061353a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611a86573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aaa91906135bf565b505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b0f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b339190613599565b6040517f581a7ab0000000000000000000000000000000000000000000000000000000008152600481018590529091505f906001600160a01b0383169063581a7ab0906024016102c060405180830381865afa158015611b95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bb99190613ab0565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e78bede836040518263ffffffff1660e01b8152600401611c089190613c6f565b602060405180830381865afa158015611c23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c479190613df7565b61ffff1690505f611c65611c5a84612e5e565b836127106001612eb5565b9050611c7187826124e9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ccd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf19190613599565b6001600160a01b03166323b872dd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152306024820152604481018990526064015f604051808303815f87803b158015611d63575f5ffd5b505af1158015611d75573d5f5f3e3d5ffd5b50506040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018590527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303815f875af1158015611dfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e2291906135bf565b506040517f8fb702200000000000000000000000000000000000000000000000000000000081526004810187905260ff861660248201526001600160a01b03851690638fb70220906044015f604051808303815f87803b158015611e84575f5ffd5b505af1158015611e96573d5f5f3e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f1a9190613599565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018990526064015f604051808303815f87803b158015611f8e575f5ffd5b505af1158015611fa0573d5f5f3e3d5ffd5b5050505050505050505050565b5f611fd9847f000000000000000000000000000000000000000000000000000000000000000084610a80565b9050611fe584826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612042573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120669190613599565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156120f0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211491906135bf565b506040517f40b369c100000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b038216906340b369c190604401610a4c565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa1580156121be573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e59190810190613662565b90505f5b81518110156110e45781818151811061220457612204613472565b60209081029190910101516040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529091169063095ea7b3906044016020604051808303815f875af11580156122b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d891906135bf565b506001016121e9565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b6040517f013745180000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301525f91829182917f000000000000000000000000000000000000000000000000000000000000000090911690630137451890602401602060405180830381865afa158015612391573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123b59190613599565b6040517f9097548d000000000000000000000000000000000000000000000000000000008152600481018690529091506001600160a01b03821690639097548d906024016040805180830381865afa158015612413573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124379190613e10565b80935081945050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f43bde6d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561249c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c09190613df7565b90506124de846124d283612710613e3f565b61ffff16612710612f00565b935050509250929050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612557576110e47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316333084612977565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa1580156125ff573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612623919061353a565b905061262f8382612af7565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015b5f604051808303815f87803b1580156126d0575f5ffd5b505af11580156126e2573d5f5f3e3d5ffd5b50505050505050565b5f612717837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506127238382612af7565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156127a8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127cc91906135bf565b506040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390528516906347e7ef24906044015f604051808303815f87803b15801561284d575f5ffd5b505af115801561285f573d5f5f3e3d5ffd5b50506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038716925063a9059cbb9150339083906370a0823190602401602060405180830381865afa1580156128c8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ec919061353a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af115801561294c573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061297091906135bf565b5050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526129f39186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612fb0565b50505050565b6040516001600160a01b0383811660248301526044820183905261144c91859182169063a9059cbb906064016129ac565b808015612a6857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b15612ae2577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004015f604051808303818588803b158015612ac6575f5ffd5b505af1158015612ad8573d5f5f3e3d5ffd5b5050505050505050565b61144c6001600160a01b038416333085612977565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612b45576110e46001600160a01b038316333084612977565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa158015612bcd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bf1919061353a565b9050612bfc33611142565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044016126b9565b6040517f7fe9a7e6000000000000000000000000000000000000000000000000000000008152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637fe9a7e690602401602060405180830381865afa158015612ce8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d0c9190613599565b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c3c5a54790602401602060405180830381865afa158015612d8e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612db291906135bf565b612e59576040517f22fa95c4000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906322fa95c4906024016020604051808303815f875af1158015612e33573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e579190613599565b505b919050565b5f612e7f826101c00151836101a00151612e7891906134e7565b8390613035565b826101800151836101e00151846101600151612e9b9190613568565b612ea59190613568565b612eaf9190613568565b92915050565b5f612ee2612ec28361307f565b8015612edd57505f8480612ed857612ed86134fa565b868809115b151590565b612eed868686612f00565b612ef791906134e7565b95945050505050565b5f5f5f612f0d86866130ab565b91509150815f03612f3157838181612f2757612f276134fa565b0492505050610e3a565b818411612f4857612f4860038515026011186130e6565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f5f60205f8451602086015f885af180612fcf576040513d5f823e3d81fd5b50505f513d91508115612fe6578060011415612ff3565b6001600160a01b0384163b155b156129f3576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016114ce565b5f8261014001515f0361304957505f612eaf565b610e3a82846101800151856101e001518661016001516130699190613568565b6130739190613568565b8561014001515f612eb5565b5f600282600381111561309457613094613c09565b61309e9190613e59565b60ff166001149050919050565b5f807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f60c08284031215612e57575f5ffd5b5f60208284031215613117575f5ffd5b813567ffffffffffffffff81111561312d575f5ffd5b613139848285016130f7565b949350505050565b6001600160a01b0381168114613155575f5ffd5b50565b8035612e5981613141565b5f5f5f60608486031215613175575f5ffd5b833561318081613141565b95602085013595506040909401359392505050565b5f5f5f606084860312156131a7575f5ffd5b83356131b281613141565b925060208401356131c281613141565b929592945050506040919091013590565b5f5f604083850312156131e4575f5ffd5b82356131ef81613141565b946020939093013593505050565b8015158114613155575f5ffd5b8035612e59816131fd565b5f5f5f5f60808587031215613228575f5ffd5b843561323381613141565b9350602085013567ffffffffffffffff81111561324e575f5ffd5b61325a878288016130f7565b935050604085013561326b816131fd565b9396929550929360600135925050565b5f5f5f5f5f5f60a08789031215613290575f5ffd5b863567ffffffffffffffff8111156132a6575f5ffd5b8701601f810189136132b6575f5ffd5b803567ffffffffffffffff8111156132cc575f5ffd5b8960208260051b84010111156132e0575f5ffd5b6020918201975095506132f4908801613158565b9350604087013567ffffffffffffffff81111561330f575f5ffd5b61331b89828a016130f7565b93505061332a6060880161320a565b95989497509295919493608090920135925050565b5f5f5f60608486031215613351575f5ffd5b8335925060208401356131c281613141565b60ff81168114613155575f5ffd5b5f5f5f60608486031215613383575f5ffd5b833561338e81613141565b92506020840135915060408401356133a581613363565b809150509250925092565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126133e2575f5ffd5b9190910192915050565b5f602082840312156133fc575f5ffd5b8135610e3a816131fd565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261343a575f5ffd5b83018035915067ffffffffffffffff821115613454575f5ffd5b6020019150600581901b360382131561346b575f5ffd5b9250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156134af575f5ffd5b8135610e3a81613141565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115612eaf57612eaf6134ba565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82613535576135356134fa565b500490565b5f6020828403121561354a575f5ffd5b5051919050565b8082028115828204841417612eaf57612eaf6134ba565b81810381811115612eaf57612eaf6134ba565b5f82613589576135896134fa565b500690565b8051612e5981613141565b5f602082840312156135a9575f5ffd5b8151610e3a81613141565b8051612e59816131fd565b5f602082840312156135cf575f5ffd5b8151610e3a816131fd565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516102c0810167ffffffffffffffff8111828210171561362b5761362b6135da565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561365a5761365a6135da565b604052919050565b5f60208284031215613672575f5ffd5b815167ffffffffffffffff811115613688575f5ffd5b8201601f81018413613698575f5ffd5b805167ffffffffffffffff8111156136b2576136b26135da565b8060051b6136c260208201613631565b918252602081840181019290810190878411156136dd575f5ffd5b6020850194505b8385101561370b57845192506136f983613141565b828252602094850194909101906136e4565b979650505050505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613749575f5ffd5b830160208101925035905067ffffffffffffffff811115613768575f5ffd5b8060051b360382131561346b575f5ffd5b8183526020830192505f815f5b848110156137b757813561379981613141565b6001600160a01b031686526020958601959190910190600101613786565b5093949350505050565b5f6137cc8283613716565b60a085528060a08601527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115613802575f5ffd5b60051b808260c087013784019050602083013561381e81613363565b60ff1660208501526138336040840184613716565b60c086840301604087015261384c60c084018284613779565b9250505061385c6060840161320a565b1515606085015260809283013592909301919091525090565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126138a8575f5ffd5b830160208101925035905067ffffffffffffffff8111156138c7575f5ffd5b80360382131561346b575f5ffd5b81835281816020850137505f602082840101525f6020601f19601f840116840101905092915050565b602081525f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61843603018112613934575f5ffd5b60c0602084015261394a60e084018583016137c1565b90506139596020850185613875565b601f198584030160408601526139708382846138d5565b9250505061398060408501613158565b6001600160a01b03811660608501525061399c60608501613158565b6001600160a01b0381166080850152506139b96080850185613716565b601f198584030160a08601526139d0838284613779565b925050506139e060a0850161320a565b80151560c0850152509392505050565b602080825281018290525f6040600584901b8301810190830185835b86811015613a67577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0868503018352613a458289613875565b613a508682846138d5565b955050506020928301929190910190600101613a0c565b50919695505050505050565b8051612e5981613363565b805161ffff81168114612e59575f5ffd5b805163ffffffff81168114612e59575f5ffd5b805160038110612e59575f5ffd5b5f6102c0828403128015613ac2575f5ffd5b50613acb613607565b82518152613adb6020840161358e565b6020820152613aec60408401613a73565b60408201526060838101519082015260808084015190820152613b1160a0840161358e565b60a0820152613b2260c08401613a7e565b60c0820152613b3360e08401613a7e565b60e0820152613b456101008401613a8f565b610100820152613b586101208401613a8f565b6101208201526101408381015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e0808401519082015261020080840151908201526102208084015190820152613bc36102408401613a73565b610240820152613bd66102608401613a73565b610260820152613be961028084016135b4565b610280820152613bfc6102a08401613aa2565b6102a08201529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613c6b577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b815181526020808301516102c0830191613c93908401826001600160a01b03169052565b506040830151613ca8604084018260ff169052565b50606083015160608301526080830151608083015260a0830151613cd760a08401826001600160a01b03169052565b5060c0830151613ced60c084018261ffff169052565b5060e0830151613d0360e084018261ffff169052565b50610100830151613d1d61010084018263ffffffff169052565b50610120830151613d3761012084018263ffffffff169052565b506101408301516101408301526101608301516101608301526101808301516101808301526101a08301516101a08301526101c08301516101c08301526101e08301516101e0830152610200830151610200830152610220830151610220830152610240830151613dae61024084018260ff169052565b50610260830151613dc561026084018260ff169052565b50610280830151613ddb61028084018215159052565b506102a0830151613df06102a0840182613c36565b5092915050565b5f60208284031215613e07575f5ffd5b610e3a82613a7e565b5f5f60408385031215613e21575f5ffd5b82516020840151909250613e3481613363565b809150509250929050565b61ffff8181168382160190811115612eaf57612eaf6134ba565b5f60ff831680613e6b57613e6b6134fa565b8060ff8416069150509291505056fea2646970667358221220a251c113cc429b06965d89acf00b225e00ee46f582824303c17dc0522233ec6564736f6c634300081e00330000000000000000000000005555555555555555555555555555555555555555000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da50000000000000000000000005e4a85d1bad334a2fdd07856201136bc6ee2e3020000000000000000000000008bc1f48ce0d241bb2b7ec05af202b7da9aabd1d9000000000000000000000000e9d69cdd6fe41e7b621b4a688c5d1a68cb5c8adc", - "nonce": "0x137", + "input": "0x610180604052348015610010575f5ffd5b506040516146a83803806146a883398101604081905261002f916103b6565b6001600160a01b0380861661010052848116608081905284821660a05283821660c05290821660e0526040805163311176d760e01b8152905163311176d7916004808201926020929091908290030181865afa158015610091573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100b59190610417565b6001600160a01b0316610120816001600160a01b031681525050836001600160a01b031663eb91d0f56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012f9190610417565b6001600160a01b0316610140816001600160a01b031681525050836001600160a01b03166331d31efb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a99190610417565b6001600160a01b03908116610160526101005160805160405163095ea7b360e01b815290831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af1158015610203573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102279190610437565b50610120516101405160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561027c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a09190610437565b506101405160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af11580156102f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103189190610437565b506101205160805160405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561036c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103909190610437565b505050505050610456565b80516001600160a01b03811681146103b1575f5ffd5b919050565b5f5f5f5f5f60a086880312156103ca575f5ffd5b6103d38661039b565b94506103e16020870161039b565b93506103ef6040870161039b565b92506103fd6060870161039b565b915061040b6080870161039b565b90509295509295909350565b5f60208284031215610427575f5ffd5b6104308261039b565b9392505050565b5f60208284031215610447575f5ffd5b81518015158114610430575f5ffd5b60805160a05160c05160e051610100516101205161014051610160516140616106475f395f818161029401528181612e4c01528181612ef80152612f9601525f8181610468015281816108a20152818161099601528181610aa301528181610b4001528181610bb201528181610beb01528181610e44015281816112260152818161135e01528181611db601528181611fb4015281816120a8015281816124eb01528181612527015281816125b8015261268e01525f818161026101528181610b0201528181610c1a01528181610c3f01528181610cea01528181610d6001528181610dce01528181611156015281816111cc0152818161128b0152818161132c01528181611834015281816118b0015281816121650152818161223f015281816125870152818161265f0152818161289701528181612907015281816129a201528181612caa01528181612d370152612dec01525f81816101c801528181612be50152612c2001525f818161049b01528181611702015261179101525f81816103c401526110ed01525f81816102fa01526122e601525f8181610391015281816108d60152818161103d01528181611557015281816115e701528181611ab501528181611bbe01528181611c7301528181611e9c01528181611fe80152818161234a015261244201526140615ff3fe608060405260043610610165575f3560e01c80637aea9eab116100c6578063b500cf771161007c578063ea81deb411610057578063ea81deb414610438578063eb91d0f514610457578063f98d06f01461048a575f5ffd5b8063b500cf77146103e6578063ca38e8cc14610405578063e2230a4214610424575f5ffd5b806389d7f33c116100ac57806389d7f33c1461036157806396ebfb89146103805780639a76c764146103b3575f5ffd5b80637aea9eab1461033b57806381f139f41461034e575f5ffd5b806331d31efb1161011b5780633e7e6927116101015780633e7e6927146102ca57806343d2c350146102e9578063623556381461031c575f5ffd5b806331d31efb1461028357806339b90b99146102b6575f5ffd5b806321679a2e1161014b57806321679a2e14610202578063248391ff14610223578063311176d714610250575f5ffd5b806307ecbf3c1461017057806317fcb39b146101b7575f5ffd5b3661016c57005b5f5ffd5b34801561017b575f5ffd5b5061018f61018a3660046132b8565b6104bd565b6040805194855260208501939093529183015260ff1660608201526080015b60405180910390f35b3480156101c2575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ae565b34801561020d575f5ffd5b5061022161021c366004613314565b61089b565b005b34801561022e575f5ffd5b5061024261023d366004613346565b610a80565b6040519081526020016101ae565b34801561025b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b34801561028e575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c1575f5ffd5b50610221610e41565b3480156102d5575f5ffd5b506102216102e4366004613384565b6110e8565b3480156102f4575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610327575f5ffd5b50610221610336366004613346565b611113565b61018f6103493660046133c6565b611451565b61018f61035c36600461342c565b6116fb565b34801561036c575f5ffd5b5061022161037b3660046134f0565b61182d565b34801561038b575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103be575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103f1575f5ffd5b50610221610400366004613522565b611ab2565b348015610410575f5ffd5b5061022161041f366004613314565b611fad565b34801561042f575f5ffd5b50610221612162565b348015610443575f5ffd5b50610221610452366004613384565b6122e1565b348015610462575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b348015610495575f5ffd5b506101ea7f000000000000000000000000000000000000000000000000000000000000000081565b5f8080806104cb8580613561565b6104dc90608081019060600161359d565b1561072d575f5b6104ed8680613561565b6104fb9060408101906135b8565b90508110156107275761050e8680613561565b61051c9060408101906135b8565b8281811061052c5761052c613623565b90506020020160208101906105419190613650565b6001600160a01b031663c6866922600261055b8980613561565b61056590806135b8565b8581811061057557610575613623565b9050602002013560016105889190613698565b61059291906136d8565b6040518263ffffffff1660e01b81526004016105b091815260200190565b602060405180830381865afa1580156105cb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ef91906136eb565b6105f99086613698565b94505f8061064c61061060608a0160408b01613650565b600261061c8b80613561565b61062690806135b8565b8781811061063657610636613623565b9050602002013561064791906136d8565b61230c565b9450915083905061065d8880613561565b61066b9060408101906135b8565b8481811061067b5761067b613623565b90506020020160208101906106909190613650565b6001600160a01b031663c6866922836040518263ffffffff1660e01b81526004016106bd91815260200190565b602060405180830381865afa1580156106d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fc91906136eb565b610707836002613702565b6107119190613719565b61071b9086613698565b945050506001016104e3565b50610894565b5f5b6107398680613561565b6107479060408101906135b8565b9050811015610892575f8061079561076560608a0160408b01613650565b61076f8a80613561565b61077990806135b8565b8681811061078957610789613623565b9050602002013561230c565b90925090506107a48286613698565b94509250826107b38880613561565b6107c19060408101906135b8565b848181106107d1576107d1613623565b90506020020160208101906107e69190613650565b6001600160a01b031663c68669226107ff6002856136d8565b6040518263ffffffff1660e01b815260040161081d91815260200190565b602060405180830381865afa158015610838573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061085c91906136eb565b6108669087613698565b955061087360028361372c565b60010361088857610885600187613698565b95505b505060010161072f565b505b9193509193565b5f6108c7847f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506108d384826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610930573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610954919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156109de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a029190613770565b506040517ff9b1a9ad00000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0382169063f9b1a9ad906044015b5f604051808303815f87803b158015610a63575f5ffd5b505af1158015610a75573d5f5f3e3d5ffd5b505050505050505050565b5f826001600160a01b0316846001600160a01b031603610aa1575080610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610bb0576040517f4af218260000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03818116600484015260248301859052610ba99286917f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401602060405180830381865afa158015610b85573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023d91906136eb565b9050610e3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610ce8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396846de07f0000000000000000000000000000000000000000000000000000000000000000610c64877f000000000000000000000000000000000000000000000000000000000000000087610a80565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044015b602060405180830381865afa158015610cc4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906136eb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610d8f576040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018490527f00000000000000000000000000000000000000000000000000000000000000001690634af2182690604401610ca9565b6040517f96846de00000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906396846de090604401602060405180830381865afa158015610e13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3791906136eb565b90505b9392505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e9d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ec49190810190613813565b90505f5b81518110156110e457818181518110610ee357610ee3613623565b60209081029190910101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f80294d930000000000000000000000000000000000000000000000000000000060048201526001600160a01b03909116906301ffc9a790602401602060405180830381865afa158015610f6a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190613770565b156110dc575f828281518110610fa657610fa6613623565b60200260200101516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100d919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529192509082169063095ea7b3906044016020604051808303815f875af11580156110b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110d99190613770565b50505b600101610ec8565b5050565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b816001600160a01b0316836001600160a01b03160361113157505050565b805f0361113d57505050565b611154335b6001600160a01b038516903084612b28565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611224576040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015f604051808303815f87803b15801561120d575f5ffd5b505af115801561121f573d5f5f3e3d5ffd5b505050505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036113b8576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156112d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112fc91906136eb565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906347e7ef24906044015f604051808303815f87803b1580156113a1575f5ffd5b505af11580156113b3573d5f5f3e3d5ffd5b505050505b61144c336040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015611417573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061143b91906136eb565b6001600160a01b0385169190612baa565b505050565b5f5f5f5f61145e876104bd565b9296509094509250905083156114f157848411156114d7576114866060880160408901613650565b6040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260248101859052604481018690526064015b60405180910390fd5b6114f16114ea6060890160408a01613650565b8588612bdb565b8215611554578483111561154a576040517f02ec024a0000000000000000000000000000000000000000000000000000000081526001600160a01b038916600482015260248101849052604481018690526064016114ce565b6115548884612ca8565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639cf42ffa478a6040518363ffffffff1660e01b81526004016115a29190613aaf565b60206040518083038185885af11580156115be573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906115e391906136eb565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611641573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611665919061374a565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018490526064015f604051808303815f87803b1580156116d9575f5ffd5b505af11580156116eb573d5f5f3e3d5ffd5b5050505050945094509450949050565b5f5f5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d47eed458c8c6040518363ffffffff1660e01b815260040161174e929190613ba1565b602060405180830381865afa158015611769573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178d91906136eb565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ef9e5e28828d8d6040518463ffffffff1660e01b81526004016117de929190613ba1565b5f604051808303818588803b1580156117f5575f5ffd5b505af1158015611807573d5f5f3e3d5ffd5b505050505061181889898989611451565b929e919d509b50909950975050505050505050565b5f611859837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90505f61186585612e1b565b90506118718483612ca8565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af11580156118f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061191a9190613770565b506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018390526001600160a01b0382169063b6b55f25906024016020604051808303815f875af1158015611978573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199c91906136eb565b506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b0382169063a9059cbb90339083906370a0823190602401602060405180830381865afa158015611a02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a2691906136eb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611a86573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aaa9190613770565b505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b0f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b33919061374a565b6040517f581a7ab0000000000000000000000000000000000000000000000000000000008152600481018590529091505f906001600160a01b0383169063581a7ab0906024016102c060405180830381865afa158015611b95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bb99190613c61565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e78bede836040518263ffffffff1660e01b8152600401611c089190613e20565b602060405180830381865afa158015611c23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c479190613fa8565b61ffff1690505f611c65611c5a8461300f565b836127106001613066565b9050611c7187826124e9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ccd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf1919061374a565b6001600160a01b03166323b872dd336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152306024820152604481018990526064015f604051808303815f87803b158015611d63575f5ffd5b505af1158015611d75573d5f5f3e3d5ffd5b50506040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018590527f000000000000000000000000000000000000000000000000000000000000000016925063095ea7b391506044016020604051808303815f875af1158015611dfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e229190613770565b506040517f8fb702200000000000000000000000000000000000000000000000000000000081526004810187905260ff861660248201526001600160a01b03851690638fb70220906044015f604051808303815f87803b158015611e84575f5ffd5b505af1158015611e96573d5f5f3e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d7e24f2c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f1a919061374a565b6001600160a01b03166323b872dd30336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018990526064015f604051808303815f87803b158015611f8e575f5ffd5b505af1158015611fa0573d5f5f3e3d5ffd5b5050505050505050505050565b5f611fd9847f000000000000000000000000000000000000000000000000000000000000000084610a80565b9050611fe584826124e9565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b3ccbcfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612042573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612066919061374a565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152602482018590529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303815f875af11580156120f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121149190613770565b506040517f40b369c100000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b038216906340b369c190604401610a4c565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d3c7c2c76040518163ffffffff1660e01b81526004015f60405180830381865afa1580156121be573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e59190810190613813565b90505f5b81518110156110e45781818151811061220457612204613623565b60209081029190910101516040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248301529091169063095ea7b3906044016020604051808303815f875af11580156122b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d89190613770565b506001016121e9565b6110e47f000000000000000000000000000000000000000000000000000000000000000083836126eb565b6040517f013745180000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301525f91829182917f000000000000000000000000000000000000000000000000000000000000000090911690630137451890602401602060405180830381865afa158015612391573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123b5919061374a565b6040517f9097548d000000000000000000000000000000000000000000000000000000008152600481018690529091506001600160a01b03821690639097548d906024016040805180830381865afa158015612413573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124379190613fc1565b80935081945050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f43bde6d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561249c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c09190613fa8565b90506124de846124d283612710613ff0565b61ffff166127106130b1565b935050509250929050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612557576110e47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316333084612b28565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa1580156125ff573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262391906136eb565b905061262f8382612ca8565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018490527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044015b5f604051808303815f87803b1580156126d0575f5ffd5b505af11580156126e2573d5f5f3e3d5ffd5b50505050505050565b826001600160a01b03166389f91ece6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612727573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061274b9190613770565b80156128485750826001600160a01b03166391d14854846001600160a01b0316637a997ab76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561279d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127c191906136eb565b336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526001600160a01b03166024820152604401602060405180830381865afa158015612822573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128469190613770565b155b15612890576040517f876027c70000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201523360248201526044016114ce565b5f6128bc837f000000000000000000000000000000000000000000000000000000000000000084610a80565b90506128c88382612ca8565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af115801561294d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129719190613770565b506040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018390528516906347e7ef24906044015f604051808303815f87803b1580156129f2575f5ffd5b505af1158015612a04573d5f5f3e3d5ffd5b50505050836001600160a01b031663a9059cbb612a1e3390565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015612a79573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a9d91906136eb565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015612afd573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b219190613770565b5050505050565b6040516001600160a01b038481166024830152838116604483015260648201839052612ba49186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613161565b50505050565b6040516001600160a01b0383811660248301526044820183905261144c91859182169063a9059cbb90606401612b5d565b808015612c1957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b15612c93577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004015f604051808303818588803b158015612c77575f5ffd5b505af1158015612c89573d5f5f3e3d5ffd5b5050505050505050565b61144c6001600160a01b038416333085612b28565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031603612cf6576110e46001600160a01b038316333084612b28565b6040517f4af218260000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390525f917f000000000000000000000000000000000000000000000000000000000000000090911690634af2182690604401602060405180830381865afa158015612d7e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da291906136eb565b9050612dad33611142565b6040517f47e7ef240000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390527f000000000000000000000000000000000000000000000000000000000000000016906347e7ef24906044016126b9565b6040517f7fe9a7e6000000000000000000000000000000000000000000000000000000008152600481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637fe9a7e690602401602060405180830381865afa158015612e99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ebd919061374a565b6040517fc3c5a5470000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c3c5a54790602401602060405180830381865afa158015612f3f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f639190613770565b61300a576040517f22fa95c4000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906322fa95c4906024016020604051808303815f875af1158015612fe4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613008919061374a565b505b919050565b5f613030826101c00151836101a001516130299190613698565b83906131e6565b826101800151836101e0015184610160015161304c9190613719565b6130569190613719565b6130609190613719565b92915050565b5f61309361307383613230565b801561308e57505f8480613089576130896136ab565b868809115b151590565b61309e8686866130b1565b6130a89190613698565b95945050505050565b5f5f5f6130be868661325c565b91509150815f036130e2578381816130d8576130d86136ab565b0492505050610e3a565b8184116130f9576130f96003851502601118613297565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f5f60205f8451602086015f885af180613180576040513d5f823e3d81fd5b50505f513d915081156131975780600114156131a4565b6001600160a01b0384163b155b15612ba4576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016114ce565b5f8261014001515f036131fa57505f613060565b610e3a82846101800151856101e0015186610160015161321a9190613719565b6132249190613719565b8561014001515f613066565b5f600282600381111561324557613245613dba565b61324f919061400a565b60ff166001149050919050565b5f807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f60c08284031215613008575f5ffd5b5f602082840312156132c8575f5ffd5b813567ffffffffffffffff8111156132de575f5ffd5b6132ea848285016132a8565b949350505050565b6001600160a01b0381168114613306575f5ffd5b50565b803561300a816132f2565b5f5f5f60608486031215613326575f5ffd5b8335613331816132f2565b95602085013595506040909401359392505050565b5f5f5f60608486031215613358575f5ffd5b8335613363816132f2565b92506020840135613373816132f2565b929592945050506040919091013590565b5f5f60408385031215613395575f5ffd5b82356133a0816132f2565b946020939093013593505050565b8015158114613306575f5ffd5b803561300a816133ae565b5f5f5f5f608085870312156133d9575f5ffd5b84356133e4816132f2565b9350602085013567ffffffffffffffff8111156133ff575f5ffd5b61340b878288016132a8565b935050604085013561341c816133ae565b9396929550929360600135925050565b5f5f5f5f5f5f60a08789031215613441575f5ffd5b863567ffffffffffffffff811115613457575f5ffd5b8701601f81018913613467575f5ffd5b803567ffffffffffffffff81111561347d575f5ffd5b8960208260051b8401011115613491575f5ffd5b6020918201975095506134a5908801613309565b9350604087013567ffffffffffffffff8111156134c0575f5ffd5b6134cc89828a016132a8565b9350506134db606088016133bb565b95989497509295919493608090920135925050565b5f5f5f60608486031215613502575f5ffd5b833592506020840135613373816132f2565b60ff81168114613306575f5ffd5b5f5f5f60608486031215613534575f5ffd5b833561353f816132f2565b925060208401359150604084013561355681613514565b809150509250925092565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112613593575f5ffd5b9190910192915050565b5f602082840312156135ad575f5ffd5b8135610e3a816133ae565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126135eb575f5ffd5b83018035915067ffffffffffffffff821115613605575f5ffd5b6020019150600581901b360382131561361c575f5ffd5b9250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215613660575f5ffd5b8135610e3a816132f2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156130605761306061366b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826136e6576136e66136ab565b500490565b5f602082840312156136fb575f5ffd5b5051919050565b80820281158282048414176130605761306061366b565b818103818111156130605761306061366b565b5f8261373a5761373a6136ab565b500690565b805161300a816132f2565b5f6020828403121561375a575f5ffd5b8151610e3a816132f2565b805161300a816133ae565b5f60208284031215613780575f5ffd5b8151610e3a816133ae565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516102c0810167ffffffffffffffff811182821017156137dc576137dc61378b565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561380b5761380b61378b565b604052919050565b5f60208284031215613823575f5ffd5b815167ffffffffffffffff811115613839575f5ffd5b8201601f81018413613849575f5ffd5b805167ffffffffffffffff8111156138635761386361378b565b8060051b613873602082016137e2565b9182526020818401810192908101908784111561388e575f5ffd5b6020850194505b838510156138bc57845192506138aa836132f2565b82825260209485019490910190613895565b979650505050505050565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126138fa575f5ffd5b830160208101925035905067ffffffffffffffff811115613919575f5ffd5b8060051b360382131561361c575f5ffd5b8183526020830192505f815f5b8481101561396857813561394a816132f2565b6001600160a01b031686526020958601959190910190600101613937565b5093949350505050565b5f61397d82836138c7565b60a085528060a08601527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139b3575f5ffd5b60051b808260c08701378401905060208301356139cf81613514565b60ff1660208501526139e460408401846138c7565b60c08684030160408701526139fd60c08401828461392a565b92505050613a0d606084016133bb565b1515606085015260809283013592909301919091525090565b5f5f83357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613a59575f5ffd5b830160208101925035905067ffffffffffffffff811115613a78575f5ffd5b80360382131561361c575f5ffd5b81835281816020850137505f602082840101525f6020601f19601f840116840101905092915050565b602081525f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61843603018112613ae5575f5ffd5b60c06020840152613afb60e08401858301613972565b9050613b0a6020850185613a26565b601f19858403016040860152613b21838284613a86565b92505050613b3160408501613309565b6001600160a01b038116606085015250613b4d60608501613309565b6001600160a01b038116608085015250613b6a60808501856138c7565b601f198584030160a0860152613b8183828461392a565b92505050613b9160a085016133bb565b80151560c0850152509392505050565b602080825281018290525f6040600584901b8301810190830185835b86811015613c18577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0868503018352613bf68289613a26565b613c01868284613a86565b955050506020928301929190910190600101613bbd565b50919695505050505050565b805161300a81613514565b805161ffff8116811461300a575f5ffd5b805163ffffffff8116811461300a575f5ffd5b80516003811061300a575f5ffd5b5f6102c0828403128015613c73575f5ffd5b50613c7c6137b8565b82518152613c8c6020840161373f565b6020820152613c9d60408401613c24565b60408201526060838101519082015260808084015190820152613cc260a0840161373f565b60a0820152613cd360c08401613c2f565b60c0820152613ce460e08401613c2f565b60e0820152613cf66101008401613c40565b610100820152613d096101208401613c40565b6101208201526101408381015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e0808401519082015261020080840151908201526102208084015190820152613d746102408401613c24565b610240820152613d876102608401613c24565b610260820152613d9a6102808401613765565b610280820152613dad6102a08401613c53565b6102a08201529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110613e1c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b815181526020808301516102c0830191613e44908401826001600160a01b03169052565b506040830151613e59604084018260ff169052565b50606083015160608301526080830151608083015260a0830151613e8860a08401826001600160a01b03169052565b5060c0830151613e9e60c084018261ffff169052565b5060e0830151613eb460e084018261ffff169052565b50610100830151613ece61010084018263ffffffff169052565b50610120830151613ee861012084018263ffffffff169052565b506101408301516101408301526101608301516101608301526101808301516101808301526101a08301516101a08301526101c08301516101c08301526101e08301516101e0830152610200830151610200830152610220830151610220830152610240830151613f5f61024084018260ff169052565b50610260830151613f7661026084018260ff169052565b50610280830151613f8c61028084018215159052565b506102a0830151613fa16102a0840182613de7565b5092915050565b5f60208284031215613fb8575f5ffd5b610e3a82613c2f565b5f5f60408385031215613fd2575f5ffd5b82516020840151909250613fe581613514565b809150509250929050565b61ffff81811683821601908111156130605761306061366b565b5f60ff83168061401c5761401c6136ab565b8060ff8416069150509291505056fea264697066735822122022abdc8ba0aebea94b7a374b6e826fcb20c25c7c6b8182b86058e7dd0318f62964736f6c634300081e00330000000000000000000000005555555555555555555555555555555555555555000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da50000000000000000000000005e4a85d1bad334a2fdd07856201136bc6ee2e3020000000000000000000000008bc1f48ce0d241bb2b7ec05af202b7da9aabd1d9000000000000000000000000e9d69cdd6fe41e7b621b4a688c5d1a68cb5c8adc", + "nonce": "0x13c", "chainId": "0x3e7" }, "additionalContracts": [], "isFixedGasLimit": false }, { - "hash": "0xd438b85c2433586d90a9dbbd25e6e274e1c8519bf5c2ace95df6c6ef219ca0af", + "hash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", "transactionType": "CALL", "contractName": "Router", - "contractAddress": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "function": "approveCollaterals()", "arguments": [], "transaction": { "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", - "to": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "gas": "0x13422", "value": "0x0", "input": "0x39b90b99", - "nonce": "0x138", + "nonce": "0x13d", "chainId": "0x3e7" }, "additionalContracts": [], "isFixedGasLimit": false }, { - "hash": "0x099dec62101f4c807c6741f02f5ad5bdcd4fac1d00613305c678bb457d9e4c2a", + "hash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", "transactionType": "CALL", "contractName": "Router", - "contractAddress": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "function": "approveUsdTokens()", "arguments": [], "transaction": { "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", - "to": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "gas": "0x31824", "value": "0x0", "input": "0xe2230a42", - "nonce": "0x139", + "nonce": "0x13e", "chainId": "0x3e7" }, "additionalContracts": [], @@ -66,188 +66,188 @@ "receipts": [ { "status": "0x1", - "cumulativeGasUsed": "0x1458d6e", + "cumulativeGasUsed": "0x53131a", "logs": [ { "address": "0x5555555555555555555555555555555555555555", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", - "transactionIndex": "0x3", - "logIndex": "0xbc", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x12", "removed": false }, { "address": "0x22632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x00000000000000000000000088e35cd2cc5845780058e997cbd3fd92e3345864" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", - "transactionIndex": "0x3", - "logIndex": "0xbd", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x13", "removed": false }, { "address": "0x88e35cd2cc5845780058e997cbd3fd92e3345864", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", - "transactionIndex": "0x3", - "logIndex": "0xbe", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x14", "removed": false }, { "address": "0x22632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", - "transactionIndex": "0x3", - "logIndex": "0xbf", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "logIndex": "0x15", "removed": false } ], - "logsBloom": "0x00000000000000000000000000000000000000000000000000001000000000000020000000000000000000000000020000000000000000000800000000200000000000000000020002000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020200000000000000000000008001000000000000000000000000000000000002000000000000000000000000010000000000000000000000000000000000000010002000080000000000000002000000000000000000000020000000000000", + "logsBloom": "0x00000000000000000000000000000000000400000000000000001000000000000020000000000000000000000000020000000000000000000000000000200000000000000000020002000000000000000000000000000000000000000040000000010000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020200000000000000000000008001000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010002000080000000000000082000000000000000000000000000000000000", "type": "0x2", - "transactionHash": "0xe6a67af8bdba2b757b07d71400833de0b9949b7dc5c976400c544f9b590f40c5", - "transactionIndex": "0x3", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "gasUsed": "0x377cbe", - "effectiveGasPrice": "0x6f01f80", + "transactionHash": "0xf8617c3ab6be37d094df29b160f6acca8361aa11a752d32d484213acb0e83554", + "transactionIndex": "0x2", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "gasUsed": "0x38e826", + "effectiveGasPrice": "0x202190e5", "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", "to": null, - "contractAddress": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1" + "contractAddress": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316" }, { "status": "0x1", - "cumulativeGasUsed": "0x146601f", + "cumulativeGasUsed": "0x53e5cb", "logs": [ { "address": "0x5555555555555555555555555555555555555555", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x000000000000000000000000df8023679fe964982bdb93956f96b01c25f33da5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0xd438b85c2433586d90a9dbbd25e6e274e1c8519bf5c2ace95df6c6ef219ca0af", - "transactionIndex": "0x4", - "logIndex": "0xc0", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", + "transactionIndex": "0x3", + "logIndex": "0x16", "removed": false } ], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000200000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000010000000080000000000000002000000000000000000000020000000000000", + "logsBloom": "0x00000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000002000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000008000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000080000000000000082000000000000000000000000000000000000", "type": "0x2", - "transactionHash": "0xd438b85c2433586d90a9dbbd25e6e274e1c8519bf5c2ace95df6c6ef219ca0af", - "transactionIndex": "0x4", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", + "transactionHash": "0x3079803556de878cdf65525d8c7d386a6bbd66daa4744c4260db143d4d269878", + "transactionIndex": "0x3", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", "gasUsed": "0xd2b1", - "effectiveGasPrice": "0x6f01f80", + "effectiveGasPrice": "0x202190e5", "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", - "to": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "contractAddress": null }, { "status": "0x1", - "cumulativeGasUsed": "0x1487dc2", + "cumulativeGasUsed": "0x56036e", "logs": [ { "address": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0x099dec62101f4c807c6741f02f5ad5bdcd4fac1d00613305c678bb457d9e4c2a", - "transactionIndex": "0x5", - "logIndex": "0xc1", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x17", "removed": false }, { "address": "0xb88339cb7199b77e23db6e890353e22632ba630f", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0x099dec62101f4c807c6741f02f5ad5bdcd4fac1d00613305c678bb457d9e4c2a", - "transactionIndex": "0x5", - "logIndex": "0xc2", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x18", "removed": false }, { "address": "0x111111a1a0667d36bd57c0a9f569b98057111111", "topics": [ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x00000000000000000000000058b6943ed3a48981ea58c0918830efd4febbe5a1", + "0x0000000000000000000000002a868efd3cdf2be83ff63decdfdc07a8dcada316", "0x00000000000000000000000022632c11c1b4ff37edb06ddc1d5bf9c4ca2132e5" ], "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", - "blockTimestamp": "0x694378bc", - "transactionHash": "0x099dec62101f4c807c6741f02f5ad5bdcd4fac1d00613305c678bb457d9e4c2a", - "transactionIndex": "0x5", - "logIndex": "0xc3", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", + "blockTimestamp": "0x6945fbdc", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "logIndex": "0x19", "removed": false } ], - "logsBloom": "0x00000080400000000000400000000000000000000000000000000000000000000000000000000000000004000000000000000000080000000800000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000400000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000200000000000200010000000000000000000000000000000000000000000081020000000000000", + "logsBloom": "0x00000080400000000000400000000000000400000000000000000000000000000000000000000000000004000000000000000000080000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000400000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000200000000000200010000000000000000000000080000000000000000000081000000000000000", "type": "0x2", - "transactionHash": "0x099dec62101f4c807c6741f02f5ad5bdcd4fac1d00613305c678bb457d9e4c2a", - "transactionIndex": "0x5", - "blockHash": "0xeb6dbce4a58756f82bf324ccc26cafaef49f893362340ad515d781d3bd3604b3", - "blockNumber": "0x151cfd1", + "transactionHash": "0x52c7a3ca8881bedd9588016433b816f1dd6f82b4699542da63813d1891fc7b11", + "transactionIndex": "0x4", + "blockHash": "0x60e2a82161d1a2342a92f20ce87a77996e9ad3d23d8051dce96f52dd2309abf9", + "blockNumber": "0x1545da9", "gasUsed": "0x21da3", - "effectiveGasPrice": "0x6f01f80", + "effectiveGasPrice": "0x202190e5", "from": "0xd7e86bd77784217324b4e94aedc68e5c8227ec2b", - "to": "0x58b6943ed3a48981ea58c0918830efd4febbe5a1", + "to": "0x2a868efd3cdf2be83ff63decdfdc07a8dcada316", "contractAddress": null } ], "libraries": [], "pending": [], "returns": {}, - "timestamp": 1766029502056, + "timestamp": 1766194143046, "chain": 999, - "commit": "da1d2a2" + "commit": "43573b1" } \ No newline at end of file diff --git a/src/Router.sol b/src/Router.sol index a4c8cd8..8bf37b1 100644 --- a/src/Router.sol +++ b/src/Router.sol @@ -29,6 +29,7 @@ import {PythErrors} from "@pythnetwork/PythErrors.sol"; import {MortgageMath} from "@core/libraries/MortgageMath.sol"; import {MortgagePosition} from "@core/types/MortgagePosition.sol"; import {ILiquidityVault} from "./interfaces/ILiquidityVault/ILiquidityVault.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; /** * @title Router @@ -466,18 +467,25 @@ contract Router is * @param usdTokenAmount The amount of usdToken to pull in */ function _vaultDeposit(address vault, address usdToken, uint256 usdTokenAmount) internal { + if ( + ILiquidityVault(vault).whitelistEnforced() + && !IAccessControl(vault).hasRole(ILiquidityVault(vault).WHITELIST_ROLE(), _msgSender()) + ) { + revert VaultWhitelistEnforced(vault, _msgSender()); + } + // Convert the usdTokenAmount to USDX uint256 usdxAmount = convert(usdToken, usdx, usdTokenAmount); // Pull in the usdToken from the user _pullUsdToken(usdToken, usdxAmount); - // Deposit the USDX into the rollover vault + // Deposit the USDX into the vault IUSDX(usdx).approve(vault, usdxAmount); ILiquidityVault(vault).deposit(usdx, usdxAmount); // Transfer the vault share tokens to the user - ILiquidityVault(vault).transfer(msg.sender, ILiquidityVault(vault).balanceOf(address(this))); + ILiquidityVault(vault).transfer(_msgSender(), ILiquidityVault(vault).balanceOf(address(this))); } /** diff --git a/src/interfaces/IRouter/IRouterErrors.sol b/src/interfaces/IRouter/IRouterErrors.sol index 8315c05..9df3b6b 100644 --- a/src/interfaces/IRouter/IRouterErrors.sol +++ b/src/interfaces/IRouter/IRouterErrors.sol @@ -14,4 +14,11 @@ interface IRouterErrors { * @param maxColllected The maximum amount that can be collected */ error CollectedAmountExceedsMaximum(address token, uint256 collectedAmount, uint256 maxColllected); + + /** + * @notice Thrown when the vault's whitelist is enforced and the sender is not whitelisted + * @param vault The address of the vault + * @param sender The address of the sender + */ + error VaultWhitelistEnforced(address vault, address sender); } diff --git a/verification.json b/verification.json index 7bf31ba..58de7b3 100644 --- a/verification.json +++ b/verification.json @@ -1 +1 @@ -{"language":"Solidity","sources":{"src/Router.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {ILoanManager} from \"@core/interfaces/ILoanManager/ILoanManager.sol\";\nimport {IGeneralManager, IGeneralManagerErrors} from \"@core/interfaces/IGeneralManager/IGeneralManager.sol\";\nimport {Context} from \"@openzeppelin/contracts/utils/Context.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IOriginationPool, IOriginationPoolErrors} from \"@core/interfaces/IOriginationPool/IOriginationPool.sol\";\nimport {IPriceOracle} from \"@core/interfaces/IPriceOracle.sol\";\nimport {IConsol} from \"@core/interfaces/IConsol/IConsol.sol\";\nimport {ISubConsol} from \"@core/interfaces/ISubConsol/ISubConsol.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {IUSDX} from \"@core/interfaces/IUSDX/IUSDX.sol\";\nimport {CreationRequest} from \"@core/types/orders/OrderRequests.sol\";\nimport {IWNT} from \"./interfaces/IWNT.sol\";\nimport {OPoolConfigId} from \"@core/types/OPoolConfigId.sol\";\nimport {\n IOriginationPoolScheduler,\n IOriginationPoolSchedulerErrors\n} from \"@core/interfaces/IOriginationPoolScheduler/IOriginationPoolScheduler.sol\";\nimport {IRouter} from \"./interfaces/IRouter/IRouter.sol\";\nimport {IMortgageNFT} from \"@core/interfaces/IMortgageNFT/IMortgageNFT.sol\";\nimport {IMortgageNFTErrors} from \"@core/interfaces/IMortgageNFT/IMortgageNFTErrors.sol\";\nimport {IERC20Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {IPyth} from \"@pythnetwork/IPyth.sol\";\nimport {PythErrors} from \"@pythnetwork/PythErrors.sol\";\nimport {MortgageMath} from \"@core/libraries/MortgageMath.sol\";\nimport {MortgagePosition} from \"@core/types/MortgagePosition.sol\";\nimport {ILiquidityVault} from \"./interfaces/ILiquidityVault/ILiquidityVault.sol\";\n\n/**\n * @title Router\n * @author @SocksNFlops\n * @notice This contract facilitates user interactions with core contracts of the Cash protocol.\n */\ncontract Router is\n IRouter,\n Context,\n IMortgageNFTErrors,\n IERC20Errors,\n IGeneralManagerErrors,\n IOriginationPoolErrors,\n IOriginationPoolSchedulerErrors\n{\n using SafeERC20 for IERC20;\n using MortgageMath for MortgagePosition;\n using PythErrors for IPyth;\n\n /// @inheritdoc IRouter\n address public immutable generalManager;\n /// @inheritdoc IRouter\n address public immutable rolloverVault;\n /// @inheritdoc IRouter\n address public immutable fulfillmentVault;\n /// @inheritdoc IRouter\n address public immutable pyth;\n /// @inheritdoc IRouter\n address public immutable wrappedNativeToken;\n /// @inheritdoc IRouter\n address public immutable usdx;\n /// @inheritdoc IRouter\n address public immutable consol;\n /// @inheritdoc IRouter\n address public immutable originationPoolScheduler;\n\n /**\n * @param _wrappedNativeToken The address of the wrapped native token (i.e., whype: 0x555...)\n * @param _generalManager The address of the general manager contract\n * @param _rolloverVault The address of the rollover vault contract\n * @param _fulfillmentVault The address of the fulfillment vault contract\n * @param _pyth The address of the Pyth contract\n */\n constructor(address _wrappedNativeToken, address _generalManager, address _rolloverVault, address _fulfillmentVault, address _pyth) {\n wrappedNativeToken = _wrappedNativeToken;\n generalManager = _generalManager;\n rolloverVault = _rolloverVault;\n fulfillmentVault = _fulfillmentVault;\n pyth = _pyth;\n usdx = IGeneralManager(_generalManager).usdx();\n consol = IGeneralManager(_generalManager).consol();\n originationPoolScheduler = IGeneralManager(_generalManager).originationPoolScheduler();\n\n // Auto-approve the tokens to be spent by the consol/generalManager contracts\n IWNT(wrappedNativeToken).approve(generalManager, type(uint256).max);\n IUSDX(usdx).approve(consol, type(uint256).max);\n IConsol(consol).approve(generalManager, type(uint256).max);\n IUSDX(usdx).approve(generalManager, type(uint256).max);\n }\n\n receive() external payable {}\n\n /**\n * @inheritdoc IRouter\n */\n function approveCollaterals() external {\n address[] memory consolInputTokens = IConsol(consol).getSupportedTokens();\n // Iterate over consolInputTokens to find which are SubConsol tokens\n for (uint256 i = 0; i < consolInputTokens.length; i++) {\n if (IERC165(consolInputTokens[i]).supportsInterface(type(ISubConsol).interfaceId)) {\n // Fetch the collateral out of the SubConsol and max approve it to be spent by the generalManager\n address collateral = ISubConsol(consolInputTokens[i]).collateral();\n IERC20(collateral).approve(address(generalManager), type(uint256).max);\n }\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function approveUsdTokens() external {\n address[] memory usdTokens = IUSDX(usdx).getSupportedTokens();\n // Iterate over usdTokens and approve them to be spent by the USDX contract\n for (uint256 i = 0; i < usdTokens.length; i++) {\n IERC20(usdTokens[i]).approve(address(usdx), type(uint256).max);\n }\n }\n\n /**\n * @dev Internal function to pull in USDX via the underlying usdToken\n * @param usdToken The address of the usdToken to pull in\n * @param usdxAmount The amount of USDX to pull in\n */\n function _pullUsdToken(address usdToken, uint256 usdxAmount) internal {\n if (usdToken == address(usdx)) {\n // Don't need to wrap USDX\n // Pull in the USDX from the user\n IERC20(usdToken).safeTransferFrom(_msgSender(), address(this), usdxAmount);\n } else {\n // Need to wrap token into USDX\n // Calculate how much usdToken to pull in from the user\n uint256 usdTokenAmount = IUSDX(usdx).convertUnderlying(usdToken, usdxAmount);\n\n // Pull in the usdToken from the user\n IERC20(usdToken).safeTransferFrom(_msgSender(), address(this), usdTokenAmount);\n\n // Deposit the usdToken into the USDX contract\n IUSDX(usdx).deposit(usdToken, usdTokenAmount);\n }\n }\n\n /**\n * @dev Internal function to pull in Consol via the underlying usdTokens, USDX, SubConsols, or ForfeitedAssetsPool\n * @param inputToken The address of the input token to pull in\n * @param consolAmount The amount of Consol to pull in\n */\n function _pullInConsol(address inputToken, uint256 consolAmount) internal {\n if (inputToken == address(consol)) {\n // Input token is Consol\n // Pull in the Consol from the user\n IERC20(consol).safeTransferFrom(_msgSender(), address(this), consolAmount);\n } else {\n // Need to wrap token into USDX and then Consol\n // Calculate how much usdx is needed\n uint256 usdxAmount = IConsol(consol).convertUnderlying(usdx, consolAmount);\n // Pull in the usdToken from the user and convert it to USDX\n _pullUsdToken(inputToken, usdxAmount);\n // Deposit the USDX into Consol\n IConsol(consol).deposit(address(usdx), consolAmount);\n }\n }\n\n /**\n * @dev Internal function to pull in collateral\n * @param collateral The address of the collateral token to pull in\n * @param collateralCollected The amount of collateral to pull in\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n */\n function _pullCollateral(address collateral, uint256 collateralCollected, bool isNative) internal {\n if (isNative && collateral == address(wrappedNativeToken)) {\n // If you're paying with the native token, needs to be wrapped into the wrappedNativeToken first\n IWNT(wrappedNativeToken).deposit{value: collateralCollected}();\n } else {\n // Otherwise, pull in the collateral directly from the user\n IERC20(collateral).safeTransferFrom(_msgSender(), address(this), collateralCollected);\n }\n }\n\n /**\n * @dev Internal function to calculate the cost of a borrowing the collateral amount (including the price spread)\n * @param collateral The address of the collateral token\n * @param collateralAmount The amount of collateral to calculate the cost for\n * @return cost The cost of the collateral amount (including the price spread)\n * @return collateralDecimals The decimals of the collateral token\n */\n function _calculateCost(address collateral, uint256 collateralAmount)\n internal\n view\n returns (uint256 cost, uint8 collateralDecimals)\n {\n IPriceOracle priceOracle = IPriceOracle(IGeneralManager(generalManager).priceOracles(collateral));\n (cost, collateralDecimals) = priceOracle.cost(collateralAmount);\n\n // Get the price spread\n uint16 priceSpread = IGeneralManager(generalManager).priceSpread();\n\n // Add the price spread to the cost\n cost = Math.mulDiv(cost, 1e4 + priceSpread, 1e4);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function calculateCollectedAmounts(CreationRequest calldata creationRequest)\n public\n view\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n if (creationRequest.base.isCompounding) {\n for (uint256 i = 0; i < creationRequest.base.originationPools.length; i++) {\n // If compounding, need to collect 1/2 of the collateral amount + commission fee (this is in the form of collateral)\n collateralCollected += IOriginationPool(creationRequest.base.originationPools[i])\n .calculateReturnAmount((creationRequest.base.collateralAmounts[i] + 1) / 2);\n (uint256 _cost, uint8 _collateralDecimals) =\n _calculateCost(creationRequest.collateral, creationRequest.base.collateralAmounts[i] / 2);\n collateralDecimals = _collateralDecimals;\n paymentAmount += (2 * _cost)\n - IOriginationPool(creationRequest.base.originationPools[i]).calculateReturnAmount(_cost);\n }\n } else {\n for (uint256 i = 0; i < creationRequest.base.originationPools.length; i++) {\n // If non-compounding, need to collect the full amountBorrowed in USDX + commission fee\n (uint256 _cost, uint8 _collateralDecimals) =\n _calculateCost(creationRequest.collateral, creationRequest.base.collateralAmounts[i]);\n paymentAmount += _cost;\n collateralDecimals = _collateralDecimals;\n usdxCollected += IOriginationPool(creationRequest.base.originationPools[i]).calculateReturnAmount(_cost / 2);\n if (_cost % 2 == 1) {\n usdxCollected += 1;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function updatePriceFeedsAndRequestMortgage(\n bytes[] calldata priceUpdates,\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n public\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n // Fetch the update fees\n uint256 updateFee = IPyth(pyth).getUpdateFee(priceUpdates);\n\n // Fetch the Pyth contract\n IPyth(pyth).updatePriceFeeds{value: updateFee}(priceUpdates);\n\n return requestMortgage(usdToken, creationRequest, isNative, maxCollected);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function requestMortgage(\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n public\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n (collateralCollected, usdxCollected, paymentAmount, collateralDecimals) = calculateCollectedAmounts(creationRequest);\n\n if (collateralCollected > 0) {\n if (collateralCollected > maxCollected) {\n revert CollectedAmountExceedsMaximum(creationRequest.collateral, collateralCollected, maxCollected);\n }\n _pullCollateral(creationRequest.collateral, collateralCollected, isNative);\n }\n\n if (usdxCollected > 0) {\n if (usdxCollected > maxCollected) {\n revert CollectedAmountExceedsMaximum(usdToken, usdxCollected, maxCollected);\n }\n _pullUsdToken(usdToken, usdxCollected);\n }\n\n uint256 tokenId =\n IGeneralManager(generalManager).requestMortgageCreation{value: address(this).balance}(creationRequest);\n\n // Transfer the mortgageNFT to the user\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(address(this), _msgSender(), tokenId);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function periodPay(address inputToken, uint256 tokenId, uint256 inputAmount) external {\n // Convert the inputAmount to Consol\n uint256 consolAmount = convert(inputToken, consol, inputAmount);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, consolAmount);\n\n // Make the period payment on Consol\n address loanManager = IGeneralManager(generalManager).loanManager();\n IConsol(consol).approve(loanManager, consolAmount);\n ILoanManager(loanManager).periodPay(tokenId, consolAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function penaltyPay(address inputToken, uint256 tokenId, uint256 inputAmount) external {\n // Convert the inputAmount to Consol\n uint256 consolAmount = convert(inputToken, consol, inputAmount);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, consolAmount);\n\n // Make the penalty payment on Consol\n address loanManager = IGeneralManager(generalManager).loanManager();\n IConsol(consol).approve(loanManager, consolAmount);\n ILoanManager(loanManager).penaltyPay(tokenId, consolAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function refinance(address inputToken, uint256 tokenId, uint8 newTotalPeriods) external {\n // Fetch the loan manager\n address loanManager = IGeneralManager(generalManager).loanManager();\n\n // Fetch the mortgage position\n MortgagePosition memory mortgagePosition = ILoanManager(loanManager).getMortgagePosition(tokenId);\n\n // Fetch the refinance rate\n uint256 refinanceRate = IGeneralManager(generalManager).refinanceRate(mortgagePosition);\n\n // Calculate the refinance fee\n uint256 refinanceFee = Math.mulDiv(mortgagePosition.principalRemaining(), refinanceRate, 1e4, Math.Rounding.Ceil);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, refinanceFee);\n\n // Transfer the mortgageNFT to the router\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(_msgSender(), address(this), tokenId);\n\n // Call `refinanceMortgage` on the loan manager\n IConsol(consol).approve(loanManager, refinanceFee);\n ILoanManager(loanManager).refinanceMortgage(tokenId, newTotalPeriods);\n\n // Return the mortgageNFT to the user\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(address(this), _msgSender(), tokenId);\n }\n\n /**\n * @dev Internal function to get or create the latest origination pool for a given OPoolConfigId\n * @param oPoolConfigId The OPoolConfigId of the origination pool config\n * @return originationPool The origination pool\n */\n function _getOrCreateOriginationPool(OPoolConfigId oPoolConfigId)\n internal\n returns (IOriginationPool originationPool)\n {\n originationPool = IOriginationPool(\n IOriginationPoolScheduler(originationPoolScheduler).predictOriginationPool(oPoolConfigId)\n );\n if (!IOriginationPoolScheduler(originationPoolScheduler).isRegistered(address(originationPool))) {\n IOriginationPool(IOriginationPoolScheduler(originationPoolScheduler).deployOriginationPool(oPoolConfigId));\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function originationPoolDeposit(OPoolConfigId oPoolConfigId, address usdToken, uint256 usdTokenAmount) external {\n // Convert the usdTokenAmount to USDX\n uint256 usdxAmount = convert(usdToken, usdx, usdTokenAmount);\n\n // Fetch the origination pool\n IOriginationPool originationPool = _getOrCreateOriginationPool(oPoolConfigId);\n\n // Pull in the usdToken from the user\n _pullUsdToken(usdToken, usdxAmount);\n\n // Deposit the USDX into the origination pool\n IUSDX(usdx).approve(address(originationPool), usdxAmount);\n originationPool.deposit(usdxAmount);\n\n // Transfer the originationPool receipt tokens to the user\n originationPool.transfer(msg.sender, originationPool.balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IRouter\n */\n function convert(address inputToken, address outputToken, uint256 inputAmount)\n public\n view\n returns (uint256 outputAmount)\n {\n // Check if input and output tokens are the same\n if (inputToken == outputToken) {\n outputAmount = inputAmount;\n }\n // If the input is Consol, then recurse from (Consol -> USDX) -> outputToken\n else if (inputToken == address(consol)) {\n // If the inputToken is Consol, convert it to USDX\n outputAmount = convert(address(usdx), outputToken, IConsol(consol).convertUnderlying(usdx, inputAmount));\n }\n // If the output token is Consol, then recurse from (inputToken -> USDX) -> Consol\n else if (outputToken == address(consol)) {\n outputAmount = IConsol(consol).convertAmount(usdx, convert(inputToken, usdx, inputAmount));\n }\n // If the input is USDX, then the outputToken is a usdToken\n else if (inputToken == address(usdx)) {\n outputAmount = IUSDX(usdx).convertUnderlying(outputToken, inputAmount);\n }\n // Output token must be USDX, meaning the input token is a usdToken\n else {\n outputAmount = IUSDX(usdx).convertAmount(inputToken, inputAmount);\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function wrap(address inputToken, address outputToken, uint256 inputAmount) public {\n // Check if input and output tokens are the same. If so, don't do anything\n if (inputToken == outputToken) {\n return;\n } else if (inputAmount == 0) {\n return;\n }\n // Pull in the input token\n IERC20(inputToken).safeTransferFrom(_msgSender(), address(this), inputAmount);\n\n // If the inputToken isn't USDX, it must be a usdToken. Deposit it into USDX\n if (inputToken != address(usdx)) {\n IUSDX(usdx).deposit(inputToken, inputAmount);\n }\n\n // If the outputToken is Consol, then we must do one more wrapping\n if (outputToken == address(consol)) {\n // Fetch the new inputAmount\n inputAmount = IUSDX(usdx).balanceOf(address(this));\n // Convert the USDX to Consol\n IConsol(consol).deposit(address(usdx), inputAmount);\n }\n\n // Transfer the output token to the user\n IERC20(outputToken).safeTransfer(_msgSender(), IERC20(outputToken).balanceOf(address(this)));\n }\n\n /**\n * @dev Internal function to deposit into a liquidity vault\n * @param vault The address of the liquidity vault to deposit into\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function _vaultDeposit(address vault, address usdToken, uint256 usdTokenAmount) internal {\n // Convert the usdTokenAmount to USDX\n uint256 usdxAmount = convert(usdToken, usdx, usdTokenAmount);\n\n // Pull in the usdToken from the user\n _pullUsdToken(usdToken, usdxAmount);\n\n // Deposit the USDX into the rollover vault\n IUSDX(usdx).approve(vault, usdxAmount);\n ILiquidityVault(vault).deposit(usdx, usdxAmount);\n\n // Transfer the vault share tokens to the user\n ILiquidityVault(vault).transfer(msg.sender, ILiquidityVault(vault).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IRouter\n */\n function rolloverVaultDeposit(address usdToken, uint256 usdTokenAmount) external {\n _vaultDeposit(rolloverVault, usdToken, usdTokenAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function fulfillmentVaultDeposit(address usdToken, uint256 usdTokenAmount) external {\n _vaultDeposit(fulfillmentVault, usdToken, usdTokenAmount);\n }\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManager.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgagePosition} from \"../../types/MortgagePosition.sol\";\nimport {MortgageParams} from \"../../types/orders/MortgageParams.sol\";\nimport {ILoanManagerEvents} from \"./ILoanManagerEvents.sol\";\nimport {ILoanManagerErrors} from \"./ILoanManagerErrors.sol\";\nimport {IConsolFlashSwap} from \"../IConsolFlashSwap.sol\";\n\n/**\n * @title ILoanManager\n * @author Socks&Flops\n * @notice Interface for the LoanManager contract\n */\ninterface ILoanManager is ILoanManagerEvents, ILoanManagerErrors, IConsolFlashSwap {\n /**\n * @notice Returns the Consol token address\n * @return The Consol token address\n */\n function consol() external view returns (address);\n\n /**\n * @notice Returns the general manager address\n * @return The general manager address\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Returns the mortgage NFT address\n * @return The NFT address\n */\n function nft() external view returns (address);\n\n /**\n * @notice Creates a new mortgage position\n * @param mortgageParams The parameters for the mortgage position\n */\n function createMortgage(MortgageParams memory mortgageParams) external;\n\n /**\n * @notice Returns the mortgage position for a given tokenId\n * @param tokenId The tokenId of the mortgage position\n * @return The mortgage position\n */\n function getMortgagePosition(uint256 tokenId) external view returns (MortgagePosition memory);\n\n /**\n * @notice Imposes applicable penalties to a mortgage position\n * @param tokenId The tokenId of the mortgage position\n */\n function imposePenalty(uint256 tokenId) external;\n\n /**\n * @notice Pays the monthly payment for a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount to pay\n */\n function periodPay(uint256 tokenId, uint256 amount) external;\n\n /**\n * @notice Pays the penalty for a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount to pay\n */\n function penaltyPay(uint256 tokenId, uint256 amount) external;\n\n /**\n * @notice Redeems a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param async Whether to allow redemption to be asynchronous\n */\n function redeemMortgage(uint256 tokenId, bool async) external;\n\n /**\n * @notice Refinances a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param totalPeriods The total number of periods that the mortgage is being refinanced to.\n */\n function refinanceMortgage(uint256 tokenId, uint8 totalPeriods) external;\n\n /**\n * @notice Forecloses a mortgage position\n * @param tokenId The tokenId of the mortgage position\n */\n function forecloseMortgage(uint256 tokenId) external;\n\n /**\n * @notice Converts a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param currentPrice The current price of the collateral\n * @param amount The amount of the principal being coverted\n * @param collateralAmount The amount of the collateral being withdrawn during the conversion\n * @param receiver The address receiving the converted assets\n */\n function convertMortgage(\n uint256 tokenId,\n uint256 currentPrice,\n uint256 amount,\n uint256 collateralAmount,\n address receiver\n ) external;\n\n /**\n * @notice Expands the balance sheet of a mortgage position by adding addtional principal and collateral to the mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amountIn The amount of the principal being added to the mortgage position\n * @param collateralAmountIn The amount of collateral being added to the mortgage position\n * @param newInterestRate The new interest rate of the mortgage position\n */\n function expandBalanceSheet(uint256 tokenId, uint256 amountIn, uint256 collateralAmountIn, uint16 newInterestRate)\n external;\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManager.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IGeneralManagerEvents} from \"./IGeneralManagerEvents.sol\";\nimport {IGeneralManagerErrors} from \"./IGeneralManagerErrors.sol\";\nimport {MortgagePosition} from \"../../types/MortgagePosition.sol\";\nimport {CreationRequest, ExpansionRequest} from \"../../types/orders/OrderRequests.sol\";\nimport {IOriginationPoolDeployCallback} from \"../IOriginationPoolDeployCallback.sol\";\nimport {OriginationParameters} from \"../../types/orders/OriginationParameters.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\n\n/**\n * @title IGeneralManager\n * @author @SocksNFlops\n * @notice The GeneralManager contract is responsible for managing the mortgage positions and the foreclosure process.\n */\ninterface IGeneralManager is IOriginationPoolDeployCallback, IPausable, IGeneralManagerEvents, IGeneralManagerErrors {\n /**\n * @notice Returns the USDX token address\n * @return The USDX token address\n */\n function usdx() external view returns (address);\n\n /**\n * @notice Returns the Consol token address\n * @return The Consol token address\n */\n function consol() external view returns (address);\n\n /**\n * @notice Sets the penalty rate for a mortgage (in basis points)\n * @param penaltyRate_ The penalty rate\n */\n function setPenaltyRate(uint16 penaltyRate_) external;\n\n /**\n * @notice Returns the penalty rate for a mortgage (in basis points)\n * @dev Takes in a mortgage position to allow upgraded implementations to take into account the position's details.\n * @param mortgagePosition The position of the mortgage\n * @return The penalty rate\n */\n function penaltyRate(MortgagePosition memory mortgagePosition) external view returns (uint16);\n\n /**\n * @notice Sets the refinance rate for a mortgage (in basis points)\n * @param refinanceRate_ The refinance rate\n */\n function setRefinanceRate(uint16 refinanceRate_) external;\n\n /**\n * @notice Returns the refinance rate (in basis points).\n * @dev Takes in a mortgage position to allow upgraded implementations to take into account the position's details.\n * @param mortgagePosition The position of the mortgage\n * @return The refinance rate\n */\n function refinanceRate(MortgagePosition memory mortgagePosition) external view returns (uint16);\n\n /**\n * @notice Sets the insurance fund address\n * @param insuranceFund_ The insurance fund address\n */\n function setInsuranceFund(address insuranceFund_) external;\n\n /**\n * @notice Returns the insurance fund address\n * @return The insurance fund address\n */\n function insuranceFund() external view returns (address);\n\n /**\n * @notice Returns the interest rate oracle address\n * @return The interest rate oracle address\n */\n function interestRateOracle() external view returns (address);\n\n /**\n * @notice Sets the interest rate oracle address\n * @param interestRateOracle_ The interest rate oracle address\n */\n function setInterestRateOracle(address interestRateOracle_) external;\n\n /**\n * @notice Returns the interest rate (in basis points)\n * @param collateral The address of the collateral\n * @param totalPeriods The total number of periods for the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The interest rate\n */\n function interestRate(address collateral, uint8 totalPeriods, bool hasPaymentPlan) external view returns (uint16);\n\n /**\n * @notice Returns the conversion premium rate (in basis points)\n * @param collateral The address of the collateral\n * @param totalPeriods The total number of periods for the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The conversion premium rate\n */\n function conversionPremiumRate(address collateral, uint8 totalPeriods, bool hasPaymentPlan)\n external\n view\n returns (uint16);\n\n /**\n * @notice Sets the conversion premium rate (in basis points)\n * @param conversionPremiumRate_ The conversion premium rate\n */\n function setConversionPremiumRate(uint16 conversionPremiumRate_) external;\n\n /**\n * @notice Sets the origination pool scheduler address\n * @param originationPoolScheduler_ The origination pool scheduler address\n */\n function setOriginationPoolScheduler(address originationPoolScheduler_) external;\n\n /**\n * @notice Returns the origination pool scheduler address\n * @return The origination pool scheduler address\n */\n function originationPoolScheduler() external view returns (address);\n\n /**\n * @notice Sets the loan manager address\n * @param loanManager_ The loan manager address\n */\n function setLoanManager(address loanManager_) external;\n\n /**\n * @notice Returns the loan manager address\n * @return The loan manager address\n */\n function loanManager() external view returns (address);\n\n /**\n * @notice Returns the mortgage NFT address\n * @return The mortgage NFT address\n */\n function mortgageNFT() external view returns (address);\n\n /**\n * @notice Sets the order pool address\n * @param orderPool_ The order pool address\n */\n function setOrderPool(address orderPool_) external;\n\n /**\n * @notice Returns the order pool address\n * @return The order pool address\n */\n function orderPool() external view returns (address);\n\n /**\n * @notice Updates the supported mortgage period terms for a collateral.\n * @param collateral The address of the collateral\n * @param totalPeriods The new total number of periods for the new mortgage term\n * @param isSupported Whether the mortgage period term is supported\n */\n function updateSupportedMortgagePeriodTerms(address collateral, uint8 totalPeriods, bool isSupported) external;\n\n /**\n * @notice Returns whether a mortgage period term is supported\n * @param collateral The address of the collateral\n * @param mortgagePeriods The mortgage period\n * @return Whether the mortgage period term is supported\n */\n function isSupportedMortgagePeriodTerms(address collateral, uint8 mortgagePeriods) external view returns (bool);\n\n /**\n * @notice The address of the price oracle for the collateral\n * @param collateral The address of the collateral\n * @return The address of the price oracle\n */\n function priceOracles(address collateral) external view returns (address);\n\n /**\n * @notice Sets the address of the price oracle\n * @param collateral The address of the collateral\n * @param priceOracle The address of the price oracle\n */\n function setPriceOracle(address collateral, address priceOracle) external;\n\n /**\n * @notice Returns the minimum request size of a mortgage for a given collateral. Requests cannot borrow less than this amount.\n * @param collateral The address of the collateral\n * @return The minimum cap\n */\n function minimumCap(address collateral) external view returns (uint256);\n\n /**\n * @notice Sets the minimum request size of a mortgage for a given collateral. Requests cannot borrow less than this amount.\n * @param collateral The address of the collateral\n * @param minimumCap_ The minimum cap\n */\n function setMinimumCap(address collateral, uint256 minimumCap_) external;\n\n /**\n * @notice Returns the maximum request size of a mortgage for a given collateral. Requests cannot borrow more than this amount.\n * @param collateral The address of the collateral\n * @return The maximum cap\n */\n function maximumCap(address collateral) external view returns (uint256);\n\n /**\n * @notice Sets the maximum request size of a mortgage for a given collateral. Requests cannot borrow more than this amount.\n * @param collateral The address of the collateral\n * @param maximumCap_ The maximum cap\n */\n function setMaximumCap(address collateral, uint256 maximumCap_) external;\n\n /**\n * @notice The price spread to incentivize the fulfiller to fill orders\n * @return priceSpread The price spread\n */\n function priceSpread() external view returns (uint16);\n\n /**\n * @notice Sets the price spread to incentivize the fulfiller to fill orders\n * @param priceSpread_ The price spread\n */\n function setPriceSpread(uint16 priceSpread_) external;\n\n /**\n * @notice Returns the conversion queues a given mortgage position is registered with\n * @param tokenId The tokenId of the mortgage position\n * @return The conversion queues\n */\n function conversionQueues(uint256 tokenId) external view returns (address[] memory);\n\n /**\n * @notice Requests a new mortgage creation\n * @param creationRequest The parameters of the mortgage creation being requested\n * @return tokenId The tokenId of the mortgage NFT that was created\n */\n function requestMortgageCreation(CreationRequest calldata creationRequest) external payable returns (uint256 tokenId);\n\n /**\n * @notice Burns a mortgage NFT\n * @param tokenId The tokenId of the mortgage NFT to burn\n */\n function burnMortgageNFT(uint256 tokenId) external;\n\n /**\n * @notice Originates a mortgage position. Only callable by the OrderPool.\n * @param originationParameters The parameters for originating a mortgage creation or balance sheet expansion\n */\n function originate(OriginationParameters calldata originationParameters) external payable;\n\n /**\n * @notice Enqueues a mortgage position into a conversion queue\n * @param tokenId The tokenId of the mortgage position\n * @param conversionQueueList The list of conversion queues to use\n * @param hintPrevIds The hint for the previous mortgage position in the conversion queue\n */\n function enqueueMortgage(uint256 tokenId, address[] memory conversionQueueList, uint256[] memory hintPrevIds)\n external\n payable;\n\n /**\n * @notice Converts a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount of the principal being coverted\n * @param collateralAmount The amount of the collateral being withdrawn during the conversion\n * @param receiver The address receiving the converted collateral\n */\n function convert(uint256 tokenId, uint256 amount, uint256 collateralAmount, address receiver) external;\n\n /**\n * @notice Requests to expand the balance sheet of a mortgage position by adding additional principal and collateral to the mortgage position. Only callable by whitelisted addresses.\n * @param expansionRequest The parameters of the balance sheet expansion being requested\n */\n function requestBalanceSheetExpansion(ExpansionRequest calldata expansionRequest) external payable;\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance < requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n *\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n * set here.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n safeTransfer(token, to, value);\n } else if (!token.transferAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferFromAndCallRelaxed(\n IERC1363 token,\n address from,\n address to,\n uint256 value,\n bytes memory data\n ) internal {\n if (to.code.length == 0) {\n safeTransferFrom(token, from, to, value);\n } else if (!token.transferFromAndCall(from, to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n * once without retrying, and relies on the returned value to be true.\n *\n * Reverts if the returned value is other than `true`.\n */\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n forceApprove(token, to, value);\n } else if (!token.approveAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n uint256 returnSize;\n uint256 returnValue;\n assembly (\"memory-safe\") {\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n // bubble errors\n if iszero(success) {\n let ptr := mload(0x40)\n returndatacopy(ptr, 0, returndatasize())\n revert(ptr, returndatasize())\n }\n returnSize := returndatasize()\n returnValue := mload(0)\n }\n\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly (\"memory-safe\") {\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0)\n }\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n }\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPool.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IOriginationPoolEvents} from \"./IOriginationPoolEvents.sol\";\nimport {IOriginationPoolErrors} from \"./IOriginationPoolErrors.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\nimport {OriginationPoolPhase} from \"../../types/enums/OriginationPoolPhase.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title Interface for the OriginationPool contract\n */\ninterface IOriginationPool is IOriginationPoolEvents, IOriginationPoolErrors, IPausable, IERC20 {\n /**\n * @notice The USDX token address\n * @return The usdx address\n */\n function usdx() external view returns (address);\n\n /**\n * @notice The Consol token address\n * @return The consol address\n */\n function consol() external view returns (address);\n\n /**\n * @notice The deposit phase timestamp\n * @return The deposit phase timestamp\n */\n function depositPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice The deploy phase timestamp\n * @return The deploy phase timestamp\n */\n function deployPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice The redemption phase timestamp\n * @return The redemption phase timestamp\n */\n function redemptionPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice Fetches the current phase of the Origination Pool\n * @return The current phase\n */\n function currentPhase() external view returns (OriginationPoolPhase);\n\n /**\n * @notice Fetches the pool multiplier in basis points\n * @return The pool multiplier in basis points\n */\n function poolMultiplierBps() external view returns (uint16);\n\n /**\n * @notice Fetches the pool deposit limit\n * @return The pool deposit limit\n */\n function poolLimit() external view returns (uint256);\n\n /**\n * @notice Fetches the amount of USD tokens deployed from the pool\n * @return The amount of USD tokens deployed from the pool\n */\n function amountDeployed() external view returns (uint256);\n\n /**\n * @notice Calculates the return amount of Consol for a given amount of USDX by applying the pool multiplier\n * @param amount The amount of USDX to calculate the return amount for\n * @return returnAmount The return amount of Consol\n */\n function calculateReturnAmount(uint256 amount) external view returns (uint256 returnAmount);\n\n /**\n * @notice Deposit USDX into the pool\n * @param amount The amount of USDX to deposit\n * @return mintAmount The amount of receipt tokens minted to the user\n */\n function deposit(uint256 amount) external returns (uint256 mintAmount);\n\n /**\n * @notice Redeem USDX + Consol from the pool from receipt tokens\n * @param amount The amount of receipt tokens to burn in exchange for USDX + Consol\n */\n function redeem(uint256 amount) external;\n\n /**\n * @notice Deploy USDX in the pool and convert it to Consol. Only callable by contracts implementing IOriginationPoolDeployCallback\n * @param amount The amount of USDX to deploy\n * @param data The calldata to pass into the callback\n */\n function deploy(uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/IPriceOracle.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IPriceOracle\n * @author @SocksNFlops\n * @notice Interface for the price oracle.\n */\ninterface IPriceOracle {\n /**\n * @notice The number of decimals for the collateral\n * @return collateralDecimals The number of decimals for the collateral\n */\n function collateralDecimals() external view returns (uint8);\n\n /**\n * @notice Returns the price of the collateral in USDX\n * @return The price of the collateral in USDX (18 decimals)\n */\n function price() external view returns (uint256);\n\n /**\n * @notice Returns the cost of the collateral in USDX\n * @param collateralAmount The amount of collateral to calculate the cost of\n * @return totalCost The cost of the collateral in USDX (18 decimals)\n * @return _collateralDecimals The collateral decimals\n */\n function cost(uint256 collateralAmount) external view returns (uint256 totalCost, uint8 _collateralDecimals);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsol.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVault} from \"../IMultiTokenVault/IMultiTokenVault.sol\";\nimport {IConsolErrors} from \"./IConsolErrors.sol\";\nimport {IConsolEvents} from \"./IConsolEvents.sol\";\n\n/**\n * @title IConsol\n * @author SocksNFlops\n * @notice Interface for the Consol contract. A wrapper token for USDX and SubConsol tokens.\n */\ninterface IConsol is IMultiTokenVault, IConsolErrors, IConsolEvents {\n /**\n * @notice Get the address of the forfeited assets pool.\n * @return The address of the forfeited assets pool\n */\n function forfeitedAssetsPool() external view returns (address);\n\n /**\n * @notice Set the address of the forfeited assets pool.\n * @param forfeitedAssetsPool_ The address of the forfeited assets pool\n */\n function setForfeitedAssetsPool(address forfeitedAssetsPool_) external;\n\n /**\n * @notice Flash swap tokens. Caller must implement the IConsolFlashSwap interface.\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param amount The amount of tokens to swap\n * @param data The data to pass into the callback\n */\n function flashSwap(address inputToken, address outputToken, uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/ISubConsol/ISubConsol.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ISubConsolEvents} from \"./ISubConsolEvents.sol\";\n\n/**\n * @title ISubConsol\n * @author Socks&Flops\n * @notice Interface for the SubConsol contract. This is meant to hold collateral and mint an input into Consol\n */\ninterface ISubConsol is IERC20, ISubConsolEvents {\n /**\n * @notice Get the collateral token\n * @return The address of the collateral token\n */\n function collateral() external view returns (address);\n\n /**\n * @notice Set the yield strategy\n * @param yieldStrategy_ The address of the yield strategy\n */\n function setYieldStrategy(address yieldStrategy_) external;\n\n /**\n * @notice Get the yield strategy\n * @return The address of the yield strategy\n */\n function yieldStrategy() external view returns (address);\n\n /**\n * @notice Deposit collateral into the Consol contract while minting a specified amount of SubConsol\n * @param collateralAmount The amount of collateral to deposit\n * @param mintAmount The amount of SubConsol to mint\n */\n function depositCollateral(uint256 collateralAmount, uint256 mintAmount) external;\n\n /**\n * @notice Withdraw collateral from the Consol contract while burning a specified amount of SubConsol\n * @param to The address to send the collateral to\n * @param collateralAmount The amount of collateral to withdraw\n * @param burnAmount The amount of SubConsol to burn\n */\n function withdrawCollateral(address to, uint256 collateralAmount, uint256 burnAmount) external;\n\n /**\n * @notice Withdraw collateral from the SubConsol contract asynchronously (from the yield strategy if necessary)\n * @param to The address to send the collateral to\n * @param collateralAmount The amount of collateral to withdraw\n * @param burnAmount The amount of SubConsol to burn\n */\n function withdrawCollateralAsync(address to, uint256 collateralAmount, uint256 burnAmount) external;\n\n /**\n * @notice Get the amount of yield in the yield strategy\n * @return The amount of yield in the yield strategy\n */\n function yieldAmount() external view returns (uint256);\n\n /**\n * @notice Deposit collateral into the yield strategy\n * @param collateralAmount The amount of collateral to deposit\n */\n function depositToYieldStrategy(uint256 collateralAmount) external;\n\n /**\n * @notice Withdraw collateral from the yield strategy\n * @param collateralAmount The amount of collateral to withdraw\n */\n function withdrawFromYieldStrategy(uint256 collateralAmount) external;\n}\n"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDX.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVault} from \"../IMultiTokenVault/IMultiTokenVault.sol\";\nimport {IUSDXEvents} from \"./IUSDXEvents.sol\";\nimport {IUSDXErrors} from \"./IUSDXErrors.sol\";\n\n/**\n * @title IUSDX\n * @author SocksNFlops\n * @notice Interface for the USDX contract. A wrapper token for USD-pegged tokens.\n */\ninterface IUSDX is IMultiTokenVault, IUSDXEvents, IUSDXErrors {\n /**\n * @notice Add a supported token to the MultiTokenVault with specified scalar values\n * @param token The address of the token to add\n * @param scalarNumerator The scalar numerator for the token\n * @param scalarDenominator The scalar denominator for the token\n */\n function addSupportedToken(address token, uint256 scalarNumerator, uint256 scalarDenominator) external;\n\n /**\n * @notice Get the scalars for a token\n * @param token The address of the token to get the scalars for\n * @return numerator The numerator for the token\n * @return denominator The denominator for the token\n */\n function tokenScalars(address token) external view returns (uint256 numerator, uint256 denominator);\n\n /**\n * @notice Burn a specified amount of USDX for a proportional amount of each supported token\n * @param amount The amount of USDX to burn\n */\n function burn(uint256 amount) external;\n}\n"},"lib/cash/src/types/orders/OrderRequests.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @notice The base parameters required for a creating a mortgage or expanding the balance sheet of a mortgage\n * @param collateralAmounts The amounts of collateral to borrow against for each origination pool. This will be escrowed in the Consol contract.\n * @param totalPeriods The total number of periods that the mortgage will last\n * @param originationPools The addresses of the origination pools to use\n * @param isCompounding Whether the mortgage is compounding\n * @param expiration The expiration of the mortgage\n */\nstruct BaseRequest {\n uint256[] collateralAmounts;\n uint8 totalPeriods;\n address[] originationPools;\n bool isCompounding;\n uint256 expiration;\n}\n\n/**\n * @notice The parameters required for a creating a mortgage request\n * @param base The base parameters required for a creating a mortgage\n * @param mortgageId The mortgageId of the mortgage NFT to be created\n * @param collateral The address of the collateral token\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param conversionQueues The addresses of the conversion queues to use. Ignored in expansion requests.\n * @param hasPaymentPlan Whether the mortgage is hasPaymentPlan (periodic payment plan vs single payment)\n */\nstruct CreationRequest {\n BaseRequest base;\n string mortgageId;\n address collateral;\n address subConsol;\n address[] conversionQueues;\n bool hasPaymentPlan;\n}\n\n/**\n * @notice The parameters required for a request to expand the balance of a mortgage\n * @param base The base parameters required for a request to expand the balance of a mortgage\n * @param tokenId The tokenId of the mortgage NFT to be expanded\n */\nstruct ExpansionRequest {\n BaseRequest base;\n uint256 tokenId;\n}\n"},"src/interfaces/IWNT.sol":{"content":"pragma solidity >=0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWNT is IERC20 {\n /**\n * @notice Deposit native tokens into the WNT contract\n */\n function deposit() external payable;\n\n /**\n * @notice Withdraw native tokens from the WNT contract\n * @param wad The amount of WNT to withdraw\n */\n function withdraw(uint256 wad) external;\n\n /**\n * @notice Approve a spender to spend a certain amount of WNT\n * @param guy The address of the spender\n * @param wad The amount of WNT to approve\n * @return bool Whether the approval was successful\n */\n function approve(address guy, uint256 wad) external returns (bool);\n}\n"},"lib/cash/src/types/OPoolConfigId.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {OriginationPoolConfig} from \"./OriginationPoolConfig.sol\";\n\ntype OPoolConfigId is bytes32;\n\n/**\n * @title OPoolConfigIdLibrary\n * @author SocksNFlops\n * @notice Library for computing the ID of a origination pool config\n */\nlibrary OPoolConfigIdLibrary {\n /**\n * @dev Returns value equal to keccak256(abi.encode(OPoolConfig))\n * @param oPoolConfig The origination pool config to compute the ID for\n * @return oPoolConfigId The ID of the origination pool config\n */\n function toId(OriginationPoolConfig memory oPoolConfig) internal pure returns (OPoolConfigId oPoolConfigId) {\n return OPoolConfigId.wrap(keccak256(abi.encode(oPoolConfig)));\n }\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolScheduler.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IOriginationPoolSchedulerEvents} from \"./IOriginationPoolSchedulerEvents.sol\";\nimport {IOriginationPoolSchedulerErrors} from \"./IOriginationPoolSchedulerErrors.sol\";\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\n\n/**\n * @notice A record of the last deployment address, epoch, and timestamp for a given origination pool config\n * @param deploymentAddress The address of the last deployment\n * @param epoch The epoch number of the last deployment\n * @param timestamp The timestamp of the last deployment\n */\nstruct LastDeploymentRecord {\n address deploymentAddress;\n uint256 epoch;\n uint256 timestamp;\n}\n\n/**\n * @title Interface for the OriginationPoolFactory contract\n * @author SocksNFlops\n * @notice Interface for the OriginationPoolFactory contract\n */\ninterface IOriginationPoolScheduler is IOriginationPoolSchedulerEvents, IOriginationPoolSchedulerErrors, IPausable {\n /**\n * @notice Set the general manager address\n * @param newGeneralManager The address of the new general manager\n */\n function setGeneralManager(address newGeneralManager) external;\n\n /**\n * @notice Get the general manager address\n * @return The address of the general manager\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Set the admin address that is assigned to the origination pools on deployment\n * @param newOpoolAdmin The address of the new origination pool admin\n */\n function setOpoolAdmin(address newOpoolAdmin) external;\n\n /**\n * @notice Get the admin address that is assigned to the origination pools on deployment\n * @return The address of the origination pool admin\n */\n function oPoolAdmin() external view returns (address);\n\n /**\n * @notice Get the number of origination pool configs\n * @return The number of origination pool configs\n */\n function configLength() external view returns (uint256);\n\n /**\n * @notice Get the origination pool config ID at the given index\n * @param index The index of the origination pool config to get the ID for\n * @return oPoolConfigId The ID of the origination pool config\n */\n function configIdAt(uint256 index) external view returns (OPoolConfigId oPoolConfigId);\n\n /**\n * @notice Get the origination pool config at the given index\n * @param index The index of the origination pool config to get\n * @return config The origination pool config\n */\n function configAt(uint256 index) external view returns (OriginationPoolConfig memory);\n\n /**\n * @notice Get the last deployment address from the given config index\n * @param index The index of the origination pool config to get the last deployment address from\n * @return lastDeploymentRecord The last deployment record\n */\n function lastConfigDeployment(uint256 index) external view returns (LastDeploymentRecord memory lastDeploymentRecord);\n\n /**\n * @notice Get the last deployment address from the given config ID\n * @param oPoolConfigId The ID of the origination pool config to get the last deployment address from\n * @return lastDeploymentRecord The last deployment record\n */\n function lastConfigDeployment(OPoolConfigId oPoolConfigId)\n external\n view\n returns (LastDeploymentRecord memory lastDeploymentRecord);\n\n /**\n * @notice Add a new origination pool config\n * @param config The origination pool config to add\n */\n function addConfig(OriginationPoolConfig memory config) external;\n\n /**\n * @notice Remove an origination pool config\n * @param config The origination pool config to remove\n */\n function removeConfig(OriginationPoolConfig memory config) external;\n\n /**\n * @notice Get the current epoch. Indexed from 1\n * @return currentEpoch The current epoch\n */\n function currentEpoch() external view returns (uint256);\n\n /**\n * @notice Deploy a new origination pool\n * @param oPoolConfigId The ID of the origination pool config to deploy\n * @return deploymentAddress The address of the deployed origination pool\n */\n function deployOriginationPool(OPoolConfigId oPoolConfigId) external returns (address deploymentAddress);\n\n /**\n * @notice Predict the origination pool address for the given config ID and current epoch. If already deployed, will return the already deployed address.\n * @param oPoolConfigId The ID of the origination pool config to predict the address for\n * @return deploymentAddress The predicted deployment address\n */\n function predictOriginationPool(OPoolConfigId oPoolConfigId) external view returns (address deploymentAddress);\n\n /**\n * @notice Check if an origination pool is registered (deployed by the scheduler)\n * @param originationPool The address of the origination pool to check\n * @return registered Whether the origination pool is registered\n */\n function isRegistered(address originationPool) external view returns (bool registered);\n\n /**\n * @notice Update the registration of an origination pool\n * @param originationPool The address of the origination pool to update the registration for\n * @param registered Whether the origination pool is registered\n */\n function updateRegistration(address originationPool, bool registered) external;\n}\n"},"src/interfaces/IRouter/IRouter.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {CreationRequest} from \"@core/types/orders/OrderRequests.sol\";\nimport {OPoolConfigId} from \"@core/types/OPoolConfigId.sol\";\nimport {IRouterErrors} from \"./IRouterErrors.sol\";\n\n/**\n * @title IRouter\n * @author @SocksNFlops\n * @notice Interface for the Router contract meant to facilitate user interactions with core contracts of the Cash protocol.\n */\ninterface IRouter is IRouterErrors {\n /**\n * @notice The address of the general manager contract\n * @return The address of the general manager contract\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice The address of the rollover vault contract\n * @return The address of the rollover vault contract\n */\n function rolloverVault() external view returns (address);\n\n /**\n * @notice The address of the fulfillment vault contract\n * @return The address of the fulfillment vault contract\n */\n function fulfillmentVault() external view returns (address);\n\n /**\n * @notice The address of the Pyth contract\n * @return The address of the Pyth contract\n */\n function pyth() external view returns (address);\n\n /**\n * @notice The address of the wrapped native token\n * @return The address of the wrapped native token\n */\n function wrappedNativeToken() external view returns (address);\n\n /**\n * @notice The address of the USDX token contract\n * @return The address of the USDX token contract\n */\n function usdx() external view returns (address);\n\n /**\n * @notice The address of the Consol token contract\n * @return The address of the Consol token contract\n */\n function consol() external view returns (address);\n\n /**\n * @notice The address of the origination pool scheduler contract\n * @return The address of the origination pool scheduler contract\n */\n function originationPoolScheduler() external view returns (address);\n\n /**\n * @notice Approve all the collaterals to be spent by the general manager\n */\n function approveCollaterals() external;\n\n /**\n * @notice Approve all the usdTokens to be spent by the USDX contract (for depositing into USDX)\n */\n function approveUsdTokens() external;\n\n /**\n * @notice Calculates the amounts that will be collected from the borrower for a given creation request before sending the request to the general manager\n * @param creationRequest The creation request\n * @return collateralCollected The amount of collateral that will be collected from the borrower\n * @return usdxCollected The amount of USDX that will be collected from the borrower\n * @return paymentAmount The amount of USDX that will be paid to the fulfilller\n * @return collateralDecimals The decimals of the collateral token\n */\n function calculateCollectedAmounts(CreationRequest calldata creationRequest)\n external\n view\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Request a mortgage\n * @param usdToken The address of the usdToken to pull in\n * @param creationRequest The creation request\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n * @param maxCollected The maximum amount that can be collected from the borrower (in USDX if non-compounding, in collateral if compounding)\n * @return collateralCollected The amount of collateral collected\n * @return usdxCollected The amount of USDX collected\n * @return paymentAmount The amount of payment to be made\n * @return collateralDecimals The decimals of the collateral\n */\n function requestMortgage(\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n external\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Request a mortgage\n * @param priceUpdates The price updates to send to the Pyth contract\n * @param usdToken The address of the usdToken to pull in\n * @param creationRequest The creation request\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n * @param maxCollected The maximum amount that can be collected from the borrower (in USDX if non-compounding, in collateral if compounding)\n * @return collateralCollected The amount of collateral collected\n * @return usdxCollected The amount of USDX collected\n * @return paymentAmount The amount of payment to be made\n * @return collateralDecimals The decimals of the collateral\n */\n function updatePriceFeedsAndRequestMortgage(\n bytes[] calldata priceUpdates,\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n external\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Make a periodic payment on a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID\n * @param inputAmount The amount of input token to pull in\n */\n function periodPay(address inputToken, uint256 tokenId, uint256 inputAmount) external;\n\n /**\n * @notice Make a penalty payment on a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID\n * @param inputAmount The amount of input token to pull in\n */\n function penaltyPay(address inputToken, uint256 tokenId, uint256 inputAmount) external;\n\n /**\n * @notice Refinance a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID of the mortgage to refinance\n * @param newTotalPeriods The new total periods of the mortgage\n */\n function refinance(address inputToken, uint256 tokenId, uint8 newTotalPeriods) external;\n\n /**\n * @notice Deposit into an origination pool\n * @param oPoolConfigId The OPoolConfigId of the origination pool to deposit into\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function originationPoolDeposit(OPoolConfigId oPoolConfigId, address usdToken, uint256 usdTokenAmount) external;\n\n /**\n * @notice Quotes the amount of output token that would be received for a given amount of input token\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param inputAmount The amount of input token to convert\n * @return outputAmount The amount of output token received\n */\n function convert(address inputToken, address outputToken, uint256 inputAmount)\n external\n view\n returns (uint256 outputAmount);\n\n /**\n * @notice Wraps tokens from usdToken -> usdx -> consol\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param inputAmount The amount of input token to convert\n */\n function wrap(address inputToken, address outputToken, uint256 inputAmount) external;\n\n /**\n * @notice Deposit into the rollover vault\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function rolloverVaultDeposit(address usdToken, uint256 usdTokenAmount) external;\n\n /**\n * @notice Deposit into the fulfillment vault\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function fulfillmentVaultDeposit(address usdToken, uint256 usdTokenAmount) external;\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFT.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IMortgageNFTEvents} from \"./IMortgageNFTEvents.sol\";\nimport {IMortgageNFTErrors} from \"./IMortgageNFTErrors.sol\";\n\n/**\n * @title IMortgageNFT\n * @author Socks&Flops\n * @notice The interface for the MortgageNFT contract, a non-fungible token that represents ownership of a mortgage position in LoanManager\n */\ninterface IMortgageNFT is IERC721, IMortgageNFTEvents, IMortgageNFTErrors {\n /**\n * @notice Returns the general manager address\n * @return The general manager address\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Returns the NFT metadata generator address\n * @return The NFT metadata generator address\n */\n function nftMetadataGenerator() external view returns (address);\n\n /**\n * @notice Mints a mortgage NFT. Only callable by the loan manager.\n * @param to The address to mint the mortgage NFT to\n * @param mortgageId The string identifier of the mortage position\n * @return tokenId The tokenId of the newly minted mortgage NFT\n */\n function mint(address to, string memory mortgageId) external returns (uint256 tokenId);\n\n /**\n * @notice Burns a mortgage NFT. Only callable by the loan manager.\n * @param tokenId The ID of the mortgage NFT to burn\n */\n function burn(uint256 tokenId) external;\n\n /**\n * @notice Returns the mortgageId for a given tokenID\n * @param tokenId The tokenId to get the mortgageId for\n * @return mortgageId The corresponding mortgageId\n */\n function getMortgageId(uint256 tokenId) external view returns (string memory mortgageId);\n\n /**\n * @notice Returns the tokenId for a given mortgageId\n * @param mortgageId The mortgageId to get the tokenId for\n * @return tokenId The coresponding tokenId\n */\n function getTokenId(string memory mortgageId) external view returns (uint256 tokenId);\n\n /**\n * @notice Returns the owner of a given mortgage ID\n * @param mortgageId The mortgage ID to get the owner for\n * @return owner The owner of the mortgage ID\n */\n function ownerOf(string memory mortgageId) external view returns (address owner);\n\n /**\n * @notice Returns the last tokenId created\n * @return lastTokenIdCreated The last tokenId created\n */\n function lastTokenIdCreated() external view returns (uint256);\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFTErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IMortgageNFTErrors\n * @author Socks&Flops\n */\ninterface IMortgageNFTErrors {\n /**\n * @notice Emitted when a mortgageId is already taken\n * @param tokenId The ID of the mortgage NFT with the taken mortgageId\n * @param mortgageId The mortageId of the mortgage\n */\n error MortgageIdAlreadyTaken(uint256 tokenId, string mortgageId);\n\n /**\n * @notice Emitted when a non-owner attempts to update a mortgageId\n * @param owner The owner of the mortgage NFT\n * @param caller The caller of the function\n */\n error OnlyOwner(address owner, address caller);\n\n /**\n * @notice Emitted when a non-general manager attempts to update a mortgage NFT\n * @param generalManager The general manager address\n * @param caller The caller of the function\n */\n error OnlyGeneralManager(address generalManager, address caller);\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Floor, // Toward negative infinity\n Ceil, // Toward positive infinity\n Trunc, // Toward zero\n Expand // Away from zero\n }\n\n /**\n * @dev Return the 512-bit addition of two uint256.\n *\n * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n */\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n assembly (\"memory-safe\") {\n low := add(a, b)\n high := lt(low, a)\n }\n }\n\n /**\n * @dev Return the 512-bit multiplication of two uint256.\n *\n * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n */\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = high * 2²⁵⁶ + low.\n assembly (\"memory-safe\") {\n let mm := mulmod(a, b, not(0))\n low := mul(a, b)\n high := sub(sub(mm, low), lt(mm, low))\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a + b;\n success = c >= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a - b;\n success = c <= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a * b;\n assembly (\"memory-safe\") {\n // Only true when the multiplication doesn't overflow\n // (c / a == b) || (a == 0)\n success := or(eq(div(c, a), b), iszero(a))\n }\n // equivalent to: success ? c : 0\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `DIV` opcode returns zero when the denominator is 0.\n result := div(a, b)\n }\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `MOD` opcode returns zero when the denominator is 0.\n result := mod(a, b)\n }\n }\n }\n\n /**\n * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryAdd(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n */\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n (, uint256 result) = trySub(a, b);\n return result;\n }\n\n /**\n * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryMul(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\n }\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a > b, a, b);\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a < b, a, b);\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds towards infinity instead\n * of rounding towards zero.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n if (b == 0) {\n // Guarantee the same behavior as in a regular Solidity division.\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n\n // The following calculation ensures accurate ceiling division without overflow.\n // Since a is non-zero, (a - 1) / b will not overflow.\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n // but the largest value we can obtain is type(uint256).max - 1, which happens\n // when a = type(uint256).max and b = 1.\n unchecked {\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n }\n }\n\n /**\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n * denominator == 0.\n *\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n * Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n\n // Handle non-overflow cases, 256 by 256 division.\n if (high == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return low / denominator;\n }\n\n // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n if (denominator <= high) {\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [high low].\n uint256 remainder;\n assembly (\"memory-safe\") {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n high := sub(high, gt(remainder, low))\n low := sub(low, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n uint256 twos = denominator & (0 - denominator);\n assembly (\"memory-safe\") {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [high low] by twos.\n low := div(low, twos)\n\n // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from high into low.\n low |= high * twos;\n\n // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n // works in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n inverse *= 2 - denominator * inverse; // inverse mod 2³²\n inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n // is no longer required.\n result = low * inverse;\n return result;\n }\n }\n\n /**\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n }\n\n /**\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n */\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n if (high >= 1 << n) {\n Panic.panic(Panic.UNDER_OVERFLOW);\n }\n return (high << (256 - n)) | (low >> n);\n }\n }\n\n /**\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n */\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n }\n\n /**\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n *\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n *\n * If the input value is not inversible, 0 is returned.\n *\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n */\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n unchecked {\n if (n == 0) return 0;\n\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n // ax + ny = 1\n // ax = 1 + (-y)n\n // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n // If the remainder is 0 the gcd is n right away.\n uint256 remainder = a % n;\n uint256 gcd = n;\n\n // Therefore the initial coefficients are:\n // ax + ny = gcd(a, n) = n\n // 0a + 1n = n\n int256 x = 0;\n int256 y = 1;\n\n while (remainder != 0) {\n uint256 quotient = gcd / remainder;\n\n (gcd, remainder) = (\n // The old remainder is the next gcd to try.\n remainder,\n // Compute the next remainder.\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n // where gcd is at most n (capped to type(uint256).max)\n gcd - remainder * quotient\n );\n\n (x, y) = (\n // Increment the coefficient of a.\n y,\n // Decrement the coefficient of n.\n // Can overflow, but the result is casted to uint256 so that the\n // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n x - y * int256(quotient)\n );\n }\n\n if (gcd != 1) return 0; // No inverse exists.\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n }\n }\n\n /**\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n *\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n *\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n */\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n unchecked {\n return Math.modExp(a, p - 2, p);\n }\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n *\n * Requirements:\n * - modulus can't be zero\n * - underlying staticcall to precompile must succeed\n *\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n * interpreted as 0.\n */\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n (bool success, uint256 result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n * to operate modulo 0 or if the underlying precompile reverted.\n *\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n * of a revert, but the result may be incorrectly interpreted as 0.\n */\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n if (m == 0) return (false, 0);\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n // | Offset | Content | Content (Hex) |\n // |-----------|------------|--------------------------------------------------------------------|\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n mstore(ptr, 0x20)\n mstore(add(ptr, 0x20), 0x20)\n mstore(add(ptr, 0x40), 0x20)\n mstore(add(ptr, 0x60), b)\n mstore(add(ptr, 0x80), e)\n mstore(add(ptr, 0xa0), m)\n\n // Given the result < m, it's guaranteed to fit in 32 bytes,\n // so we can use the memory scratch space located at offset 0.\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n result := mload(0x00)\n }\n }\n\n /**\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\n */\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n (bool success, bytes memory result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n */\n function tryModExp(\n bytes memory b,\n bytes memory e,\n bytes memory m\n ) internal view returns (bool success, bytes memory result) {\n if (_zeroBytes(m)) return (false, new bytes(0));\n\n uint256 mLen = m.length;\n\n // Encode call args in result and move the free memory pointer\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n assembly (\"memory-safe\") {\n let dataPtr := add(result, 0x20)\n // Write result on top of args to avoid allocating extra memory.\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n // Overwrite the length.\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n mstore(result, mLen)\n // Set the memory pointer after the returned data.\n mstore(0x40, add(dataPtr, mLen))\n }\n }\n\n /**\n * @dev Returns whether the provided byte array is zero.\n */\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n for (uint256 i = 0; i < byteArray.length; ++i) {\n if (byteArray[i] != 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n * towards zero.\n *\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n * using integer operations.\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n unchecked {\n // Take care of easy edge cases when a == 0 or a == 1\n if (a <= 1) {\n return a;\n }\n\n // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n // the current value as `ε_n = | x_n - sqrt(a) |`.\n //\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n // bigger than any uint256.\n //\n // By noticing that\n // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n // to the msb function.\n uint256 aa = a;\n uint256 xn = 1;\n\n if (aa >= (1 << 128)) {\n aa >>= 128;\n xn <<= 64;\n }\n if (aa >= (1 << 64)) {\n aa >>= 64;\n xn <<= 32;\n }\n if (aa >= (1 << 32)) {\n aa >>= 32;\n xn <<= 16;\n }\n if (aa >= (1 << 16)) {\n aa >>= 16;\n xn <<= 8;\n }\n if (aa >= (1 << 8)) {\n aa >>= 8;\n xn <<= 4;\n }\n if (aa >= (1 << 4)) {\n aa >>= 4;\n xn <<= 2;\n }\n if (aa >= (1 << 2)) {\n xn <<= 1;\n }\n\n // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n //\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n // This is going to be our x_0 (and ε_0)\n xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n // From here, Newton's method give us:\n // x_{n+1} = (x_n + a / x_n) / 2\n //\n // One should note that:\n // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n // = ((x_n² + a) / (2 * x_n))² - a\n // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n // = (x_n² - a)² / (2 * x_n)²\n // = ((x_n² - a) / (2 * x_n))²\n // ≥ 0\n // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n //\n // This gives us the proof of quadratic convergence of the sequence:\n // ε_{n+1} = | x_{n+1} - sqrt(a) |\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\n // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n // = | (x_n - sqrt(a))² / (2 * x_n) |\n // = | ε_n² / (2 * x_n) |\n // = ε_n² / | (2 * x_n) |\n //\n // For the first iteration, we have a special case where x_0 is known:\n // ε_1 = ε_0² / | (2 * x_0) |\n // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n // ≤ 2**(2*e-4) / (3 * 2**(e-1))\n // ≤ 2**(e-3) / 3\n // ≤ 2**(e-3-log2(3))\n // ≤ 2**(e-4.5)\n //\n // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n // ε_{n+1} = ε_n² / | (2 * x_n) |\n // ≤ (2**(e-k))² / (2 * 2**(e-1))\n // ≤ 2**(2*e-2*k) / 2**e\n // ≤ 2**(e-2*k)\n xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above\n xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5\n xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9\n xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18\n xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36\n xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72\n\n // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n // sqrt(a) or sqrt(a) + 1.\n return xn - SafeCast.toUint(xn > a / xn);\n }\n }\n\n /**\n * @dev Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n }\n }\n\n /**\n * @dev Return the log in base 2 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log2(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // If upper 8 bits of 16-bit half set, add 8 to result\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n // If upper 4 bits of 8-bit half set, add 4 to result\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n // Shifts value right by the current result and use it as an index into this lookup table:\n //\n // | x (4 bits) | index | table[index] = MSB position |\n // |------------|---------|-----------------------------|\n // | 0000 | 0 | table[0] = 0 |\n // | 0001 | 1 | table[1] = 0 |\n // | 0010 | 2 | table[2] = 1 |\n // | 0011 | 3 | table[3] = 1 |\n // | 0100 | 4 | table[4] = 2 |\n // | 0101 | 5 | table[5] = 2 |\n // | 0110 | 6 | table[6] = 2 |\n // | 0111 | 7 | table[7] = 2 |\n // | 1000 | 8 | table[8] = 3 |\n // | 1001 | 9 | table[9] = 3 |\n // | 1010 | 10 | table[10] = 3 |\n // | 1011 | 11 | table[11] = 3 |\n // | 1100 | 12 | table[12] = 3 |\n // | 1101 | 13 | table[13] = 3 |\n // | 1110 | 14 | table[14] = 3 |\n // | 1111 | 15 | table[15] = 3 |\n //\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n assembly (\"memory-safe\") {\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n }\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n }\n }\n\n /**\n * @dev Return the log in base 10 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n }\n }\n\n /**\n * @dev Return the log in base 256 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n }\n }\n\n /**\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n */\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n return uint8(rounding) % 2 == 1;\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/IPyth.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"./PythStructs.sol\";\nimport \"./IPythEvents.sol\";\n\n/// @title Consume prices from the Pyth Network (https://pyth.network/).\n/// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely.\n/// @author Pyth Data Association\ninterface IPyth is IPythEvents {\n /// @notice Returns the price of a price feed without any sanity checks.\n /// @dev This function returns the most recent price update in this contract without any recency checks.\n /// This function is unsafe as the returned price update may be arbitrarily far in the past.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use `getPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the price that is no older than `age` seconds of the current time.\n /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.\n /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.\n /// However, if the price is not recent this function returns the latest available price.\n ///\n /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that\n /// the returned price is recent or useful for any particular application.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds\n /// of the current time.\n /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Update price feeds with given update messages.\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n /// Prices will be updated if they are more recent than the current stored prices.\n /// The call will succeed even if the update is not the most recent.\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n function updatePriceFeeds(bytes[] calldata updateData) external payable;\n\n /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is\n /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the\n /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime\n /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have\n /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.\n /// Otherwise, it calls updatePriceFeeds method to update the prices.\n ///\n /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`\n function updatePriceFeedsIfNecessary(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64[] calldata publishTimes\n ) external payable;\n\n /// @notice Returns the required fee to update an array of price updates.\n /// @param updateData Array of price update data.\n /// @return feeAmount The required fee in Wei.\n function getUpdateFee(\n bytes[] calldata updateData\n ) external view returns (uint feeAmount);\n\n /// @notice Returns the required fee to update a TWAP price.\n /// @param updateData Array of price update data.\n /// @return feeAmount The required fee in Wei.\n function getTwapUpdateFee(\n bytes[] calldata updateData\n ) external view returns (uint feeAmount);\n\n /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published\n /// within `minPublishTime` and `maxPublishTime`.\n ///\n /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;\n /// otherwise, please consider using `updatePriceFeeds`. This method will not store the price updates on-chain.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdates(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minPublishTime,\n uint64 maxPublishTime\n ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);\n\n /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published\n /// within `minPublishTime` and `maxPublishTime,` but choose to store price updates if `storeUpdatesIfFresh`.\n ///\n /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;\n /// otherwise, please consider using `updatePriceFeeds`. This method may store the price updates on-chain, if they\n /// are more recent than the current stored prices.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n /// This method will eventually allow the caller to determine whether parsed price feeds should update\n /// the stored values as well.\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minAllowedPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxAllowedPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @param storeUpdatesIfFresh flag for the parse function to\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdatesWithConfig(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minAllowedPublishTime,\n uint64 maxAllowedPublishTime,\n bool checkUniqueness,\n bool checkUpdateDataIsMinimal,\n bool storeUpdatesIfFresh\n )\n external\n payable\n returns (\n PythStructs.PriceFeed[] memory priceFeeds,\n uint64[] memory slots\n );\n\n /// @notice Parse time-weighted average price (TWAP) from two consecutive price updates for the given `priceIds`.\n ///\n /// This method calculates TWAP between two data points by processing the difference in cumulative price values\n /// divided by the time period. It requires exactly two updates that contain valid price information\n /// for all the requested price IDs.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the updateData array.\n ///\n /// @dev Reverts if:\n /// - The transferred fee is not sufficient\n /// - The updateData is invalid or malformed\n /// - The updateData array does not contain exactly 2 updates\n /// - There is no update for any of the given `priceIds`\n /// - The time ordering between data points is invalid (start time must be before end time)\n /// @param updateData Array containing exactly two price updates (start and end points for TWAP calculation)\n /// @param priceIds Array of price ids to calculate TWAP for\n /// @return twapPriceFeeds Array of TWAP price feeds corresponding to the given `priceIds` (with the same order)\n function parseTwapPriceFeedUpdates(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds\n )\n external\n payable\n returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds);\n\n /// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are\n /// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,\n /// this method will return the first update. This method may store the price updates on-chain, if they\n /// are more recent than the current stored prices.\n ///\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range and uniqueness condition.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdatesUnique(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minPublishTime,\n uint64 maxPublishTime\n ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/PythErrors.sol":{"content":"// SPDX-License-Identifier: Apache 2\n\npragma solidity ^0.8.0;\n\nlibrary PythErrors {\n // Function arguments are invalid (e.g., the arguments lengths mismatch)\n // Signature: 0xa9cb9e0d\n error InvalidArgument();\n // Update data is coming from an invalid data source.\n // Signature: 0xe60dce71\n error InvalidUpdateDataSource();\n // Update data is invalid (e.g., deserialization error)\n // Signature: 0xe69ffece\n error InvalidUpdateData();\n // Insufficient fee is paid to the method.\n // Signature: 0x025dbdd4\n error InsufficientFee();\n // There is no fresh update, whereas expected fresh updates.\n // Signature: 0xde2c57fa\n error NoFreshUpdate();\n // There is no price feed found within the given range or it does not exists.\n // Signature: 0x45805f5d\n error PriceFeedNotFoundWithinRange();\n // Price feed not found or it is not pushed on-chain yet.\n // Signature: 0x14aebe68\n error PriceFeedNotFound();\n // Requested price is stale.\n // Signature: 0x19abf40e\n error StalePrice();\n // Given message is not a valid Wormhole VAA.\n // Signature: 0x2acbe915\n error InvalidWormholeVaa();\n // Governance message is invalid (e.g., deserialization error).\n // Signature: 0x97363b35\n error InvalidGovernanceMessage();\n // Governance message is not for this contract.\n // Signature: 0x63daeb77\n error InvalidGovernanceTarget();\n // Governance message is coming from an invalid data source.\n // Signature: 0x360f2d87\n error InvalidGovernanceDataSource();\n // Governance message is old.\n // Signature: 0x88d1b847\n error OldGovernanceMessage();\n // The wormhole address to set in SetWormholeAddress governance is invalid.\n // Signature: 0x13d3ed82\n error InvalidWormholeAddressToSet();\n // The twap update data is invalid.\n error InvalidTwapUpdateData();\n // The twap update data set is invalid.\n error InvalidTwapUpdateDataSet();\n // The Input Price is negative.\n error NegativeInputPrice();\n // The Input Exponent is invalid.\n error InvalidInputExpo();\n // The combined price is greater than int64.max.\n error CombinedPriceOverflow();\n // The exponent is greater than 77 or less than -77.\n error ExponentOverflow();\n}\n"},"lib/cash/src/libraries/MortgageMath.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {MortgagePosition, MortgageStatus} from \"../types/MortgagePosition.sol\";\nimport {Constants} from \"./Constants.sol\";\n\n/**\n * @title MortgageMath\n * @author SocksNFlops\n * @notice Library for running operations on MortgagePositions\n */\nlibrary MortgageMath {\n using MortgageMath for MortgagePosition;\n\n /**\n * @notice Thrown when a periodPay, penaltyPay, or refinance amount is zero\n * @param mortgage The mortgage position\n */\n error ZeroAmount(MortgagePosition mortgage);\n /**\n * @notice Thrown when a payment is greater than the termBalance\n * @param mortgage The mortgage position\n * @param amount The amount of the payment\n */\n error CannotOverpay(MortgagePosition mortgage, uint256 amount);\n /**\n * @notice Thrown when a mortgage position has unpaid penalties that need to be settled\n * @param mortgage The mortgage position\n */\n error UnpaidPenalties(MortgagePosition mortgage);\n /**\n * @notice Thrown when a penalty payment is greater than the penalty accrued\n * @param mortgage The mortgage position\n * @param amount The amount of the penalty\n */\n error CannotOverpayPenalty(MortgagePosition mortgage, uint256 amount);\n /**\n * @notice Thrown when a mortgage position has unpaid payments that need to be settled\n * @param mortgage The mortgage position\n */\n error UnpaidPayments(MortgagePosition mortgage);\n /**\n * @notice Thrown when a mortgage position has missed payments that need to be settled\n * @param mortgage The mortgage position\n */\n error MissedPayments(MortgagePosition mortgage);\n /**\n * @notice Thrown when a mortgage position is not foreclosable\n * @param mortgage The mortgage position\n * @param maxMissedPayments The maximum number of missed payments\n */\n error NotForeclosable(MortgagePosition mortgage, uint8 maxMissedPayments);\n /**\n * @notice Thrown when the conversion trigger price is not met\n * @param mortgage The mortgage position\n * @param currentPrice The current price of the collateral\n */\n error ConversionTriggerPriceNotMet(MortgagePosition mortgage, uint256 currentPrice);\n /**\n * @notice Thrown when a mortgage position is not convertible\n * @param mortgage The mortgage position\n * @param amountConverting The amount of principal being converted\n * @param collateralConverting The amount of collateral being converted\n */\n error CannotOverConvert(MortgagePosition mortgage, uint256 amountConverting, uint256 collateralConverting);\n /**\n * @notice Thrown when a mortgage position is not partially prepayable (i.e., does not have a payment plan) and the payment is less than the termBalance\n * @param mortgage The mortgage position\n */\n error CannotPartialPrepay(MortgagePosition mortgage);\n\n /**\n * @dev Copies a mortgage position\n * @param mortgagePosition The mortgage position to copy\n * @return The copied mortgage position\n */\n function copy(MortgagePosition memory mortgagePosition) internal pure returns (MortgagePosition memory) {\n return MortgagePosition({\n tokenId: mortgagePosition.tokenId,\n collateral: mortgagePosition.collateral,\n collateralDecimals: mortgagePosition.collateralDecimals,\n collateralAmount: mortgagePosition.collateralAmount,\n collateralConverted: mortgagePosition.collateralConverted,\n subConsol: mortgagePosition.subConsol,\n interestRate: mortgagePosition.interestRate,\n conversionPremiumRate: mortgagePosition.conversionPremiumRate,\n dateOriginated: mortgagePosition.dateOriginated,\n termOriginated: mortgagePosition.termOriginated,\n termBalance: mortgagePosition.termBalance,\n amountBorrowed: mortgagePosition.amountBorrowed,\n amountPrior: mortgagePosition.amountPrior,\n termPaid: mortgagePosition.termPaid,\n termConverted: mortgagePosition.termConverted,\n amountConverted: mortgagePosition.amountConverted,\n penaltyAccrued: mortgagePosition.penaltyAccrued,\n penaltyPaid: mortgagePosition.penaltyPaid,\n paymentsMissed: mortgagePosition.paymentsMissed,\n totalPeriods: mortgagePosition.totalPeriods,\n status: mortgagePosition.status,\n hasPaymentPlan: mortgagePosition.hasPaymentPlan\n });\n }\n\n /**\n * @dev Evaluates if two mortgage positions are equal\n * @param mortgagePosition The mortgage position to evaluate\n * @param other The other mortgage position to evaluate\n * @return True if the mortgage positions are equal, false otherwise\n */\n function equals(MortgagePosition memory mortgagePosition, MortgagePosition memory other)\n internal\n pure\n returns (bool)\n {\n return (mortgagePosition.tokenId == other.tokenId && mortgagePosition.collateral == other.collateral\n && mortgagePosition.collateralDecimals == other.collateralDecimals\n && mortgagePosition.collateralAmount == other.collateralAmount\n && mortgagePosition.collateralConverted == other.collateralConverted\n && mortgagePosition.subConsol == other.subConsol && mortgagePosition.interestRate == other.interestRate\n && mortgagePosition.conversionPremiumRate == other.conversionPremiumRate\n && mortgagePosition.dateOriginated == other.dateOriginated\n && mortgagePosition.termOriginated == other.termOriginated && mortgagePosition.termBalance == other.termBalance\n && mortgagePosition.amountBorrowed == other.amountBorrowed && mortgagePosition.amountPrior == other.amountPrior\n && mortgagePosition.termPaid == other.termPaid && mortgagePosition.termConverted == other.termConverted\n && mortgagePosition.amountConverted == other.amountConverted\n && mortgagePosition.penaltyAccrued == other.penaltyAccrued && mortgagePosition.penaltyPaid == other.penaltyPaid\n && mortgagePosition.paymentsMissed == other.paymentsMissed\n && mortgagePosition.totalPeriods == other.totalPeriods && mortgagePosition.status == other.status\n && mortgagePosition.hasPaymentPlan == other.hasPaymentPlan);\n }\n\n /**\n * @dev Converts a payment amount to the principal amount being paid off\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @return The principal amount of the payment\n */\n function convertPaymentToPrincipal(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n if (mortgagePosition.termBalance == 0) {\n return 0;\n }\n return Math.mulDiv(\n amount,\n mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior,\n mortgagePosition.termBalance,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the delta in principal created from a payment\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @return The principal delta created\n */\n function calculatePrincipalDelta(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n return mortgagePosition.convertPaymentToPrincipal(\n mortgagePosition.termPaid + mortgagePosition.termConverted + amount\n ) - mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid + mortgagePosition.termConverted);\n }\n\n /**\n * @dev Converts a principal amount to the total debt being paid\n * @param mortgagePosition The mortgage position\n * @param amount The amount of principal\n * @return The payment amount\n */\n function convertPrincipalToPayment(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n if (mortgagePosition.termBalance == 0) {\n return 0;\n }\n return Math.mulDiv(\n amount,\n mortgagePosition.termBalance,\n mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior,\n Math.Rounding.Ceil\n );\n }\n\n /**\n * @dev Defined as the amount of principal that is left to be repaid (not including interest)\n * @param mortgagePosition The mortgage position\n * @return The amount of principal that is left to be repaid\n */\n function principalRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior\n - mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid + mortgagePosition.termConverted);\n }\n\n /**\n * @dev Defined as the amount of debt left to be repaid in the current term (includes interest)\n * @param mortgagePosition The mortgage position\n * @return The amount of debt that is left to be repaid\n */\n function termRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.termBalance - mortgagePosition.termConverted - mortgagePosition.termPaid;\n }\n\n /**\n * @dev Defined as the amount of collateral left to be converted\n * @param mortgagePosition The mortgage position\n * @return The amount of collateral that is left to be converted\n */\n function collateralRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.collateralAmount - mortgagePosition.collateralConverted;\n }\n\n /**\n * @dev Calculates the term balance of a mortgage position using the simple interest formula\n * @dev termBalance = debt * (1 + interestRate * number of years)\n * @dev termBalance = debt * (BPS + interestBPS * number of years) / BPS\n * @dev termBalance = debt * (BPS * PERIODS_PER_YEAR + interestBPS * totalPeriods) / (BPS * PERIODS_PER_YEAR)\n * @param principal The principal amount of the mortgage\n * @param interestRate The interest rate of the mortgage\n * @param totalPeriods The total number of periods of the mortgage\n * @param periodsLeft The number of periods left to be paid\n * @return termBalance The term balance of the mortgage position\n */\n function calculateTermBalance(uint256 principal, uint256 interestRate, uint8 totalPeriods, uint8 periodsLeft)\n internal\n pure\n returns (uint256 termBalance)\n {\n // Apply simple interest formula to calculate the total owed\n termBalance = Math.mulDiv(\n principal,\n Constants.BPS * Constants.PERIODS_PER_YEAR + (interestRate * totalPeriods),\n (Constants.BPS * Constants.PERIODS_PER_YEAR),\n Math.Rounding.Floor\n );\n // Round it up so that the termBalance is a multiple of the periodsLeft (each month has the same payment)\n termBalance += (periodsLeft - (termBalance % periodsLeft)) % periodsLeft;\n }\n\n /**\n * @dev Calculates the monthly payment of a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The monthly payment\n */\n function monthlyPayment(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n // If the mortgage does not have a payment plan, the mortgage is paid in full at the end of the term\n if (!mortgagePosition.hasPaymentPlan) {\n return 0;\n }\n // Otherwise, calculate the monthly payment\n return mortgagePosition.termBalance / mortgagePosition.totalPeriods;\n }\n\n /**\n * @dev Calculates the purchase price of a mortgage position by dividing the amount borrowed by the collateral amount\n * @param mortgagePosition The mortgage position\n * @return The purchase price\n */\n function purchasePrice(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return Math.mulDiv(\n mortgagePosition.amountBorrowed,\n 2 * (10 ** mortgagePosition.collateralDecimals),\n mortgagePosition.collateralAmount,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the price at which the collateral must be in order for the mortgage position to be convertible\n * @param mortgagePosition The mortgage position\n * @return The price at which the collateral must be in order for the mortgage position to be convertible\n */\n function conversionTriggerPrice(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return Math.mulDiv(\n (Constants.BPS + mortgagePosition.conversionPremiumRate) * mortgagePosition.amountBorrowed,\n 2 * (10 ** mortgagePosition.collateralDecimals),\n Constants.BPS * mortgagePosition.collateralAmount,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the amount of principal that has been forfeited after a foreclosure. Returns 0 if the mortgage position is not foreclosed.\n * @param mortgagePosition The mortgage position\n * @return The amount of principal that has been forfeited\n */\n function amountForfeited(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n if (mortgagePosition.status != MortgageStatus.FORECLOSED) {\n return 0;\n }\n return mortgagePosition.amountPrior + mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid);\n }\n\n /**\n * @dev Creates a new mortgage position\n * @param tokenId The token ID of the mortgage position\n * @param collateral The address of the collateral\n * @param collateralDecimals The number of decimals of the collateral\n * @param subConsol The address of the subConsol\n * @param collateralAmount The amount of collateral\n * @param amountBorrowed The amount of principal borrowed\n * @param interestRate The interest rate of the mortgage\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param totalPeriods The total number of periods of the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The new mortgage position\n */\n function createNewMortgagePosition(\n uint256 tokenId,\n address collateral,\n uint8 collateralDecimals,\n address subConsol,\n uint256 collateralAmount,\n uint256 amountBorrowed,\n uint16 interestRate,\n uint16 conversionPremiumRate,\n uint8 totalPeriods,\n bool hasPaymentPlan\n ) internal view returns (MortgagePosition memory) {\n return MortgagePosition({\n tokenId: tokenId,\n collateral: collateral,\n collateralDecimals: collateralDecimals,\n collateralAmount: collateralAmount,\n collateralConverted: 0,\n subConsol: subConsol,\n interestRate: interestRate,\n conversionPremiumRate: conversionPremiumRate,\n dateOriginated: uint32(block.timestamp),\n termOriginated: uint32(block.timestamp),\n termBalance: calculateTermBalance(amountBorrowed, interestRate, totalPeriods, totalPeriods),\n amountBorrowed: amountBorrowed,\n amountPrior: 0,\n termPaid: 0,\n termConverted: 0,\n amountConverted: 0,\n penaltyAccrued: 0,\n penaltyPaid: 0,\n paymentsMissed: 0,\n totalPeriods: totalPeriods,\n hasPaymentPlan: hasPaymentPlan,\n status: MortgageStatus.ACTIVE\n });\n }\n\n /**\n * @dev Calculates the current number of periods that have been paid for a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The number of periods paid\n */\n function periodsPaid(MortgagePosition memory mortgagePosition) internal pure returns (uint8) {\n // Calculate the number of periods paid based on the fraction of (termPaid+termConverted)/termBalance\n if (mortgagePosition.termBalance == 0) {\n return mortgagePosition.totalPeriods;\n }\n\n return uint8(\n Math.mulDiv(\n mortgagePosition.totalPeriods,\n mortgagePosition.termPaid + mortgagePosition.termConverted,\n mortgagePosition.termBalance,\n Math.Rounding.Floor\n )\n );\n }\n\n /**\n * @dev Updates the mortgage position with a periodic payment\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @return The updated mortgage position and the principal payment\n * @return principalPayment The principal payment\n * @return refund The amount of the refund in the case of overpayment\n */\n function periodPay(MortgagePosition memory mortgagePosition, uint256 amount, uint256 latePenaltyWindow)\n internal\n view\n returns (MortgagePosition memory, uint256 principalPayment, uint256 refund)\n {\n // Revert if the amount is zero\n if (amount == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Ensure that the amount is not greater than the termBalance. Refund the surplus.\n uint256 _termRemaining = mortgagePosition.termRemaining();\n if (_termRemaining == 0 && amount > 0) {\n revert CannotOverpay(mortgagePosition, amount);\n }\n // If the mortgage does not have a payment plan, the mortgage is paid in full at the end of the term\n if (!mortgagePosition.hasPaymentPlan && amount < mortgagePosition.termRemaining()) {\n revert CannotPartialPrepay(mortgagePosition);\n }\n // Calculate the refund and subtract it from the amount\n if (amount > _termRemaining) {\n refund = amount - _termRemaining;\n amount = _termRemaining;\n }\n // Calculate principal payment\n principalPayment = mortgagePosition.calculatePrincipalDelta(amount);\n\n // Update the termPaid\n mortgagePosition.termPaid += amount;\n\n // Make sure paymentsMissed is up to date\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If the mortgage is paid in full, there are no more missed payments since and additional penalties can no longer be applied\n if (_periodsPaid == mortgagePosition.totalPeriods) {\n mortgagePosition.paymentsMissed = 0;\n } else {\n // If the mortgage has a payment plan, the number of missed payments is the difference between the periods since origination and the periods paid\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n mortgagePosition.paymentsMissed =\n _periodsPaid > periodsSinceOrigination ? 0 : periodsSinceOrigination - _periodsPaid;\n }\n\n // Return the updated mortgage position\n return (mortgagePosition, principalPayment, refund);\n }\n\n /**\n * @dev Calculates the number of periods since the term origination\n * @param mortgagePosition The mortgage position\n * @param latePaymentWindow The number of days after the due date that a payment is still considered on time\n * @return periods The number of periods since the term origination\n */\n function periodsSinceTermOrigination(MortgagePosition memory mortgagePosition, uint256 latePaymentWindow)\n internal\n view\n returns (uint8 periods)\n {\n if (mortgagePosition.termOriginated == 0) {\n return 0;\n }\n // Calculate the number of since origination\n periods = uint8((block.timestamp - mortgagePosition.termOriginated) / Constants.PERIOD_DURATION);\n // If the late payment window can impact the number of periods, subtract one\n if (\n periods > 0\n && (block.timestamp - mortgagePosition.termOriginated) % Constants.PERIOD_DURATION <= latePaymentWindow\n ) {\n periods -= 1;\n }\n }\n\n /**\n * @dev Calculates the penalty amount for a mortgage position given a number of additional payments missed and the current penalty rate\n * @param mortgagePosition The mortgage position\n * @param additionalPaymentsMissed The number of additional payments missed\n * @param penaltyRate The penalty rate\n * @return The penalty amount\n */\n function calculatePenaltyAmount(\n MortgagePosition memory mortgagePosition,\n uint8 additionalPaymentsMissed,\n uint16 penaltyRate\n ) internal pure returns (uint256) {\n // This is monthlyPayment * additionalPaymentsMissed * (1 + penaltyRate)\n // Mortgages without a payment plan don't have monthlyPayments, so we use the termBalance and totalPeriods instead\n return Math.mulDiv(\n mortgagePosition.termBalance,\n uint256(additionalPaymentsMissed) * penaltyRate,\n mortgagePosition.totalPeriods * Constants.BPS,\n Math.Rounding.Ceil\n );\n }\n\n /**\n * @dev Applies missing penalties to a mortgage position\n * @param mortgagePosition The mortgage position\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @param penaltyRate The penalty rate\n * @return The updated mortgage position\n * @return penaltyAmount The penalty amount\n * @return additionalPaymentsMissed The number of additional payments missed\n */\n function applyPenalties(MortgagePosition memory mortgagePosition, uint256 latePenaltyWindow, uint16 penaltyRate)\n internal\n view\n returns (MortgagePosition memory, uint256 penaltyAmount, uint8 additionalPaymentsMissed)\n {\n // Calculate the number of periods missed\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If _periodsPaid >= periodsSinceOrigination, then it is not possible to have missed payments\n // If periodsPaid = totalPeriods, then it is not possible to have missed payments\n if (periodsSinceOrigination > _periodsPaid && _periodsPaid < mortgagePosition.totalPeriods) {\n if (mortgagePosition.hasPaymentPlan) {\n // If the mortgage does have a payment plan, then delta is (periodsSinceOrigination - _periodsPaid)\n additionalPaymentsMissed = periodsSinceOrigination - _periodsPaid - mortgagePosition.paymentsMissed;\n } else if (periodsSinceOrigination >= mortgagePosition.totalPeriods) {\n // If the mortgage does not have a payment plan, then delta is (periodsSinceOrigination - totalPeriods + 1)\n additionalPaymentsMissed =\n periodsSinceOrigination - mortgagePosition.totalPeriods + 1 - mortgagePosition.paymentsMissed;\n }\n // If periodsMissed > paymentsMissed, then you have addition missed payments and penalties to apply\n if (additionalPaymentsMissed > 0) {\n penaltyAmount = mortgagePosition.calculatePenaltyAmount(additionalPaymentsMissed, penaltyRate);\n mortgagePosition.penaltyAccrued += penaltyAmount;\n mortgagePosition.paymentsMissed += additionalPaymentsMissed;\n }\n }\n return (mortgagePosition, penaltyAmount, additionalPaymentsMissed);\n }\n\n /**\n * @dev Pays a penalty for a mortgage position\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the penalty\n * @return The updated mortgage position\n * @return refund The amount of the refund in the case of overpayment\n */\n function penaltyPay(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (MortgagePosition memory, uint256 refund)\n {\n // Revert if the amount is zero\n if (amount == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Ensure that the amount is not greater than the penaltyAccrued. Refund the surplus.\n uint256 penaltyRemaining = mortgagePosition.penaltyAccrued - mortgagePosition.penaltyPaid;\n if (penaltyRemaining == 0 && amount > 0) {\n revert CannotOverpayPenalty(mortgagePosition, amount);\n }\n if (amount > penaltyRemaining) {\n refund = amount - penaltyRemaining;\n amount = penaltyRemaining;\n }\n // Increase the penalty paid by the amount\n mortgagePosition.penaltyPaid += amount;\n // paymentsMissed does not change until they make a payment.\n return (mortgagePosition, refund);\n }\n\n /**\n * @dev Redeems a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The updated mortgage position\n */\n function redeem(MortgagePosition memory mortgagePosition) internal pure returns (MortgagePosition memory) {\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are unpaid payments\n if (mortgagePosition.termBalance > mortgagePosition.termPaid + mortgagePosition.termConverted) {\n revert UnpaidPayments(mortgagePosition);\n }\n // Update the status and return the updated mortgage position\n mortgagePosition.status = MortgageStatus.REDEEMED;\n return mortgagePosition;\n }\n\n /**\n * @dev Helper function to refinance/expand a mortgage position\n * @param mortgagePosition The mortgage position\n * @param principalIn The amount of principal to add to the mortgage position. 0 for refinance, >0 for expansion\n * @param newInterestRate The new interest rate.\n * @param newTotalPeriods The new total number of periods. Should stay the same for expansion.\n * @return The updated mortgage position\n */\n function _refinanceHelper(\n MortgagePosition memory mortgagePosition,\n uint256 principalIn,\n uint16 newInterestRate,\n uint8 newTotalPeriods\n ) private view returns (MortgagePosition memory) {\n uint256 principalPaid = mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid);\n uint256 principalConverted = mortgagePosition.convertPaymentToPrincipal(\n mortgagePosition.termPaid + mortgagePosition.termConverted\n ) - principalPaid;\n mortgagePosition.termBalance = calculateTermBalance(\n mortgagePosition.principalRemaining() + principalIn, newInterestRate, newTotalPeriods, newTotalPeriods\n );\n mortgagePosition.interestRate = newInterestRate;\n mortgagePosition.totalPeriods = newTotalPeriods;\n mortgagePosition.amountPrior += principalPaid;\n mortgagePosition.termOriginated = uint32(block.timestamp);\n mortgagePosition.termPaid = 0;\n mortgagePosition.amountConverted += principalConverted;\n mortgagePosition.termConverted = 0;\n return mortgagePosition;\n }\n\n /**\n * @dev Refinances a mortgage position\n * @param mortgagePosition The mortgage position\n * @param refinanceRate The refinance rate\n * @param newInterestRate The new interest rate\n * @param newTotalPeriods The new total number of periods\n * @return The updated mortgage position\n * @return refinanceFee The refinance fee\n */\n function refinance(\n MortgagePosition memory mortgagePosition,\n uint16 refinanceRate,\n uint16 newInterestRate,\n uint8 newTotalPeriods\n ) internal view returns (MortgagePosition memory, uint256 refinanceFee) {\n // Revert if the termRemaining is 0 (i.e. the mortgage is already paid in full)\n if (mortgagePosition.termRemaining() == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are missed payments\n if (mortgagePosition.paymentsMissed > 0) {\n revert MissedPayments(mortgagePosition);\n }\n\n // Calculate the refinance fee as a percentage of the principalRemaining\n refinanceFee = Math.mulDiv(mortgagePosition.principalRemaining(), refinanceRate, Constants.BPS, Math.Rounding.Ceil);\n\n // Add refinance fee into penaltyAccrued and penaltyPaid\n mortgagePosition.penaltyAccrued += refinanceFee;\n mortgagePosition.penaltyPaid += refinanceFee;\n\n // // Update the mortgagePosition with the new values\n mortgagePosition = _refinanceHelper(mortgagePosition, 0, newInterestRate, newTotalPeriods);\n\n // Return the updated mortgage position and the refinance fee\n return (mortgagePosition, refinanceFee);\n }\n\n /**\n * @dev Forecloses a mortgage position\n * @param mortgagePosition The mortgage position\n * @param maxMissedPayments The maximum number of missed payments\n * @return The updated mortgage position\n */\n function foreclose(MortgagePosition memory mortgagePosition, uint8 maxMissedPayments)\n internal\n pure\n returns (MortgagePosition memory)\n {\n // Revert if paymentsMissed is less than or equal to maxMissedPayments\n if (mortgagePosition.paymentsMissed <= maxMissedPayments) {\n revert NotForeclosable(mortgagePosition, maxMissedPayments);\n }\n\n // Update the status and return the updated mortgage position\n mortgagePosition.status = MortgageStatus.FORECLOSED;\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n\n /**\n * @dev Converts a mortgage position by reducing the principal and collateral\n * @param mortgagePosition The mortgage position\n * @param currentPrice The current price of the collateral\n * @param principalConverting The amount of principal to convert\n * @param collateralConverting The amount of collateral to convert\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @return The updated mortgage position\n */\n function convert(\n MortgagePosition memory mortgagePosition,\n uint256 currentPrice,\n uint256 principalConverting,\n uint256 collateralConverting,\n uint256 latePenaltyWindow\n ) internal view returns (MortgagePosition memory) {\n // Check three conditions:\n // 1. Current price is greater than or equal to the conversion trigger price\n if (mortgagePosition.conversionTriggerPrice() > currentPrice) {\n revert ConversionTriggerPriceNotMet(mortgagePosition, currentPrice);\n }\n // 2. principalConverting is not greater than principalRemaining\n // 3. collateralConverting is not greater than collateralRemaining\n if (\n mortgagePosition.conversionTriggerPrice() > currentPrice\n || principalConverting > mortgagePosition.principalRemaining()\n || collateralConverting > mortgagePosition.collateralRemaining()\n ) {\n revert CannotOverConvert(mortgagePosition, principalConverting, collateralConverting);\n }\n\n // Update the termConverted, amountConverted, and collateralConverted fields\n mortgagePosition.termConverted += mortgagePosition.convertPrincipalToPayment(principalConverting);\n mortgagePosition.collateralConverted += collateralConverting;\n\n // Make sure paymentsMissed is up to date\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If the mortgage is paid in full, there are no more missed payments since and additional penalties can no longer be applied\n if (_periodsPaid == mortgagePosition.totalPeriods) {\n mortgagePosition.paymentsMissed = 0;\n } else if (mortgagePosition.hasPaymentPlan) {\n // If the mortgage has a payment plan, the number of missed payments is the difference between the periods since origination and the periods paid\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n mortgagePosition.paymentsMissed =\n _periodsPaid > periodsSinceOrigination ? 0 : periodsSinceOrigination - _periodsPaid;\n }\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n\n /**\n * @dev Calculates the new interest rate for an existing mortgage position given a new principal amount, interest rate, and computes a weighted average\n * @param mortgagePosition The mortgage position\n * @param amountIn The amount of principal to add to the mortgage position\n * @param newInterestRate The new interest rate\n * @return The new average interest rate\n */\n function calculateNewAverageInterestRate(\n MortgagePosition memory mortgagePosition,\n uint256 amountIn,\n uint16 newInterestRate\n ) internal pure returns (uint16) {\n return uint16(\n (mortgagePosition.interestRate * mortgagePosition.principalRemaining() + newInterestRate * amountIn)\n / (mortgagePosition.principalRemaining() + amountIn)\n );\n }\n\n /**\n * @dev Expands the balance sheet of a mortgage position\n * @param mortgagePosition The mortgage position to expand the balance sheet of\n * @param amountIn The amount of principal to add to the mortgage position\n * @param collateralAmountIn The amount of collateral to add to the mortgage position\n * @param newInterestRate The new interest rate to set for the mortgage position\n * @return The updated mortgage position\n */\n function expandBalanceSheet(\n MortgagePosition memory mortgagePosition,\n uint256 amountIn,\n uint256 collateralAmountIn,\n uint16 newInterestRate\n ) internal view returns (MortgagePosition memory) {\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are missed payments\n if (mortgagePosition.paymentsMissed > 0) {\n revert MissedPayments(mortgagePosition);\n }\n // Calculate the new interest rate\n uint16 averageInterestRate = mortgagePosition.calculateNewAverageInterestRate(amountIn, newInterestRate);\n\n // Update the mortgagePosition with the new values\n mortgagePosition = _refinanceHelper(mortgagePosition, amountIn, averageInterestRate, mortgagePosition.totalPeriods);\n mortgagePosition.collateralAmount += collateralAmountIn;\n mortgagePosition.amountBorrowed += amountIn;\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n}\n"},"lib/cash/src/types/MortgagePosition.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgageStatus} from \"./enums/MortgageStatus.sol\";\n\n/**\n * @notice The complete state of a mortgage position\n * @param tokenId Numerical identifier for the mortgage\n * @param collateral The address of the collateral token\n * @param collateralDecimals The decimals of the collateral token\n * @param collateralAmount The amount of collateral escrowed in the Consol contract\n * @param collateralConverted The amount of collateral that has been withdrawn as a result of a conversion\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param interestRate The interest rate of the mortgage, determined at time of initialization\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param dateOriginated The date the mortgage was originated\n * @param termOriginated The beginning of the term of the mortgage. Will differ from `dateOriginated` if the mortgage is refinanced.\n * @param termBalance The total balance of the mortgage for the current term.\n * @param amountBorrowed The amount borrowed by the borrower\n * @param amountPrior The cumulative amount of principal paid off in prior terms\n * @param termPaid The amount paid by the borrower for the current term\n * @param termConverted The amount of the current term paid via conversion in the current term.\n * @param amountConverted The amount of the principal that has been forgiven as a result of a conversion in previous terms. Excludes the current term.\n * @param penaltyAccrued Sum of penalties accrued. This number is never decremented.\n * @param penaltyPaid The penalty paid by the borrower. Incremented with every call to penaltyPay()\n * @param paymentsMissed The number of payments missed by the borrower. It records the number of penalties that have already been applied. Reset to 0 when mortgage is paid in full.\n * @param totalPeriods The total number of periods that the mortgage will last\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @param status The status of the mortgage\n */\nstruct MortgagePosition {\n uint256 tokenId;\n address collateral;\n uint8 collateralDecimals;\n uint256 collateralAmount;\n uint256 collateralConverted;\n address subConsol;\n uint16 interestRate;\n uint16 conversionPremiumRate;\n uint32 dateOriginated;\n uint32 termOriginated;\n uint256 termBalance;\n uint256 amountBorrowed;\n uint256 amountPrior; // This one is cumulative amounts of principal paid off in prior terms\n uint256 termPaid; // This one is only for the current term\n uint256 termConverted; // This is only for the current term\n uint256 amountConverted; // This one is cumulative amounts of principal converted in previous terms\n uint256 penaltyAccrued;\n uint256 penaltyPaid;\n uint8 paymentsMissed;\n uint8 totalPeriods;\n bool hasPaymentPlan;\n MortgageStatus status;\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVault.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ILiquidityVaultEvents} from \"./ILiquidityVaultEvents.sol\";\nimport {ILiquidityVaultErrors} from \"./ILiquidityVaultErrors.sol\";\n\n/**\n * @title ILiquidityVault\n * @author @SocksNFlops\n * @notice Interface for LiquidityVault, a yield-bearing vault that enables depositing tokens for redeemable shares that earn yield.\n */\ninterface ILiquidityVault is IERC20, ILiquidityVaultEvents, ILiquidityVaultErrors {\n /**\n * @notice The role for the keeper\n * @return The role for the keeper\n */\n // solhint-disable-next-line func-name-mixedcase\n function KEEPER_ROLE() external view returns (bytes32);\n\n /**\n * @notice\n * @return The role for the whitelist\n */\n // solhint-disable-next-line func-name-mixedcase\n function WHITELIST_ROLE() external view returns (bytes32);\n\n /**\n * @notice Whether the whitelist is enforced.\n * @return Whether the whitelist is enforced.\n */\n function whitelistEnforced() external view returns (bool);\n\n /**\n * @notice Enforces the whitelist.\n * @param enforced Whether the whitelist is enforced.\n */\n function setWhitelistEnforced(bool enforced) external;\n\n /**\n * @notice The decimals offset. The number of decimals to offset the shares by. Used to protect against inflation attacks.\n * @return The decimals offset\n */\n function decimalsOffset() external view returns (uint8);\n\n /**\n * @notice The total assets of the vault\n * @return The total assets of the vault\n */\n function totalAssets() external view returns (uint256);\n\n /**\n * @notice The address of the depositable asset.\n * @return The address of the depositable asset.\n */\n function depositableAssets() external view returns (address[] memory);\n\n /**\n * @notice The addresses of the redeemable assets.\n * @return The addresses of the redeemable assets.\n */\n function redeemableAssets() external view returns (address[] memory);\n\n /**\n * @notice Sets the paused state of the vault.\n * @param paused The paused state of the vault.\n */\n function setPaused(bool paused) external;\n\n /**\n * @notice Deposits the specified amount of depositable asset into the vault.\n * @param depositableAsset The address of the depositable asset to deposit.\n * @param assets The amount of depositable asset to deposit.\n */\n function deposit(address depositableAsset, uint256 assets) external;\n\n /**\n * @notice Redeems the specified amount of shares for the redeemable asset.\n * @param shares The amount of shares to redeem.\n */\n function redeem(uint256 shares) external;\n}\n"},"lib/cash/src/types/orders/MortgageParams.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @notice The parameters for creating a mortgage position\n * @param owner The address of the owner of the mortgage\n * @param tokenId The tokenId of the mortgage NFT\n * @param collateral The address of the collateral token\n * @param collateralDecimals The decimals of the collateral token\n * @param collateralAmount The amount of collateral escrowed in the Consol contract\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param interestRate The interest rate of the mortgage\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param amountBorrowed The total amount being borrowed from all origination pools\n * @param totalPeriods The total umber of periods that the mortgage will last\n * @param hasPaymentPlan Whether the mortgage is hasPaymentPlan (periodic payment plan vs single payment)\n */\nstruct MortgageParams {\n address owner;\n uint256 tokenId;\n address collateral;\n uint8 collateralDecimals;\n uint256 collateralAmount;\n address subConsol;\n uint16 interestRate;\n uint16 conversionPremiumRate;\n uint256 amountBorrowed;\n uint8 totalPeriods;\n bool hasPaymentPlan;\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManagerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILoanManagerErrors\n * @author Socks&Flops\n * @notice Interface for all errors in the LoanManager contract\n */\ninterface ILoanManagerEvents {\n /**\n * @notice Emitted when a mortgage is created\n * @param tokenId The numerical index of the mortgageNFT\n * @param owner The owner of the mortgage\n * @param collateral The collateral address\n * @param collateralAmount The collateral amount\n * @param amountBorrowed The amount borrowed\n */\n event CreateMortgage(\n uint256 indexed tokenId,\n address indexed owner,\n address indexed collateral,\n uint256 collateralAmount,\n uint256 amountBorrowed\n );\n\n /**\n * @notice Emitted when a mortgage position has a monthly payment paid\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountPaid The amount paid\n * @param periodsPaid The number of periods paid\n */\n event PeriodPay(uint256 indexed tokenId, uint256 amountPaid, uint8 periodsPaid);\n\n /**\n * @notice Emitted when a mortgage position has a penalty paid\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountPaid The amount paid\n */\n event PenaltyPay(uint256 indexed tokenId, uint256 amountPaid);\n\n /**\n * @notice Emitted when a penalty is imposed on a mortgage position\n * @param tokenId The numerical index of the mortgageNFT\n * @param penaltyAmount The penalty amount added to the mortgage position\n * @param additionalMissedPayments The number of missed payments added to the mortgage position\n * @param penaltyAccrued The total penalty accrued so far\n * @param paymentsMissed The total number of payments missed so far\n */\n event PenaltyImposed(\n uint256 indexed tokenId,\n uint256 penaltyAmount,\n uint8 additionalMissedPayments,\n uint256 penaltyAccrued,\n uint8 paymentsMissed\n );\n\n /**\n * @notice Emitted when a mortgage is redeemed\n * @param tokenId The numerical index of the mortgageNFT\n */\n event RedeemMortgage(uint256 indexed tokenId);\n\n /**\n * @notice Emitted when a mortgage is refinanced\n * @param tokenId The numerical index of the mortgageNFT\n * @param timestamp The timestamp of the refinance\n * @param refinanceFee The refinance fee\n * @param interestRate The interest rate\n * @param principalRemaining The principal remaining\n */\n event RefinanceMortgage(\n uint256 indexed tokenId, uint256 timestamp, uint256 refinanceFee, uint16 interestRate, uint256 principalRemaining\n );\n\n /**\n * @notice Emitted when a mortgage is foreclosed\n * @param tokenId The numerical index of the mortgageNFT\n */\n event ForecloseMortgage(uint256 indexed tokenId);\n\n /**\n * @notice Emitted when a mortgage is converted\n * @param tokenId The numerical index of the mortgageNFT\n * @param amount The amount of the mortgage that is being converted\n * @param collateralAmount The amount of the collateral that is being converted\n * @param receiver The address receiving the converted collateral\n */\n event ConvertMortgage(uint256 indexed tokenId, uint256 amount, uint256 collateralAmount, address receiver);\n\n /**\n * @notice Emitted when the balance sheet of a mortgage position is expanded\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountIn The amount of the principal being added to the mortgage position\n * @param collateralAmountIn The amount of collateral being added to the mortgage position\n * @param newInterestRate The new interest rate of the mortgage position\n */\n event ExpandBalanceSheet(\n uint256 indexed tokenId, uint256 amountIn, uint256 collateralAmountIn, uint16 newInterestRate\n );\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManagerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgageStatus} from \"../../types/MortgagePosition.sol\";\n\n/**\n * @title ILoanManagerErrors\n * @author Socks&Flops\n * @notice Interface for all errors in the LoanManager contract\n */\ninterface ILoanManagerErrors {\n /**\n * @notice Thrown when a non-general manager attempts to call an operation that requires general manager access\n * @param caller The address of the caller\n * @param generalManager The address of the general manager\n */\n error OnlyGeneralManager(address caller, address generalManager);\n\n /**\n * @notice Thrown when the amount borrowed is below the minimum threshold\n * @param amountBorrowed The amount borrowed\n * @param minAmountBorrowed The minimum amount borrowed\n */\n error AmountBorrowedBelowMinimum(uint256 amountBorrowed, uint256 minAmountBorrowed);\n\n /**\n * @notice Thrown when a mortgage position does not exist\n * @param tokenId The tokenId of the mortgage\n */\n error MortgagePositionDoesNotExist(uint256 tokenId);\n\n /**\n * @notice Thrown when a mortgage position is not active\n * @param tokenId The tokenId of the mortgage\n * @param status The status of the mortgage\n */\n error MortgagePositionNotActive(uint256 tokenId, MortgageStatus status);\n\n /**\n * @notice Thrown when a non-mortgage owner attempts to call an operation that requires ownership\n * @param tokenId The tokenId of the mortgage\n * @param owner The owner of the mortgage\n * @param caller The caller of the function\n */\n error OnlyMortgageOwner(uint256 tokenId, address owner, address caller);\n}\n"},"lib/cash/src/interfaces/IConsolFlashSwap.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolFlashSwap\n * @author SocksNFlops\n * @notice Any contract that calls IConsol#flashSwap must implement this interface\n */\ninterface IConsolFlashSwap {\n /**\n * @notice Thrown when a non-Consol contract attempts to call IConsolFlashSwap#flashSwapCallback\n * @param caller The address of the caller\n * @param consol The address of the Consol contract\n */\n error OnlyConsol(address caller, address consol);\n\n /**\n * @notice Called to `msg.sender` after transferring to the recipient from IConsol#flashSwap.\n * @dev In the implementation you must repay the inputTokens sent in the outputToken currency\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param amount The amount of tokens to swap\n * @param data The data to pass into the callback\n */\n function flashSwapCallback(address inputToken, address outputToken, uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManagerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.24;\n\n/**\n * @title IGeneralManagerEvents\n * @author @SocksNFlops\n * @notice Events emitted by the GeneralManager contract\n */\ninterface IGeneralManagerEvents {\n /**\n * @notice Emitted when the penalty rate is set\n * @param oldPenaltyRate The old penalty rate\n * @param newPenaltyRate The new penalty rate\n */\n event PenaltyRateSet(uint16 oldPenaltyRate, uint16 newPenaltyRate);\n\n /**\n * @notice Emitted when the refinance rate is set\n * @param oldRefinanceRate The old refinance rate\n * @param newRefinanceRate The new refinance rate\n */\n event RefinanceRateSet(uint16 oldRefinanceRate, uint16 newRefinanceRate);\n\n /**\n * @notice Emitted when the insurance fund address is set\n * @param oldInsuranceFund The old insurance fund address\n * @param newInsuranceFund The new insurance fund address\n */\n event InsuranceFundSet(address oldInsuranceFund, address newInsuranceFund);\n\n /**\n * @notice Emitted when the interest rate oracle address is set\n * @param oldInterestRateOracle The old interest rate oracle address\n * @param newInterestRateOracle The new interest rate oracle address\n */\n event InterestRateOracleSet(address oldInterestRateOracle, address newInterestRateOracle);\n\n /**\n * @notice Emitted when the conversion premium rate is set\n * @param oldConversionPremiumRate The old conversion premium rate\n * @param newConversionPremiumRate The new conversion premium rate\n */\n event ConversionPremiumRateSet(uint16 oldConversionPremiumRate, uint16 newConversionPremiumRate);\n\n /**\n * @notice Emitted when the origination pool scheduler address is set\n * @param oldOriginationPoolScheduler The old origination pool scheduler address\n * @param newOriginationPoolScheduler The new origination pool scheduler address\n */\n event OriginationPoolSchedulerSet(address oldOriginationPoolScheduler, address newOriginationPoolScheduler);\n\n /**\n * @notice Emitted when the loan manager address is set\n * @param oldLoanManager The old loan manager address\n * @param newLoanManager The new loan manager address\n */\n event LoanManagerSet(address oldLoanManager, address newLoanManager);\n\n /**\n * @notice Emitted when the order pool address is set\n * @param oldOrderPool The old order pool address\n * @param newOrderPool The new order pool address\n */\n event OrderPoolSet(address oldOrderPool, address newOrderPool);\n\n /**\n * @notice Emitted when the supported mortgage period terms are updated\n * @param collateral The address of the collateral\n * @param mortgagePeriods The mortgage period\n * @param isSupported Whether the mortgage period terms are supported\n */\n event SupportedMortgagePeriodTermsUpdated(address indexed collateral, uint8 mortgagePeriods, bool isSupported);\n\n /**\n * @notice Emitted when a price oracle is set\n * @param collateral The address of the collateral\n * @param priceOracle The address of the new oracle\n */\n event PriceOracleSet(address indexed collateral, address indexed priceOracle);\n\n /**\n * @notice Emitted when the minimum cap for a collateral is set\n * @param collateral The address of the collateral\n * @param minimumCap The minimum cap\n */\n event MinimumCapSet(address indexed collateral, uint256 minimumCap);\n\n /**\n * @notice Emitted when the maximum cap for a collateral is set\n * @param collateral The address of the collateral\n * @param maximumCap The maximum cap\n */\n event MaximumCapSet(address indexed collateral, uint256 maximumCap);\n\n /**\n * @notice Emitted when the price spread is set\n * @param oldPriceSpread The old price spread\n * @param newPriceSpread The new price spread\n */\n event PriceSpreadSet(uint16 oldPriceSpread, uint16 newPriceSpread);\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManagerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.24;\n\nimport {CreationRequest} from \"../../types/orders/OrderRequests.sol\";\n\n/**\n * @title IGeneralManagerErrors\n * @author @SocksNFlops\n * @notice Errors emitted by the GeneralManager contract\n */\ninterface IGeneralManagerErrors {\n /**\n * @notice The origination pool is not registered with the scheduler\n * @param originationPool The address of the origination pool\n */\n error InvalidOriginationPool(address originationPool);\n\n /**\n * @notice The origination pools array is empty\n */\n error EmptyOriginationPools();\n\n /**\n * @notice Duplicate origination pools provided in request\n * @param originationPool The address of the origination pool\n */\n error DuplicateOriginationPool(address originationPool);\n\n /**\n * @notice The subConsol is not backed by the collateral or is not supported by the consol\n * @param collateral The address of the collateral\n * @param subConsol The address of the subConsol\n * @param consol The address of the consol\n */\n error InvalidSubConsol(address collateral, address subConsol, address consol);\n\n /**\n * @notice The total periods exceed the maximum possible number of periods\n * @param totalPeriods The total periods\n * @param maxTotalPeriods The maximum possible number of periods\n */\n error TotalPeriodsExceedsMaximum(uint8 totalPeriods, uint8 maxTotalPeriods);\n\n /**\n * @notice The total periods are invalid\n * @param collateral The address of the collateral\n * @param totalPeriods The total periods\n */\n error InvalidTotalPeriods(address collateral, uint8 totalPeriods);\n\n /**\n * @notice The origination pools list length does not match the collateral amounts list length\n * @param originationPoolsListLength The length of the origination pools list\n * @param collateralAmountsListLength The length of the collateral amounts list\n */\n error OriginationPoolsListLengthMismatch(uint256 originationPoolsListLength, uint256 collateralAmountsListLength);\n\n /**\n * @notice The caller is not the order pool\n * @param caller The address of the caller\n * @param orderPool The address of the order pool\n */\n error OnlyOrderPool(address caller, address orderPool);\n\n /**\n * @notice The conversion queue is not registered\n * @param conversionQueue The address of the conversion queue\n */\n error InvalidConversionQueue(address conversionQueue);\n\n /**\n * @notice The mortgage is already enqueued in the conversion queue\n * @param tokenId The tokenId of the mortgage\n * @param conversionQueue The address of the conversion queue\n */\n error MortgageAlreadyEnqueuedInConversionQueue(uint256 tokenId, address conversionQueue);\n\n /**\n * @notice Thrown when the caller is not the owner of the mortgageNFT\n * @param caller The caller of the function\n * @param owner The owner of the mortgageNFT\n * @param tokenId The tokenId of the mortgageNFT\n */\n error NotMortgageOwner(address caller, address owner, uint256 tokenId);\n\n /**\n * @notice Thrown when a compounding mortgage is being created and a conversion queue is not provided\n * @param creationRequest The create request\n */\n error CompoundingMustConvert(CreationRequest creationRequest);\n\n /**\n * @notice Thrown when a non-compounding mortgage is being created and the hasPaymentPlan flag is not set to true\n * @param creationRequest The create request\n */\n error NonCompoundingMustHavePaymentPlan(CreationRequest creationRequest);\n\n /**\n * @notice Thrown when the total periods of the expansion request does not match the existing mortgage position\n * @param totalPeriods The total periods of the expansion request\n * @param existingTotalPeriods The total periods of the existing mortgage position\n */\n error ExpansionTotalPeriodsMismatch(uint8 totalPeriods, uint8 existingTotalPeriods);\n\n /**\n * @notice Thrown when the amount borrowed is below the minimum cap for the collateral\n * @param collateral The address of the collateral\n * @param amountBorrowed The amount borrowed\n * @param minimumCap The minimum cap\n */\n error MinimumCapNotMet(address collateral, uint256 amountBorrowed, uint256 minimumCap);\n\n /**\n * @notice Thrown when the amount borrowed is above the maximum cap for the collateral\n * @param collateral The address of the collateral\n * @param amountBorrowed The amount borrowed\n * @param maximumCap The maximum cap\n */\n error MaximumCapExceeded(address collateral, uint256 amountBorrowed, uint256 maximumCap);\n\n /**\n * @notice Thrown when the caller sends too little gas to the contract\n * @param sentGas The amount of gas sent\n * @param requiredGas The required gas\n */\n error InsufficientGas(uint256 sentGas, uint256 requiredGas);\n\n /**\n * @notice Failed Withdraw Native Gas.\n * @param amount The amount of native gas to withdraw\n */\n error FailedToWithdrawNativeGas(uint256 amount);\n}\n"},"lib/cash/src/interfaces/IOriginationPoolDeployCallback.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IOriginationPoolDeployCallback\n * @author SocksNFlops\n * @notice Any contract that calls IOriginationPool#deploy must implement this interface\n */\ninterface IOriginationPoolDeployCallback {\n /**\n * @notice Called to `msg.sender` after transferring to the recipient from IOriginationPool#deploy.\n * @dev In the implementation you must repay the pool the tokens sent by flash after the pool multiplier has been applied.\n * @param amount The amount of consol sent to the callback\n * @param returnAmount The amount of consol to return to the origination pool\n * @param data Any data passed through by the caller via the IOriginationPool#deploy call\n */\n function originationPoolDeployCallback(uint256 amount, uint256 returnAmount, bytes calldata data) external;\n}\n"},"lib/cash/src/types/orders/OriginationParameters.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {MortgageParams} from \"../orders/MortgageParams.sol\";\n\n/**\n * @notice The parameters for originating a mortgage creation or balance sheet expansion\n * @param mortgageParams The parameters for the mortgage\n * @param fulfiller The address of the fulfiller\n * @param originationPools The addresses of the origination pools to deploy funds from\n * @param borrowAmounts The amounts being borrowed from each origination pool. Sum must be equal to mortgageParams.amountBorrowed\n * @param conversionQueues The addresses of the conversion queues to use\n * @param hintPrevIds The hintPrevIds of the mortgage\n * @param expansion Whether the mortgage is a balance sheet expansion of an existing position\n * @param purchaseAmount The amount of USDX to purchase\n */\nstruct OriginationParameters {\n MortgageParams mortgageParams;\n address fulfiller;\n address[] originationPools;\n uint256[] borrowAmounts;\n address[] conversionQueues;\n uint256[] hintPrevIds;\n bool expansion;\n uint256 purchaseAmount;\n}\n"},"lib/cash/src/interfaces/IPausable/IPausable.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IPausableErrors} from \"./IPausableErrors.sol\";\n\n/**\n * @title IPausable\n * @author @SocksNFlops\n * @notice Interface for the pausable contract\n */\ninterface IPausable is IPausableErrors {\n /**\n * @notice Pause or unpause the contract\n * @param pause The new paused state\n */\n function setPaused(bool pause) external;\n\n /**\n * @notice Get the paused state of the contract\n * @return The paused state of the contract\n */\n function paused() external view returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n /*\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n * 0xb0202a11 ===\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n */\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @param data Additional data with no specified format, sent in call to `spender`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPoolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IOriginationPoolEvents\n * @author SocksNFlops\n * @notice Events for the OriginationPool contract\n */\ninterface IOriginationPoolEvents {\n /**\n * @notice Event for a deposit\n * @param user The user\n * @param token The token\n * @param amount The amount of USDTokens being deposited\n * @param mintAmount The amount of OriginationPool tokens being minted\n */\n event Deposit(address indexed user, address indexed token, uint256 amount, uint256 mintAmount);\n\n /**\n * @notice Event for a deploy\n * @param user The user\n * @param token The token\n * @param amount The amount of USDTokens being deployed\n * @param receiptAmount The amount of OriginationPool tokens being returned\n */\n event Deploy(address indexed user, address indexed token, uint256 amount, uint256 receiptAmount);\n\n /**\n * @notice Event for a redeem\n * @param user The user\n * @param amount The amount of OriginationPool tokens being redeemed\n */\n event Redeem(address indexed user, uint256 amount);\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPoolErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OriginationPoolPhase} from \"../../types/enums/OriginationPoolPhase.sol\";\n\n/**\n * @title IOriginationPoolErrors\n * @author SocksNFlops\n * @notice Errors for the OriginationPool contract\n */\ninterface IOriginationPoolErrors {\n /**\n * @notice Error for incorrect phase\n * @param requiredPhase The required phase\n * @param currentPhase The current phase\n */\n error IncorrectPhase(OriginationPoolPhase requiredPhase, OriginationPoolPhase currentPhase);\n\n /**\n * @notice Error for pool limit exceeded\n * @param poolLimit The pool limit\n * @param amount The amount\n */\n error PoolLimitExceeded(uint256 poolLimit, uint256 amount);\n\n /**\n * @notice Error for insufficient consol returned\n * @param requiredAmount The required amount\n * @param amountReturned The amount returned\n */\n error InsufficientConsolReturned(uint256 requiredAmount, uint256 amountReturned);\n\n /**\n * @notice Error for insufficient amount passed to a function\n * @param amount The amount\n * @param minimumAmount The minimum amount\n */\n error InsufficientAmount(uint256 amount, uint256 minimumAmount);\n}\n"},"lib/cash/src/types/enums/OriginationPoolPhase.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @notice The phases of the Origination Pool\n */\nenum OriginationPoolPhase {\n /// @notice Lenders can deposit funds into the pool to provide liquidity for mortgage origination\n DEPOSIT,\n /// @notice Pool funds are actively deployed for mortgage origination and new deposits/withdrawals are disabled\n DEPLOY,\n /// @notice Lenders can redeem their funds from the pool along with earned fees from mortgage originations\n REDEMPTION\n}\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVault.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVaultEvents} from \"./IMultiTokenVaultEvents.sol\";\nimport {IMultiTokenVaultErrors} from \"./IMultiTokenVaultErrors.sol\";\nimport {IRebasingERC20} from \"../IRebasingERC20/IRebasingERC20.sol\";\n\n/**\n * @title IMultiTokenVault\n * @author Socks&Flops\n * @notice Interface for the MultiTokenVault contract. Assumes all supported tokens deposited have same UOA.\n */\ninterface IMultiTokenVault is IRebasingERC20, IMultiTokenVaultEvents, IMultiTokenVaultErrors {\n /**\n * @notice Add a supported token to the MultiTokenVault\n * @param token The address of the token to add\n */\n function addSupportedToken(address token) external;\n\n /**\n * @notice Remove a supported token from the MultiTokenVault\n * @param token The address of the token to remove\n */\n function removeSupportedToken(address token) external;\n\n /**\n * @notice Get the list of supported tokens\n * @return The list of supported tokens\n */\n function getSupportedTokens() external view returns (address[] memory);\n\n /**\n * @notice Check if a token is supported\n * @param token The address of the token to check\n * @return isSupported True if the token is supported, false otherwise\n */\n function isTokenSupported(address token) external view returns (bool isSupported);\n\n /**\n * @notice Calculates the amount of tokens minted/burned in a deposit/withdraw operation\n * @param token The address of the token to deposit/withdraw\n * @param amount The amount of tokens to deposit/withdraw\n * @return The mint/burn amount\n */\n function convertAmount(address token, uint256 amount) external view returns (uint256);\n\n /**\n * @notice Calculates the amount of underlying tokens required to deposit/withdraw a given amount of tokens\n * @param token The address of the token to deposit/withdraw\n * @param amount The amount of tokens minted/burned as a result of the deposit/withdraw operation\n * @return The amount of underlying tokens required to deposit/withdraw the given amount of tokens\n */\n function convertUnderlying(address token, uint256 amount) external view returns (uint256);\n\n /**\n * @notice Deposit tokens into the MultiTokenVault and mint an equivalent amount of the MultiTokenVault token.\n * @param token The address of the token to deposit\n * @param amount The amount of tokens to deposit\n */\n function deposit(address token, uint256 amount) external;\n\n /**\n * @notice Withdraw tokens from the MultiTokenVault and burn an equivalent amount of the MultiTokenVault token.\n * @param token The address of the token to withdraw\n * @param amount The amount of tokens to withdraw\n */\n function withdraw(address token, uint256 amount) external;\n\n /**\n * @notice Forfeit tokens from the MultiTokenVault. Redistributes the forfeited tokens to the existing holders.\n * @param amount The amount of tokens to forfeit\n */\n function forfeit(uint256 amount) external;\n\n /**\n * @notice Given shares and an amount, this will burn shares until the amount is reached.\n * @dev This is achieved by burning all of the shares and minting the amount. Will no-op if attempting to mint more than the shares correspond to.\n * @param shares The amount of shares to burn\n * @param amount The amount of tokens to mint\n */\n function burnExcessShares(uint256 shares, uint256 amount) external;\n\n /**\n * @notice Set the absolute maximum cap for an underlying token.\n * @param token The address of the token to set the cap for\n * @param _maximumCap The new maximum cap for the token denominated in the UOA. Default is type(uint256).max.\n */\n function setMaximumCap(address token, uint256 _maximumCap) external;\n\n /**\n * @notice Get the absolute maximum cap for a token\n * @param token The address of the token to get the cap for\n * @return The maximum cap for the token denominated in the UOA.\n */\n function maximumCap(address token) external view returns (uint256);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsolErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolErrors\n * @author SocksNFlops\n * @notice Interface for the Consol errors.\n */\ninterface IConsolErrors {\n /**\n * @notice Forfeited assets pool is not set.\n */\n error ForfeitedAssetsPoolNotSet();\n\n /**\n * @notice Insufficient tokens returned.\n * @param amount The amount of tokens that were expected to be returned\n * @param actualAmount The amount of tokens that were returned\n */\n error InsufficientTokensReturned(uint256 amount, uint256 actualAmount);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolEvents\n * @author SocksNFlops\n * @notice Interface for the Consol contract events.\n */\ninterface IConsolEvents {\n /**\n * @notice Emitted when a flash swap is made.\n * @param inputToken The input token\n * @param outputToken The output token\n * @param amount The amount of tokens swapped\n * @param actualAmount The amount of tokens returned\n */\n event FlashSwap(address indexed inputToken, address indexed outputToken, uint256 amount, uint256 actualAmount);\n}\n"},"lib/cash/src/interfaces/ISubConsol/ISubConsolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ISubConsolEvents\n * @author Socks&Flops\n * @notice Interface for the SubConsolEvents.\n */\ninterface ISubConsolEvents {\n /**\n * @notice Emitted when collateral is deposited into the SubConsol contract\n * @param account The address of the account that deposited\n * @param collateralAmount The amount of collateral deposited\n * @param mintAmount The amount of subconsol minted\n */\n event Deposit(address indexed account, uint256 collateralAmount, uint256 mintAmount);\n\n /**\n * @notice Emitted when collateral is withdrawn from the SubConsol contract\n * @param account The address of the account that withdrew\n * @param collateralAmount The amount of collateral withdrawn\n * @param burnAmount The amount of subconsol burned\n */\n event Withdraw(address indexed account, uint256 collateralAmount, uint256 burnAmount);\n\n /**\n * @notice Emitted when the yield strategy is set\n * @param yieldStrategy The address of the yield strategy\n */\n event YieldStrategySet(address indexed yieldStrategy);\n\n /**\n * @notice Emitted when the yield amount is updated\n * @param yieldAmount The amount of yield in the yield strategy\n */\n event YieldAmountUpdated(uint256 yieldAmount);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDXEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IUSDXEvents {\n /**\n * @notice Emitted when a new token is added to the MultiTokenVault\n * @param token The address of the token that was added\n * @param numerator The numerator for the token\n * @param denominator The denominator for the token\n */\n event TokenScalarsAdded(address indexed token, uint256 numerator, uint256 denominator);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDXErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IUSDXErrors {\n /**\n * @notice Emitted when the token scalars are invalid\n * @param token The address of the token that has invalid scalars\n * @param numerator The numerator for the token\n * @param denominator The denominator for the token\n */\n error InvalidTokenScalars(address token, uint256 numerator, uint256 denominator);\n}\n"},"lib/cash/src/types/OriginationPoolConfig.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {OPoolConfigIdLibrary} from \"./OPoolConfigId.sol\";\n\nusing OPoolConfigIdLibrary for OriginationPoolConfig global;\n\n/**\n * @notice The configuration for a recurring origination pool deployment\n * @param namePrefix The prefix for the name of the pool\n * @param symbolPrefix The prefix for the symbol of the pool\n * @param consol The consol token for the pool\n * @param usdx The USDX token for the pool\n * @param depositPhaseDuration The duration of the deposit phase\n * @param deployPhaseDuration The duration of the deploy phase\n * @param defaultPoolLimit The starting pool limit (for first deployment)\n * @param poolLimitGrowthRateBps The rate at which the pool limit grows each epoch if the previous pool limit was reached\n * @param poolMultiplierBps The pool multiplier in basis points\n */\nstruct OriginationPoolConfig {\n string namePrefix;\n string symbolPrefix;\n address consol;\n address usdx;\n uint32 depositPhaseDuration;\n uint32 deployPhaseDuration;\n uint256 defaultPoolLimit;\n uint16 poolLimitGrowthRateBps;\n uint16 poolMultiplierBps;\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolSchedulerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\n\ninterface IOriginationPoolSchedulerEvents {\n /**\n * @notice Emitted when a new origination pool config is added\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n */\n event OriginationPoolConfigAdded(OPoolConfigId oPoolConfigId, OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice Emitted when an origination pool config is removed\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n */\n event OriginationPoolConfigRemoved(OPoolConfigId oPoolConfigId, OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice Emitted when an origination pool is deployed\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n * @param deploymentAddress The address of the deployment\n * @param deploymentEpoch The epoch of the deployment\n * @param deploymentTimestamp The timestamp of the deployment\n */\n event OriginationPoolDeployed(\n OPoolConfigId indexed oPoolConfigId,\n OriginationPoolConfig indexed oPoolConfig,\n address indexed deploymentAddress,\n uint256 deploymentEpoch,\n uint256 deploymentTimestamp\n );\n\n /**\n * @notice Emitted when an origination pool is updated\n * @param originationPool The address of the origination pool\n * @param registered Whether the origination pool is registered\n */\n event OriginationPoolRegistryUpdated(address indexed originationPool, bool registered);\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolSchedulerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\n\ninterface IOriginationPoolSchedulerErrors {\n /**\n * @notice The new admin does not have the DEFAULT_ADMIN_ROLE\n * @param newOpoolAdmin The address of the new admin\n */\n error InvalidOpoolAdmin(address newOpoolAdmin);\n\n /**\n * @notice The origination pool config already exists\n * @param oPoolConfig The origination pool config that already exists\n */\n error OriginationPoolConfigAlreadyExists(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool config does not exist\n * @param oPoolConfig The origination pool config that does not exist\n */\n error OriginationPoolConfigDoesNotExist(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool config is invalid\n * @param oPoolConfig The origination pool config that is invalid\n */\n error InvalidOriginationPoolConfig(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool has already been deployed this epoch\n * @param oPoolConfig The origination pool config\n * @param deploymentAddress The address of the deployment\n * @param deploymentEpoch The epoch of the deployment\n * @param deploymentTimestamp The timestamp of the deployment\n */\n error OriginationPoolAlreadyDeployedThisEpoch(\n OriginationPoolConfig oPoolConfig, address deploymentAddress, uint256 deploymentEpoch, uint256 deploymentTimestamp\n );\n\n /**\n * @notice The origination pool config id does not exist\n * @param oPoolConfigId The origination pool config id that does not exist\n */\n error OriginationPoolConfigIdDoesNotExist(OPoolConfigId oPoolConfigId);\n}\n"},"src/interfaces/IRouter/IRouterErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IRouterErrors\n * @author @SocksNFlops\n * @notice Errors for the Router contract\n */\ninterface IRouterErrors {\n /**\n * @notice Thrown when the collected amount exceeds the maximum permitted collected amount\n * @param token The token that was collected\n * @param collectedAmount The amount that was collected\n * @param maxColllected The maximum amount that can be collected\n */\n error CollectedAmountExceedsMaximum(address token, uint256 collectedAmount, uint256 maxColllected);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC-721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n * a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC-721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n * {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n * a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the address zero.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFTEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IMortgageNFTEvents\n * @author Socks&Flops\n */\ninterface IMortgageNFTEvents {\n /**\n * @notice Emitted when a mortgageId is updated\n * @param tokenId The numerical index of the mortgageNFT\n * @param mortgageId The new id of the mortgage\n */\n event MortgageIdUpdate(uint256 tokenId, string mortgageId);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n * using Panic for uint256;\n *\n * // Use any of the declared internal constants\n * function foo() { Panic.GENERIC.panic(); }\n *\n * // Alternatively\n * function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n /// @dev generic / unspecified error\n uint256 internal constant GENERIC = 0x00;\n /// @dev used by the assert() builtin\n uint256 internal constant ASSERT = 0x01;\n /// @dev arithmetic underflow or overflow\n uint256 internal constant UNDER_OVERFLOW = 0x11;\n /// @dev division or modulo by zero\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\n /// @dev enum conversion error\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n /// @dev invalid encoding in storage\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n /// @dev empty array pop\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n /// @dev array out of bounds access\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n /// @dev resource error (too large allocation or too large array)\n uint256 internal constant RESOURCE_ERROR = 0x41;\n /// @dev calling invalid internal function\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n /// @dev Reverts with a panic code. Recommended to use with\n /// the internal constants with predefined codes.\n function panic(uint256 code) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x00, 0x4e487b71)\n mstore(0x20, code)\n revert(0x1c, 0x24)\n }\n }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n /**\n * @dev Value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n /**\n * @dev An int value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedIntToUint(int256 value);\n\n /**\n * @dev Value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n /**\n * @dev An uint value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedUintToInt(uint256 value);\n\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n if (value > type(uint248).max) {\n revert SafeCastOverflowedUintDowncast(248, value);\n }\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n if (value > type(uint240).max) {\n revert SafeCastOverflowedUintDowncast(240, value);\n }\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n if (value > type(uint232).max) {\n revert SafeCastOverflowedUintDowncast(232, value);\n }\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n if (value > type(uint224).max) {\n revert SafeCastOverflowedUintDowncast(224, value);\n }\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n if (value > type(uint216).max) {\n revert SafeCastOverflowedUintDowncast(216, value);\n }\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n if (value > type(uint208).max) {\n revert SafeCastOverflowedUintDowncast(208, value);\n }\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n if (value > type(uint200).max) {\n revert SafeCastOverflowedUintDowncast(200, value);\n }\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n if (value > type(uint192).max) {\n revert SafeCastOverflowedUintDowncast(192, value);\n }\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n if (value > type(uint184).max) {\n revert SafeCastOverflowedUintDowncast(184, value);\n }\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n if (value > type(uint176).max) {\n revert SafeCastOverflowedUintDowncast(176, value);\n }\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n if (value > type(uint168).max) {\n revert SafeCastOverflowedUintDowncast(168, value);\n }\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n if (value > type(uint160).max) {\n revert SafeCastOverflowedUintDowncast(160, value);\n }\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n if (value > type(uint152).max) {\n revert SafeCastOverflowedUintDowncast(152, value);\n }\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n if (value > type(uint144).max) {\n revert SafeCastOverflowedUintDowncast(144, value);\n }\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n if (value > type(uint136).max) {\n revert SafeCastOverflowedUintDowncast(136, value);\n }\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) {\n revert SafeCastOverflowedUintDowncast(128, value);\n }\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n if (value > type(uint120).max) {\n revert SafeCastOverflowedUintDowncast(120, value);\n }\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n if (value > type(uint112).max) {\n revert SafeCastOverflowedUintDowncast(112, value);\n }\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n if (value > type(uint104).max) {\n revert SafeCastOverflowedUintDowncast(104, value);\n }\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n if (value > type(uint96).max) {\n revert SafeCastOverflowedUintDowncast(96, value);\n }\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n if (value > type(uint88).max) {\n revert SafeCastOverflowedUintDowncast(88, value);\n }\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n if (value > type(uint80).max) {\n revert SafeCastOverflowedUintDowncast(80, value);\n }\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n if (value > type(uint72).max) {\n revert SafeCastOverflowedUintDowncast(72, value);\n }\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n if (value > type(uint64).max) {\n revert SafeCastOverflowedUintDowncast(64, value);\n }\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n if (value > type(uint56).max) {\n revert SafeCastOverflowedUintDowncast(56, value);\n }\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n if (value > type(uint48).max) {\n revert SafeCastOverflowedUintDowncast(48, value);\n }\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n if (value > type(uint40).max) {\n revert SafeCastOverflowedUintDowncast(40, value);\n }\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n if (value > type(uint32).max) {\n revert SafeCastOverflowedUintDowncast(32, value);\n }\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n if (value > type(uint24).max) {\n revert SafeCastOverflowedUintDowncast(24, value);\n }\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n if (value > type(uint16).max) {\n revert SafeCastOverflowedUintDowncast(16, value);\n }\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n if (value > type(uint8).max) {\n revert SafeCastOverflowedUintDowncast(8, value);\n }\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n if (value < 0) {\n revert SafeCastOverflowedIntToUint(value);\n }\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(248, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(240, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(232, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(224, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(216, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(208, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(200, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(192, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(184, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(176, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(168, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(160, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(152, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(144, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(136, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(128, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(120, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(112, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(104, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(96, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(88, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(80, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(72, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(64, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(56, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(48, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(40, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(32, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(24, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(16, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(8, value);\n }\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n if (value > uint256(type(int256).max)) {\n revert SafeCastOverflowedUintToInt(value);\n }\n return int256(value);\n }\n\n /**\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n */\n function toUint(bool b) internal pure returns (uint256 u) {\n assembly (\"memory-safe\") {\n u := iszero(iszero(b))\n }\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/PythStructs.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\ncontract PythStructs {\n // A price with a degree of uncertainty, represented as a price +- a confidence interval.\n //\n // The confidence interval roughly corresponds to the standard error of a normal distribution.\n // Both the price and confidence are stored in a fixed-point numeric representation,\n // `x * (10^expo)`, where `expo` is the exponent.\n //\n // Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how\n // to how this price safely.\n struct Price {\n // Price\n int64 price;\n // Confidence interval around the price\n uint64 conf;\n // Price exponent\n int32 expo;\n // Unix timestamp describing when the price was published\n uint publishTime;\n }\n\n // PriceFeed represents a current aggregate price from pyth publisher feeds.\n struct PriceFeed {\n // The price ID.\n bytes32 id;\n // Latest available price\n Price price;\n // Latest available exponentially-weighted moving average price\n Price emaPrice;\n }\n\n struct TwapPriceFeed {\n // The price ID.\n bytes32 id;\n // Start time of the TWAP\n uint64 startTime;\n // End time of the TWAP\n uint64 endTime;\n // TWAP price\n Price twap;\n // Down slot ratio represents the ratio of price feed updates that were missed or unavailable\n // during the TWAP period, expressed as a fixed-point number between 0 and 1e6 (100%).\n // For example:\n // - 0 means all price updates were available\n // - 500_000 means 50% of updates were missed\n // - 1_000_000 means all updates were missed\n // This can be used to assess the quality/reliability of the TWAP calculation.\n // Applications should define a maximum acceptable ratio (e.g. 100000 for 10%)\n // and revert if downSlotsRatio exceeds it.\n uint32 downSlotsRatio;\n }\n\n // Information used to calculate time-weighted average prices (TWAP)\n struct TwapPriceInfo {\n // slot 1\n int128 cumulativePrice;\n uint128 cumulativeConf;\n // slot 2\n uint64 numDownSlots;\n uint64 publishSlot;\n uint64 publishTime;\n uint64 prevPublishTime;\n // slot 3\n int32 expo;\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/IPythEvents.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/// @title IPythEvents contains the events that Pyth contract emits.\n/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.\ninterface IPythEvents {\n /// @dev Emitted when the price feed with `id` has received a fresh update.\n /// @param id The Pyth Price Feed ID.\n /// @param publishTime Publish time of the given price update.\n /// @param price Price of the given price update.\n /// @param conf Confidence interval of the given price update.\n event PriceFeedUpdate(\n bytes32 indexed id,\n uint64 publishTime,\n int64 price,\n uint64 conf\n );\n\n /// @dev Emitted when the TWAP price feed with `id` has received a fresh update.\n /// @param id The Pyth Price Feed ID.\n /// @param startTime Start time of the TWAP.\n /// @param endTime End time of the TWAP.\n /// @param twapPrice Price of the TWAP.\n /// @param twapConf Confidence interval of the TWAP.\n /// @param downSlotsRatio Down slot ratio of the TWAP.\n event TwapPriceFeedUpdate(\n bytes32 indexed id,\n uint64 startTime,\n uint64 endTime,\n int64 twapPrice,\n uint64 twapConf,\n uint32 downSlotsRatio\n );\n}\n"},"lib/cash/src/libraries/Constants.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @title Constants\n * @author SocksNFlops\n * @notice Constants for the Cash Protocol\n */\nlibrary Constants {\n /**\n * @notice The number of basis points in a whole. Used in percentage and rate calculations.\n * @return BPS The number of basis points in a whole\n */\n uint256 public constant BPS = 10_000;\n /**\n * @notice The number of seconds per period (one month per period)\n * @return PERIOD_DURATION The number of seconds per period\n */\n uint256 public constant PERIOD_DURATION = 30 days;\n /**\n * @notice The number of periods for every year\n * @return PERIODS_PER_YEAR The number of periods for every year\n */\n uint256 public constant PERIODS_PER_YEAR = 12;\n /**\n * @notice The number of seconds after the due date that a payment is still considered on time\n * @return LATE_PAYMENT_WINDOW The number of seconds after the due date that a payment is still considered on time\n */\n uint256 public constant LATE_PAYMENT_WINDOW = 3 days;\n /**\n * @notice The maximum amount of missed payments before a mortgage can be foreclosed\n * @return MAXIMUM_MISSED_PAYMENTS The maximum amount of missed payments before a mortgage can be foreclosed\n */\n uint8 public constant MAXIMUM_MISSED_PAYMENTS = 2;\n /**\n * @notice The minimum amount borrowed for a mortgage\n * @return MINIMUM_AMOUNT_BORROWED The minimum amount borrowed for a mortgage\n */\n uint256 public constant MINIMUM_AMOUNT_BORROWED = 1e18;\n /**\n * @notice The duration of a single epoch for deploying origination pools. A new batch of origination pools is deployable every epoch.\n * @return EPOCH_DURATION The duration of a single epoch for deploying origination pools\n */\n uint256 public constant EPOCH_DURATION = 1 days;\n /**\n * @notice The offset for the epoch start time. This guarantees that every epoch starts at Friday 2am GMT every week\n * @return EPOCH_OFFSET The offset for the epoch start time\n */\n uint256 public constant EPOCH_OFFSET = 12 hours;\n /**\n * @notice The minimum permitted USDX deposit for an origination pool\n * @return MINIMUM_ORIGINATION_DEPOSIT The minimum permitted USDX deposit for an origination pool\n */\n uint256 public constant MINIMUM_ORIGINATION_DEPOSIT = 1e18;\n\n /**\n * @notice The maximum possible number of periods for a mortgage\n * @return MAX_TOTAL_PERIODS The maximum number of periods for a mortgage\n */\n uint8 public constant MAX_TOTAL_PERIODS = 244;\n}\n"},"lib/cash/src/types/enums/MortgageStatus.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @notice The status of a mortgage position\n */\nenum MortgageStatus {\n /// @notice Mortgage is active and operational, with payments being made according to the payment plan\n ACTIVE,\n /// @notice Mortgage has been foreclosed due to excessive missed payments\n FORECLOSED,\n /// @notice Mortgage has been fully paid off and redeemed by the borrower, with collateral returned\n REDEEMED\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVaultEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILiquidityVaultEvents\n * @author @SocksNFlops\n * @notice Interface for events emitted by LiquidityVaults.\n */\ninterface ILiquidityVaultEvents {\n /**\n * @notice Emitted when a user deposits assets into the vault.\n * @param user The address of the user who deposited the assets.\n * @param depositableAsset The address of the depositable asset.\n * @param amountDeposited The amount of depositable asset sent.\n * @param sharesMinted The amount of shares minted.\n */\n event Deposited(\n address indexed user, address indexed depositableAsset, uint256 amountDeposited, uint256 sharesMinted\n );\n\n /**\n * @notice Emitted when a user redeems assets from the vault.\n * @param user The address of the user who redeemed the assets.\n * @param redeemableAssets The addresses of the redeemable assets.\n * @param amountsRedeemed The amounts of redeemable assets received.\n * @param sharesBurned The amount of shares burned.\n */\n event Redeemed(\n address indexed user, address[] indexed redeemableAssets, uint256[] amountsRedeemed, uint256 sharesBurned\n );\n\n /**\n * @notice Emitted when the whitelist is enforced.\n * @param enforced Whether the whitelist is enforced.\n */\n event WhitelistEnforced(bool enforced);\n\n /**\n * @notice Emitted when the redeemable assets are updated.\n * @param redeemableAssets The addresses of the redeemable assets.\n */\n event RedeemableAssetsUpdated(address[] indexed redeemableAssets);\n\n /**\n * @notice Emitted when the depositable assets are updated.\n * @param depositableAssets The addresses of the depositable assets.\n */\n event DepositableAssetsUpdated(address[] indexed depositableAssets);\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVaultErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILiquidityVaultErrors\n * @author @SocksNFlops\n * @notice Interface for errors emitted by LiquidityVaults.\n */\ninterface ILiquidityVaultErrors {\n /**\n * @notice Thrown when the depositable asset is not in the depositable assets list\n * @param asset The address of the asset that is not depositable\n */\n error AssetNotDepositable(address asset);\n}\n"},"lib/cash/src/interfaces/IPausable/IPausableErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IPausableErrors\n * @author @SocksNFlops\n * @notice Errors for the pausable contract\n */\ninterface IPausableErrors {\n /**\n * @notice Error for paused pool\n */\n error Paused();\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVaultEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IMultiTokenVaultEvents {\n /**\n * @notice Emitted when a new token is added to the MultiTokenVault\n * @param token The address of the token that was added\n */\n event TokenAdded(address indexed token);\n\n /**\n * @notice Emitted when a token is removed from the MultiTokenVault\n * @param token The address of the token that was removed\n */\n event TokenRemoved(address indexed token);\n\n /**\n * @notice Emitted when an account deposits a token\n * @param account The address of the account that deposited\n * @param token The address of the token that was deposited\n * @param amount The amount of the token that was deposited\n * @param mintAmount The amount that was minted from the deposit\n */\n event Deposit(address indexed account, address indexed token, uint256 amount, uint256 mintAmount);\n\n /**\n * @notice Emitted when an account withdraws a token\n * @param account The address of the account that withdrew\n * @param token The address of the token that was withdrawn\n * @param amount The amount of the token that was withdrawn\n * @param burnAmount The amount that was burned from the withdraw\n */\n event Withdraw(address indexed account, address indexed token, uint256 amount, uint256 burnAmount);\n\n /**\n * @notice Emitted when the maximum cap for a token is set\n * @param token The address of the token that was set\n * @param maximumCap The new maximum cap for the token denominated in the UOA.\n */\n event MaximumCapSet(address indexed token, uint256 maximumCap);\n}\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVaultErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IMultiTokenVaultErrors {\n /**\n * @notice Thrown when a token is the zero address\n */\n error TokenIsZeroAddress();\n\n /**\n * @notice Thrown when a token is already supported by the MultiTokenVault\n * @param token The address of the token that is already supported\n */\n error TokenAlreadySupported(address token);\n\n /**\n * @notice Thrown when a token is not supported by the MultiTokenVault\n * @param token The address of the token that is not supported\n */\n error TokenNotSupported(address token);\n\n /**\n * @notice Thrown when a deposit/withdraw is too small that no tokens will be minted/burned\n * @param amount The amount of tokens being deposited/withdrawn\n */\n error AmountTooSmall(uint256 amount);\n\n /**\n * @notice Thrown when a token's maximum cap is exceeded\n * @param token The address of the token that exceeded its cap\n * @param amount The total amount of tokens deposited\n * @param maximumCap The maximum allowed amount for this token\n */\n error MaxmimumCapExceeded(address token, uint256 amount, uint256 maximumCap);\n}\n"},"lib/cash/src/interfaces/IRebasingERC20/IRebasingERC20.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IRebasingERC20Events} from \"./IRebasingERC20Events.sol\";\n\ninterface IRebasingERC20 is IERC20, IRebasingERC20Events {\n /**\n * @notice The total amount of the shares token\n * @return The total amount of the shares token\n */\n function totalShares() external view returns (uint256);\n\n /**\n * @notice Converts the amount of underlying token to the corresponding amount of shares\n * @param assets The amount of underlying token\n * @return The corresponding amount of shares\n */\n function convertToShares(uint256 assets) external view returns (uint256);\n\n /**\n * @notice Converts the amount of shares to the corresponding amount of underlying token\n * @param shares The amount of shares\n * @return The corresponding amount of underlying token\n */\n function convertToAssets(uint256 shares) external view returns (uint256);\n\n /**\n * @notice The amount of shares that the account has\n * @param account The address of the account\n * @return The amount of shares that the account has\n */\n function sharesOf(address account) external view returns (uint256);\n\n /**\n * @notice The decimals offset. The number of decimals to offset the shares by. Used to protect against inflation attacks.\n * @return The decimals offset\n */\n function decimalsOffset() external view returns (uint8);\n}\n"},"lib/cash/src/interfaces/IRebasingERC20/IRebasingERC20Events.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IRebasingERC20Events is IERC20 {\n /**\n * @notice Emitted when shares/balances are transferred\n * @param from The address of the sender\n * @param to The address of the recipient\n * @param amount The amount of shares transferred\n * @param shares The amount of shares transferred\n */\n event TransferShares(address indexed from, address indexed to, uint256 amount, uint256 shares);\n}\n"}},"settings":{"remappings":["forge-std/=lib/forge-std/src/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@core/=lib/cash/src/","@hyper-evm-lib/=lib/hyper-evm-lib/","@mock-contracts/=lib/cash/lib/mock-contracts/src/","@pythnetwork/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/","cash/=lib/cash/","createx/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/createx/src/","ds-test/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/","hyper-evm-lib/=lib/hyper-evm-lib/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin-foundry-upgrades/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades/src/","pyth-crosschain/=lib/cash/lib/pyth-crosschain/","solady/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/createx/lib/solady/","solidity-stringutils/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.bytecode.sourceMap","evm.bytecode.linkReferences","evm.deployedBytecode.object","evm.deployedBytecode.sourceMap","evm.deployedBytecode.linkReferences","evm.deployedBytecode.immutableReferences","evm.methodIdentifiers","metadata"]}},"evmVersion":"prague","viaIR":false,"libraries":{}}} +{"language":"Solidity","sources":{"src/Router.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {ILoanManager} from \"@core/interfaces/ILoanManager/ILoanManager.sol\";\nimport {IGeneralManager, IGeneralManagerErrors} from \"@core/interfaces/IGeneralManager/IGeneralManager.sol\";\nimport {Context} from \"@openzeppelin/contracts/utils/Context.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IOriginationPool, IOriginationPoolErrors} from \"@core/interfaces/IOriginationPool/IOriginationPool.sol\";\nimport {IPriceOracle} from \"@core/interfaces/IPriceOracle.sol\";\nimport {IConsol} from \"@core/interfaces/IConsol/IConsol.sol\";\nimport {ISubConsol} from \"@core/interfaces/ISubConsol/ISubConsol.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {IUSDX} from \"@core/interfaces/IUSDX/IUSDX.sol\";\nimport {CreationRequest} from \"@core/types/orders/OrderRequests.sol\";\nimport {IWNT} from \"./interfaces/IWNT.sol\";\nimport {OPoolConfigId} from \"@core/types/OPoolConfigId.sol\";\nimport {\n IOriginationPoolScheduler,\n IOriginationPoolSchedulerErrors\n} from \"@core/interfaces/IOriginationPoolScheduler/IOriginationPoolScheduler.sol\";\nimport {IRouter} from \"./interfaces/IRouter/IRouter.sol\";\nimport {IMortgageNFT} from \"@core/interfaces/IMortgageNFT/IMortgageNFT.sol\";\nimport {IMortgageNFTErrors} from \"@core/interfaces/IMortgageNFT/IMortgageNFTErrors.sol\";\nimport {IERC20Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {IPyth} from \"@pythnetwork/IPyth.sol\";\nimport {PythErrors} from \"@pythnetwork/PythErrors.sol\";\nimport {MortgageMath} from \"@core/libraries/MortgageMath.sol\";\nimport {MortgagePosition} from \"@core/types/MortgagePosition.sol\";\nimport {ILiquidityVault} from \"./interfaces/ILiquidityVault/ILiquidityVault.sol\";\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title Router\n * @author @SocksNFlops\n * @notice This contract facilitates user interactions with core contracts of the Cash protocol.\n */\ncontract Router is\n IRouter,\n Context,\n IMortgageNFTErrors,\n IERC20Errors,\n IGeneralManagerErrors,\n IOriginationPoolErrors,\n IOriginationPoolSchedulerErrors\n{\n using SafeERC20 for IERC20;\n using MortgageMath for MortgagePosition;\n using PythErrors for IPyth;\n\n /// @inheritdoc IRouter\n address public immutable generalManager;\n /// @inheritdoc IRouter\n address public immutable rolloverVault;\n /// @inheritdoc IRouter\n address public immutable fulfillmentVault;\n /// @inheritdoc IRouter\n address public immutable pyth;\n /// @inheritdoc IRouter\n address public immutable wrappedNativeToken;\n /// @inheritdoc IRouter\n address public immutable usdx;\n /// @inheritdoc IRouter\n address public immutable consol;\n /// @inheritdoc IRouter\n address public immutable originationPoolScheduler;\n\n /**\n * @param _wrappedNativeToken The address of the wrapped native token (i.e., whype: 0x555...)\n * @param _generalManager The address of the general manager contract\n * @param _rolloverVault The address of the rollover vault contract\n * @param _fulfillmentVault The address of the fulfillment vault contract\n * @param _pyth The address of the Pyth contract\n */\n constructor(\n address _wrappedNativeToken,\n address _generalManager,\n address _rolloverVault,\n address _fulfillmentVault,\n address _pyth\n ) {\n wrappedNativeToken = _wrappedNativeToken;\n generalManager = _generalManager;\n rolloverVault = _rolloverVault;\n fulfillmentVault = _fulfillmentVault;\n pyth = _pyth;\n usdx = IGeneralManager(_generalManager).usdx();\n consol = IGeneralManager(_generalManager).consol();\n originationPoolScheduler = IGeneralManager(_generalManager).originationPoolScheduler();\n\n // Auto-approve the tokens to be spent by the consol/generalManager contracts\n IWNT(wrappedNativeToken).approve(generalManager, type(uint256).max);\n IUSDX(usdx).approve(consol, type(uint256).max);\n IConsol(consol).approve(generalManager, type(uint256).max);\n IUSDX(usdx).approve(generalManager, type(uint256).max);\n }\n\n receive() external payable {}\n\n /**\n * @inheritdoc IRouter\n */\n function approveCollaterals() external {\n address[] memory consolInputTokens = IConsol(consol).getSupportedTokens();\n // Iterate over consolInputTokens to find which are SubConsol tokens\n for (uint256 i = 0; i < consolInputTokens.length; i++) {\n if (IERC165(consolInputTokens[i]).supportsInterface(type(ISubConsol).interfaceId)) {\n // Fetch the collateral out of the SubConsol and max approve it to be spent by the generalManager\n address collateral = ISubConsol(consolInputTokens[i]).collateral();\n IERC20(collateral).approve(address(generalManager), type(uint256).max);\n }\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function approveUsdTokens() external {\n address[] memory usdTokens = IUSDX(usdx).getSupportedTokens();\n // Iterate over usdTokens and approve them to be spent by the USDX contract\n for (uint256 i = 0; i < usdTokens.length; i++) {\n IERC20(usdTokens[i]).approve(address(usdx), type(uint256).max);\n }\n }\n\n /**\n * @dev Internal function to pull in USDX via the underlying usdToken\n * @param usdToken The address of the usdToken to pull in\n * @param usdxAmount The amount of USDX to pull in\n */\n function _pullUsdToken(address usdToken, uint256 usdxAmount) internal {\n if (usdToken == address(usdx)) {\n // Don't need to wrap USDX\n // Pull in the USDX from the user\n IERC20(usdToken).safeTransferFrom(_msgSender(), address(this), usdxAmount);\n } else {\n // Need to wrap token into USDX\n // Calculate how much usdToken to pull in from the user\n uint256 usdTokenAmount = IUSDX(usdx).convertUnderlying(usdToken, usdxAmount);\n\n // Pull in the usdToken from the user\n IERC20(usdToken).safeTransferFrom(_msgSender(), address(this), usdTokenAmount);\n\n // Deposit the usdToken into the USDX contract\n IUSDX(usdx).deposit(usdToken, usdTokenAmount);\n }\n }\n\n /**\n * @dev Internal function to pull in Consol via the underlying usdTokens, USDX, SubConsols, or ForfeitedAssetsPool\n * @param inputToken The address of the input token to pull in\n * @param consolAmount The amount of Consol to pull in\n */\n function _pullInConsol(address inputToken, uint256 consolAmount) internal {\n if (inputToken == address(consol)) {\n // Input token is Consol\n // Pull in the Consol from the user\n IERC20(consol).safeTransferFrom(_msgSender(), address(this), consolAmount);\n } else {\n // Need to wrap token into USDX and then Consol\n // Calculate how much usdx is needed\n uint256 usdxAmount = IConsol(consol).convertUnderlying(usdx, consolAmount);\n // Pull in the usdToken from the user and convert it to USDX\n _pullUsdToken(inputToken, usdxAmount);\n // Deposit the USDX into Consol\n IConsol(consol).deposit(address(usdx), consolAmount);\n }\n }\n\n /**\n * @dev Internal function to pull in collateral\n * @param collateral The address of the collateral token to pull in\n * @param collateralCollected The amount of collateral to pull in\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n */\n function _pullCollateral(address collateral, uint256 collateralCollected, bool isNative) internal {\n if (isNative && collateral == address(wrappedNativeToken)) {\n // If you're paying with the native token, needs to be wrapped into the wrappedNativeToken first\n IWNT(wrappedNativeToken).deposit{value: collateralCollected}();\n } else {\n // Otherwise, pull in the collateral directly from the user\n IERC20(collateral).safeTransferFrom(_msgSender(), address(this), collateralCollected);\n }\n }\n\n /**\n * @dev Internal function to calculate the cost of a borrowing the collateral amount (including the price spread)\n * @param collateral The address of the collateral token\n * @param collateralAmount The amount of collateral to calculate the cost for\n * @return cost The cost of the collateral amount (including the price spread)\n * @return collateralDecimals The decimals of the collateral token\n */\n function _calculateCost(address collateral, uint256 collateralAmount)\n internal\n view\n returns (uint256 cost, uint8 collateralDecimals)\n {\n IPriceOracle priceOracle = IPriceOracle(IGeneralManager(generalManager).priceOracles(collateral));\n (cost, collateralDecimals) = priceOracle.cost(collateralAmount);\n\n // Get the price spread\n uint16 priceSpread = IGeneralManager(generalManager).priceSpread();\n\n // Add the price spread to the cost\n cost = Math.mulDiv(cost, 1e4 + priceSpread, 1e4);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function calculateCollectedAmounts(CreationRequest calldata creationRequest)\n public\n view\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n if (creationRequest.base.isCompounding) {\n for (uint256 i = 0; i < creationRequest.base.originationPools.length; i++) {\n // If compounding, need to collect 1/2 of the collateral amount + commission fee (this is in the form of collateral)\n collateralCollected += IOriginationPool(creationRequest.base.originationPools[i])\n .calculateReturnAmount((creationRequest.base.collateralAmounts[i] + 1) / 2);\n (uint256 _cost, uint8 _collateralDecimals) =\n _calculateCost(creationRequest.collateral, creationRequest.base.collateralAmounts[i] / 2);\n collateralDecimals = _collateralDecimals;\n paymentAmount += (2 * _cost)\n - IOriginationPool(creationRequest.base.originationPools[i]).calculateReturnAmount(_cost);\n }\n } else {\n for (uint256 i = 0; i < creationRequest.base.originationPools.length; i++) {\n // If non-compounding, need to collect the full amountBorrowed in USDX + commission fee\n (uint256 _cost, uint8 _collateralDecimals) =\n _calculateCost(creationRequest.collateral, creationRequest.base.collateralAmounts[i]);\n paymentAmount += _cost;\n collateralDecimals = _collateralDecimals;\n usdxCollected += IOriginationPool(creationRequest.base.originationPools[i]).calculateReturnAmount(_cost / 2);\n if (_cost % 2 == 1) {\n usdxCollected += 1;\n }\n }\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function updatePriceFeedsAndRequestMortgage(\n bytes[] calldata priceUpdates,\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n public\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n // Fetch the update fees\n uint256 updateFee = IPyth(pyth).getUpdateFee(priceUpdates);\n\n // Fetch the Pyth contract\n IPyth(pyth).updatePriceFeeds{value: updateFee}(priceUpdates);\n\n return requestMortgage(usdToken, creationRequest, isNative, maxCollected);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function requestMortgage(\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n public\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals)\n {\n (collateralCollected, usdxCollected, paymentAmount, collateralDecimals) = calculateCollectedAmounts(creationRequest);\n\n if (collateralCollected > 0) {\n if (collateralCollected > maxCollected) {\n revert CollectedAmountExceedsMaximum(creationRequest.collateral, collateralCollected, maxCollected);\n }\n _pullCollateral(creationRequest.collateral, collateralCollected, isNative);\n }\n\n if (usdxCollected > 0) {\n if (usdxCollected > maxCollected) {\n revert CollectedAmountExceedsMaximum(usdToken, usdxCollected, maxCollected);\n }\n _pullUsdToken(usdToken, usdxCollected);\n }\n\n uint256 tokenId =\n IGeneralManager(generalManager).requestMortgageCreation{value: address(this).balance}(creationRequest);\n\n // Transfer the mortgageNFT to the user\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(address(this), _msgSender(), tokenId);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function periodPay(address inputToken, uint256 tokenId, uint256 inputAmount) external {\n // Convert the inputAmount to Consol\n uint256 consolAmount = convert(inputToken, consol, inputAmount);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, consolAmount);\n\n // Make the period payment on Consol\n address loanManager = IGeneralManager(generalManager).loanManager();\n IConsol(consol).approve(loanManager, consolAmount);\n ILoanManager(loanManager).periodPay(tokenId, consolAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function penaltyPay(address inputToken, uint256 tokenId, uint256 inputAmount) external {\n // Convert the inputAmount to Consol\n uint256 consolAmount = convert(inputToken, consol, inputAmount);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, consolAmount);\n\n // Make the penalty payment on Consol\n address loanManager = IGeneralManager(generalManager).loanManager();\n IConsol(consol).approve(loanManager, consolAmount);\n ILoanManager(loanManager).penaltyPay(tokenId, consolAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function refinance(address inputToken, uint256 tokenId, uint8 newTotalPeriods) external {\n // Fetch the loan manager\n address loanManager = IGeneralManager(generalManager).loanManager();\n\n // Fetch the mortgage position\n MortgagePosition memory mortgagePosition = ILoanManager(loanManager).getMortgagePosition(tokenId);\n\n // Fetch the refinance rate\n uint256 refinanceRate = IGeneralManager(generalManager).refinanceRate(mortgagePosition);\n\n // Calculate the refinance fee\n uint256 refinanceFee = Math.mulDiv(mortgagePosition.principalRemaining(), refinanceRate, 1e4, Math.Rounding.Ceil);\n\n // Pull in inputToken and wrap into Consol\n _pullInConsol(inputToken, refinanceFee);\n\n // Transfer the mortgageNFT to the router\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(_msgSender(), address(this), tokenId);\n\n // Call `refinanceMortgage` on the loan manager\n IConsol(consol).approve(loanManager, refinanceFee);\n ILoanManager(loanManager).refinanceMortgage(tokenId, newTotalPeriods);\n\n // Return the mortgageNFT to the user\n IMortgageNFT(IGeneralManager(generalManager).mortgageNFT()).transferFrom(address(this), _msgSender(), tokenId);\n }\n\n /**\n * @dev Internal function to get or create the latest origination pool for a given OPoolConfigId\n * @param oPoolConfigId The OPoolConfigId of the origination pool config\n * @return originationPool The origination pool\n */\n function _getOrCreateOriginationPool(OPoolConfigId oPoolConfigId)\n internal\n returns (IOriginationPool originationPool)\n {\n originationPool = IOriginationPool(\n IOriginationPoolScheduler(originationPoolScheduler).predictOriginationPool(oPoolConfigId)\n );\n if (!IOriginationPoolScheduler(originationPoolScheduler).isRegistered(address(originationPool))) {\n IOriginationPool(IOriginationPoolScheduler(originationPoolScheduler).deployOriginationPool(oPoolConfigId));\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function originationPoolDeposit(OPoolConfigId oPoolConfigId, address usdToken, uint256 usdTokenAmount) external {\n // Convert the usdTokenAmount to USDX\n uint256 usdxAmount = convert(usdToken, usdx, usdTokenAmount);\n\n // Fetch the origination pool\n IOriginationPool originationPool = _getOrCreateOriginationPool(oPoolConfigId);\n\n // Pull in the usdToken from the user\n _pullUsdToken(usdToken, usdxAmount);\n\n // Deposit the USDX into the origination pool\n IUSDX(usdx).approve(address(originationPool), usdxAmount);\n originationPool.deposit(usdxAmount);\n\n // Transfer the originationPool receipt tokens to the user\n originationPool.transfer(msg.sender, originationPool.balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IRouter\n */\n function convert(address inputToken, address outputToken, uint256 inputAmount)\n public\n view\n returns (uint256 outputAmount)\n {\n // Check if input and output tokens are the same\n if (inputToken == outputToken) {\n outputAmount = inputAmount;\n }\n // If the input is Consol, then recurse from (Consol -> USDX) -> outputToken\n else if (inputToken == address(consol)) {\n // If the inputToken is Consol, convert it to USDX\n outputAmount = convert(address(usdx), outputToken, IConsol(consol).convertUnderlying(usdx, inputAmount));\n }\n // If the output token is Consol, then recurse from (inputToken -> USDX) -> Consol\n else if (outputToken == address(consol)) {\n outputAmount = IConsol(consol).convertAmount(usdx, convert(inputToken, usdx, inputAmount));\n }\n // If the input is USDX, then the outputToken is a usdToken\n else if (inputToken == address(usdx)) {\n outputAmount = IUSDX(usdx).convertUnderlying(outputToken, inputAmount);\n }\n // Output token must be USDX, meaning the input token is a usdToken\n else {\n outputAmount = IUSDX(usdx).convertAmount(inputToken, inputAmount);\n }\n }\n\n /**\n * @inheritdoc IRouter\n */\n function wrap(address inputToken, address outputToken, uint256 inputAmount) public {\n // Check if input and output tokens are the same. If so, don't do anything\n if (inputToken == outputToken) {\n return;\n } else if (inputAmount == 0) {\n return;\n }\n // Pull in the input token\n IERC20(inputToken).safeTransferFrom(_msgSender(), address(this), inputAmount);\n\n // If the inputToken isn't USDX, it must be a usdToken. Deposit it into USDX\n if (inputToken != address(usdx)) {\n IUSDX(usdx).deposit(inputToken, inputAmount);\n }\n\n // If the outputToken is Consol, then we must do one more wrapping\n if (outputToken == address(consol)) {\n // Fetch the new inputAmount\n inputAmount = IUSDX(usdx).balanceOf(address(this));\n // Convert the USDX to Consol\n IConsol(consol).deposit(address(usdx), inputAmount);\n }\n\n // Transfer the output token to the user\n IERC20(outputToken).safeTransfer(_msgSender(), IERC20(outputToken).balanceOf(address(this)));\n }\n\n /**\n * @dev Internal function to deposit into a liquidity vault\n * @param vault The address of the liquidity vault to deposit into\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function _vaultDeposit(address vault, address usdToken, uint256 usdTokenAmount) internal {\n if (\n ILiquidityVault(vault).whitelistEnforced()\n && !IAccessControl(vault).hasRole(ILiquidityVault(vault).WHITELIST_ROLE(), _msgSender())\n ) {\n revert VaultWhitelistEnforced(vault, _msgSender());\n }\n\n // Convert the usdTokenAmount to USDX\n uint256 usdxAmount = convert(usdToken, usdx, usdTokenAmount);\n\n // Pull in the usdToken from the user\n _pullUsdToken(usdToken, usdxAmount);\n\n // Deposit the USDX into the vault\n IUSDX(usdx).approve(vault, usdxAmount);\n ILiquidityVault(vault).deposit(usdx, usdxAmount);\n\n // Transfer the vault share tokens to the user\n ILiquidityVault(vault).transfer(_msgSender(), ILiquidityVault(vault).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IRouter\n */\n function rolloverVaultDeposit(address usdToken, uint256 usdTokenAmount) external {\n _vaultDeposit(rolloverVault, usdToken, usdTokenAmount);\n }\n\n /**\n * @inheritdoc IRouter\n */\n function fulfillmentVaultDeposit(address usdToken, uint256 usdTokenAmount) external {\n _vaultDeposit(fulfillmentVault, usdToken, usdTokenAmount);\n }\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManager.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgagePosition} from \"../../types/MortgagePosition.sol\";\nimport {MortgageParams} from \"../../types/orders/MortgageParams.sol\";\nimport {ILoanManagerEvents} from \"./ILoanManagerEvents.sol\";\nimport {ILoanManagerErrors} from \"./ILoanManagerErrors.sol\";\nimport {IConsolFlashSwap} from \"../IConsolFlashSwap.sol\";\n\n/**\n * @title ILoanManager\n * @author Socks&Flops\n * @notice Interface for the LoanManager contract\n */\ninterface ILoanManager is ILoanManagerEvents, ILoanManagerErrors, IConsolFlashSwap {\n /**\n * @notice Returns the Consol token address\n * @return The Consol token address\n */\n function consol() external view returns (address);\n\n /**\n * @notice Returns the general manager address\n * @return The general manager address\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Returns the mortgage NFT address\n * @return The NFT address\n */\n function nft() external view returns (address);\n\n /**\n * @notice Creates a new mortgage position\n * @param mortgageParams The parameters for the mortgage position\n */\n function createMortgage(MortgageParams memory mortgageParams) external;\n\n /**\n * @notice Returns the mortgage position for a given tokenId\n * @param tokenId The tokenId of the mortgage position\n * @return The mortgage position\n */\n function getMortgagePosition(uint256 tokenId) external view returns (MortgagePosition memory);\n\n /**\n * @notice Imposes applicable penalties to a mortgage position\n * @param tokenId The tokenId of the mortgage position\n */\n function imposePenalty(uint256 tokenId) external;\n\n /**\n * @notice Pays the monthly payment for a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount to pay\n */\n function periodPay(uint256 tokenId, uint256 amount) external;\n\n /**\n * @notice Pays the penalty for a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount to pay\n */\n function penaltyPay(uint256 tokenId, uint256 amount) external;\n\n /**\n * @notice Redeems a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param async Whether to allow redemption to be asynchronous\n */\n function redeemMortgage(uint256 tokenId, bool async) external;\n\n /**\n * @notice Refinances a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param totalPeriods The total number of periods that the mortgage is being refinanced to.\n */\n function refinanceMortgage(uint256 tokenId, uint8 totalPeriods) external;\n\n /**\n * @notice Forecloses a mortgage position\n * @param tokenId The tokenId of the mortgage position\n */\n function forecloseMortgage(uint256 tokenId) external;\n\n /**\n * @notice Converts a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param currentPrice The current price of the collateral\n * @param amount The amount of the principal being coverted\n * @param collateralAmount The amount of the collateral being withdrawn during the conversion\n * @param receiver The address receiving the converted assets\n */\n function convertMortgage(\n uint256 tokenId,\n uint256 currentPrice,\n uint256 amount,\n uint256 collateralAmount,\n address receiver\n ) external;\n\n /**\n * @notice Expands the balance sheet of a mortgage position by adding addtional principal and collateral to the mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amountIn The amount of the principal being added to the mortgage position\n * @param collateralAmountIn The amount of collateral being added to the mortgage position\n * @param newInterestRate The new interest rate of the mortgage position\n */\n function expandBalanceSheet(uint256 tokenId, uint256 amountIn, uint256 collateralAmountIn, uint16 newInterestRate)\n external;\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManager.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IGeneralManagerEvents} from \"./IGeneralManagerEvents.sol\";\nimport {IGeneralManagerErrors} from \"./IGeneralManagerErrors.sol\";\nimport {MortgagePosition} from \"../../types/MortgagePosition.sol\";\nimport {CreationRequest, ExpansionRequest} from \"../../types/orders/OrderRequests.sol\";\nimport {IOriginationPoolDeployCallback} from \"../IOriginationPoolDeployCallback.sol\";\nimport {OriginationParameters} from \"../../types/orders/OriginationParameters.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\n\n/**\n * @title IGeneralManager\n * @author @SocksNFlops\n * @notice The GeneralManager contract is responsible for managing the mortgage positions and the foreclosure process.\n */\ninterface IGeneralManager is IOriginationPoolDeployCallback, IPausable, IGeneralManagerEvents, IGeneralManagerErrors {\n /**\n * @notice Returns the USDX token address\n * @return The USDX token address\n */\n function usdx() external view returns (address);\n\n /**\n * @notice Returns the Consol token address\n * @return The Consol token address\n */\n function consol() external view returns (address);\n\n /**\n * @notice Sets the penalty rate for a mortgage (in basis points)\n * @param penaltyRate_ The penalty rate\n */\n function setPenaltyRate(uint16 penaltyRate_) external;\n\n /**\n * @notice Returns the penalty rate for a mortgage (in basis points)\n * @dev Takes in a mortgage position to allow upgraded implementations to take into account the position's details.\n * @param mortgagePosition The position of the mortgage\n * @return The penalty rate\n */\n function penaltyRate(MortgagePosition memory mortgagePosition) external view returns (uint16);\n\n /**\n * @notice Sets the refinance rate for a mortgage (in basis points)\n * @param refinanceRate_ The refinance rate\n */\n function setRefinanceRate(uint16 refinanceRate_) external;\n\n /**\n * @notice Returns the refinance rate (in basis points).\n * @dev Takes in a mortgage position to allow upgraded implementations to take into account the position's details.\n * @param mortgagePosition The position of the mortgage\n * @return The refinance rate\n */\n function refinanceRate(MortgagePosition memory mortgagePosition) external view returns (uint16);\n\n /**\n * @notice Sets the insurance fund address\n * @param insuranceFund_ The insurance fund address\n */\n function setInsuranceFund(address insuranceFund_) external;\n\n /**\n * @notice Returns the insurance fund address\n * @return The insurance fund address\n */\n function insuranceFund() external view returns (address);\n\n /**\n * @notice Returns the interest rate oracle address\n * @return The interest rate oracle address\n */\n function interestRateOracle() external view returns (address);\n\n /**\n * @notice Sets the interest rate oracle address\n * @param interestRateOracle_ The interest rate oracle address\n */\n function setInterestRateOracle(address interestRateOracle_) external;\n\n /**\n * @notice Returns the interest rate (in basis points)\n * @param collateral The address of the collateral\n * @param totalPeriods The total number of periods for the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The interest rate\n */\n function interestRate(address collateral, uint8 totalPeriods, bool hasPaymentPlan) external view returns (uint16);\n\n /**\n * @notice Returns the conversion premium rate (in basis points)\n * @param collateral The address of the collateral\n * @param totalPeriods The total number of periods for the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The conversion premium rate\n */\n function conversionPremiumRate(address collateral, uint8 totalPeriods, bool hasPaymentPlan)\n external\n view\n returns (uint16);\n\n /**\n * @notice Sets the conversion premium rate (in basis points)\n * @param conversionPremiumRate_ The conversion premium rate\n */\n function setConversionPremiumRate(uint16 conversionPremiumRate_) external;\n\n /**\n * @notice Sets the origination pool scheduler address\n * @param originationPoolScheduler_ The origination pool scheduler address\n */\n function setOriginationPoolScheduler(address originationPoolScheduler_) external;\n\n /**\n * @notice Returns the origination pool scheduler address\n * @return The origination pool scheduler address\n */\n function originationPoolScheduler() external view returns (address);\n\n /**\n * @notice Sets the loan manager address\n * @param loanManager_ The loan manager address\n */\n function setLoanManager(address loanManager_) external;\n\n /**\n * @notice Returns the loan manager address\n * @return The loan manager address\n */\n function loanManager() external view returns (address);\n\n /**\n * @notice Returns the mortgage NFT address\n * @return The mortgage NFT address\n */\n function mortgageNFT() external view returns (address);\n\n /**\n * @notice Sets the order pool address\n * @param orderPool_ The order pool address\n */\n function setOrderPool(address orderPool_) external;\n\n /**\n * @notice Returns the order pool address\n * @return The order pool address\n */\n function orderPool() external view returns (address);\n\n /**\n * @notice Updates the supported mortgage period terms for a collateral.\n * @param collateral The address of the collateral\n * @param totalPeriods The new total number of periods for the new mortgage term\n * @param isSupported Whether the mortgage period term is supported\n */\n function updateSupportedMortgagePeriodTerms(address collateral, uint8 totalPeriods, bool isSupported) external;\n\n /**\n * @notice Returns whether a mortgage period term is supported\n * @param collateral The address of the collateral\n * @param mortgagePeriods The mortgage period\n * @return Whether the mortgage period term is supported\n */\n function isSupportedMortgagePeriodTerms(address collateral, uint8 mortgagePeriods) external view returns (bool);\n\n /**\n * @notice The address of the price oracle for the collateral\n * @param collateral The address of the collateral\n * @return The address of the price oracle\n */\n function priceOracles(address collateral) external view returns (address);\n\n /**\n * @notice Sets the address of the price oracle\n * @param collateral The address of the collateral\n * @param priceOracle The address of the price oracle\n */\n function setPriceOracle(address collateral, address priceOracle) external;\n\n /**\n * @notice Returns the minimum request size of a mortgage for a given collateral. Requests cannot borrow less than this amount.\n * @param collateral The address of the collateral\n * @return The minimum cap\n */\n function minimumCap(address collateral) external view returns (uint256);\n\n /**\n * @notice Sets the minimum request size of a mortgage for a given collateral. Requests cannot borrow less than this amount.\n * @param collateral The address of the collateral\n * @param minimumCap_ The minimum cap\n */\n function setMinimumCap(address collateral, uint256 minimumCap_) external;\n\n /**\n * @notice Returns the maximum request size of a mortgage for a given collateral. Requests cannot borrow more than this amount.\n * @param collateral The address of the collateral\n * @return The maximum cap\n */\n function maximumCap(address collateral) external view returns (uint256);\n\n /**\n * @notice Sets the maximum request size of a mortgage for a given collateral. Requests cannot borrow more than this amount.\n * @param collateral The address of the collateral\n * @param maximumCap_ The maximum cap\n */\n function setMaximumCap(address collateral, uint256 maximumCap_) external;\n\n /**\n * @notice The price spread to incentivize the fulfiller to fill orders\n * @return priceSpread The price spread\n */\n function priceSpread() external view returns (uint16);\n\n /**\n * @notice Sets the price spread to incentivize the fulfiller to fill orders\n * @param priceSpread_ The price spread\n */\n function setPriceSpread(uint16 priceSpread_) external;\n\n /**\n * @notice Returns the conversion queues a given mortgage position is registered with\n * @param tokenId The tokenId of the mortgage position\n * @return The conversion queues\n */\n function conversionQueues(uint256 tokenId) external view returns (address[] memory);\n\n /**\n * @notice Requests a new mortgage creation\n * @param creationRequest The parameters of the mortgage creation being requested\n * @return tokenId The tokenId of the mortgage NFT that was created\n */\n function requestMortgageCreation(CreationRequest calldata creationRequest) external payable returns (uint256 tokenId);\n\n /**\n * @notice Burns a mortgage NFT\n * @param tokenId The tokenId of the mortgage NFT to burn\n */\n function burnMortgageNFT(uint256 tokenId) external;\n\n /**\n * @notice Originates a mortgage position. Only callable by the OrderPool.\n * @param originationParameters The parameters for originating a mortgage creation or balance sheet expansion\n */\n function originate(OriginationParameters calldata originationParameters) external payable;\n\n /**\n * @notice Enqueues a mortgage position into a conversion queue\n * @param tokenId The tokenId of the mortgage position\n * @param conversionQueueList The list of conversion queues to use\n * @param hintPrevIds The hint for the previous mortgage position in the conversion queue\n */\n function enqueueMortgage(uint256 tokenId, address[] memory conversionQueueList, uint256[] memory hintPrevIds)\n external\n payable;\n\n /**\n * @notice Converts a mortgage position\n * @param tokenId The tokenId of the mortgage position\n * @param amount The amount of the principal being coverted\n * @param collateralAmount The amount of the collateral being withdrawn during the conversion\n * @param receiver The address receiving the converted collateral\n */\n function convert(uint256 tokenId, uint256 amount, uint256 collateralAmount, address receiver) external;\n\n /**\n * @notice Requests to expand the balance sheet of a mortgage position by adding additional principal and collateral to the mortgage position. Only callable by whitelisted addresses.\n * @param expansionRequest The parameters of the balance sheet expansion being requested\n */\n function requestBalanceSheetExpansion(ExpansionRequest calldata expansionRequest) external payable;\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the value of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the value of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\n * allowance mechanism. `value` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n /**\n * @dev An operation with an ERC-20 token failed.\n */\n error SafeERC20FailedOperation(address token);\n\n /**\n * @dev Indicates a failed `decreaseAllowance` request.\n */\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n }\n\n /**\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n */\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n forceApprove(token, spender, oldAllowance + value);\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n * value, non-reverting calls are assumed to be successful.\n *\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n unchecked {\n uint256 currentAllowance = token.allowance(address(this), spender);\n if (currentAllowance < requestedDecrease) {\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n }\n forceApprove(token, spender, currentAllowance - requestedDecrease);\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n *\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n * set here.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n safeTransfer(token, to, value);\n } else if (!token.transferAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * Reverts if the returned value is other than `true`.\n */\n function transferFromAndCallRelaxed(\n IERC1363 token,\n address from,\n address to,\n uint256 value,\n bytes memory data\n ) internal {\n if (to.code.length == 0) {\n safeTransferFrom(token, from, to, value);\n } else if (!token.transferFromAndCall(from, to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n * targeting contracts.\n *\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n * once without retrying, and relies on the returned value to be true.\n *\n * Reverts if the returned value is other than `true`.\n */\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n if (to.code.length == 0) {\n forceApprove(token, to, value);\n } else if (!token.approveAndCall(to, value, data)) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n uint256 returnSize;\n uint256 returnValue;\n assembly (\"memory-safe\") {\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n // bubble errors\n if iszero(success) {\n let ptr := mload(0x40)\n returndatacopy(ptr, 0, returndatasize())\n revert(ptr, returndatasize())\n }\n returnSize := returndatasize()\n returnValue := mload(0)\n }\n\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n revert SafeERC20FailedOperation(address(token));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly (\"memory-safe\") {\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0)\n }\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n }\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPool.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IOriginationPoolEvents} from \"./IOriginationPoolEvents.sol\";\nimport {IOriginationPoolErrors} from \"./IOriginationPoolErrors.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\nimport {OriginationPoolPhase} from \"../../types/enums/OriginationPoolPhase.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title Interface for the OriginationPool contract\n */\ninterface IOriginationPool is IOriginationPoolEvents, IOriginationPoolErrors, IPausable, IERC20 {\n /**\n * @notice The USDX token address\n * @return The usdx address\n */\n function usdx() external view returns (address);\n\n /**\n * @notice The Consol token address\n * @return The consol address\n */\n function consol() external view returns (address);\n\n /**\n * @notice The deposit phase timestamp\n * @return The deposit phase timestamp\n */\n function depositPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice The deploy phase timestamp\n * @return The deploy phase timestamp\n */\n function deployPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice The redemption phase timestamp\n * @return The redemption phase timestamp\n */\n function redemptionPhaseTimestamp() external view returns (uint256);\n\n /**\n * @notice Fetches the current phase of the Origination Pool\n * @return The current phase\n */\n function currentPhase() external view returns (OriginationPoolPhase);\n\n /**\n * @notice Fetches the pool multiplier in basis points\n * @return The pool multiplier in basis points\n */\n function poolMultiplierBps() external view returns (uint16);\n\n /**\n * @notice Fetches the pool deposit limit\n * @return The pool deposit limit\n */\n function poolLimit() external view returns (uint256);\n\n /**\n * @notice Fetches the amount of USD tokens deployed from the pool\n * @return The amount of USD tokens deployed from the pool\n */\n function amountDeployed() external view returns (uint256);\n\n /**\n * @notice Calculates the return amount of Consol for a given amount of USDX by applying the pool multiplier\n * @param amount The amount of USDX to calculate the return amount for\n * @return returnAmount The return amount of Consol\n */\n function calculateReturnAmount(uint256 amount) external view returns (uint256 returnAmount);\n\n /**\n * @notice Deposit USDX into the pool\n * @param amount The amount of USDX to deposit\n * @return mintAmount The amount of receipt tokens minted to the user\n */\n function deposit(uint256 amount) external returns (uint256 mintAmount);\n\n /**\n * @notice Redeem USDX + Consol from the pool from receipt tokens\n * @param amount The amount of receipt tokens to burn in exchange for USDX + Consol\n */\n function redeem(uint256 amount) external;\n\n /**\n * @notice Deploy USDX in the pool and convert it to Consol. Only callable by contracts implementing IOriginationPoolDeployCallback\n * @param amount The amount of USDX to deploy\n * @param data The calldata to pass into the callback\n */\n function deploy(uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/IPriceOracle.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IPriceOracle\n * @author @SocksNFlops\n * @notice Interface for the price oracle.\n */\ninterface IPriceOracle {\n /**\n * @notice The number of decimals for the collateral\n * @return collateralDecimals The number of decimals for the collateral\n */\n function collateralDecimals() external view returns (uint8);\n\n /**\n * @notice Returns the price of the collateral in USDX\n * @return The price of the collateral in USDX (18 decimals)\n */\n function price() external view returns (uint256);\n\n /**\n * @notice Returns the cost of the collateral in USDX\n * @param collateralAmount The amount of collateral to calculate the cost of\n * @return totalCost The cost of the collateral in USDX (18 decimals)\n * @return _collateralDecimals The collateral decimals\n */\n function cost(uint256 collateralAmount) external view returns (uint256 totalCost, uint8 _collateralDecimals);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsol.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVault} from \"../IMultiTokenVault/IMultiTokenVault.sol\";\nimport {IConsolErrors} from \"./IConsolErrors.sol\";\nimport {IConsolEvents} from \"./IConsolEvents.sol\";\n\n/**\n * @title IConsol\n * @author SocksNFlops\n * @notice Interface for the Consol contract. A wrapper token for USDX and SubConsol tokens.\n */\ninterface IConsol is IMultiTokenVault, IConsolErrors, IConsolEvents {\n /**\n * @notice Get the address of the forfeited assets pool.\n * @return The address of the forfeited assets pool\n */\n function forfeitedAssetsPool() external view returns (address);\n\n /**\n * @notice Set the address of the forfeited assets pool.\n * @param forfeitedAssetsPool_ The address of the forfeited assets pool\n */\n function setForfeitedAssetsPool(address forfeitedAssetsPool_) external;\n\n /**\n * @notice Flash swap tokens. Caller must implement the IConsolFlashSwap interface.\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param amount The amount of tokens to swap\n * @param data The data to pass into the callback\n */\n function flashSwap(address inputToken, address outputToken, uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/ISubConsol/ISubConsol.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ISubConsolEvents} from \"./ISubConsolEvents.sol\";\n\n/**\n * @title ISubConsol\n * @author Socks&Flops\n * @notice Interface for the SubConsol contract. This is meant to hold collateral and mint an input into Consol\n */\ninterface ISubConsol is IERC20, ISubConsolEvents {\n /**\n * @notice Get the collateral token\n * @return The address of the collateral token\n */\n function collateral() external view returns (address);\n\n /**\n * @notice Set the yield strategy\n * @param yieldStrategy_ The address of the yield strategy\n */\n function setYieldStrategy(address yieldStrategy_) external;\n\n /**\n * @notice Get the yield strategy\n * @return The address of the yield strategy\n */\n function yieldStrategy() external view returns (address);\n\n /**\n * @notice Deposit collateral into the Consol contract while minting a specified amount of SubConsol\n * @param collateralAmount The amount of collateral to deposit\n * @param mintAmount The amount of SubConsol to mint\n */\n function depositCollateral(uint256 collateralAmount, uint256 mintAmount) external;\n\n /**\n * @notice Withdraw collateral from the Consol contract while burning a specified amount of SubConsol\n * @param to The address to send the collateral to\n * @param collateralAmount The amount of collateral to withdraw\n * @param burnAmount The amount of SubConsol to burn\n */\n function withdrawCollateral(address to, uint256 collateralAmount, uint256 burnAmount) external;\n\n /**\n * @notice Withdraw collateral from the SubConsol contract asynchronously (from the yield strategy if necessary)\n * @param to The address to send the collateral to\n * @param collateralAmount The amount of collateral to withdraw\n * @param burnAmount The amount of SubConsol to burn\n */\n function withdrawCollateralAsync(address to, uint256 collateralAmount, uint256 burnAmount) external;\n\n /**\n * @notice Get the amount of yield in the yield strategy\n * @return The amount of yield in the yield strategy\n */\n function yieldAmount() external view returns (uint256);\n\n /**\n * @notice Deposit collateral into the yield strategy\n * @param collateralAmount The amount of collateral to deposit\n */\n function depositToYieldStrategy(uint256 collateralAmount) external;\n\n /**\n * @notice Withdraw collateral from the yield strategy\n * @param collateralAmount The amount of collateral to withdraw\n */\n function withdrawFromYieldStrategy(uint256 collateralAmount) external;\n}\n"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDX.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVault} from \"../IMultiTokenVault/IMultiTokenVault.sol\";\nimport {IUSDXEvents} from \"./IUSDXEvents.sol\";\nimport {IUSDXErrors} from \"./IUSDXErrors.sol\";\n\n/**\n * @title IUSDX\n * @author SocksNFlops\n * @notice Interface for the USDX contract. A wrapper token for USD-pegged tokens.\n */\ninterface IUSDX is IMultiTokenVault, IUSDXEvents, IUSDXErrors {\n /**\n * @notice Add a supported token to the MultiTokenVault with specified scalar values\n * @param token The address of the token to add\n * @param scalarNumerator The scalar numerator for the token\n * @param scalarDenominator The scalar denominator for the token\n */\n function addSupportedToken(address token, uint256 scalarNumerator, uint256 scalarDenominator) external;\n\n /**\n * @notice Get the scalars for a token\n * @param token The address of the token to get the scalars for\n * @return numerator The numerator for the token\n * @return denominator The denominator for the token\n */\n function tokenScalars(address token) external view returns (uint256 numerator, uint256 denominator);\n\n /**\n * @notice Burn a specified amount of USDX for a proportional amount of each supported token\n * @param amount The amount of USDX to burn\n */\n function burn(uint256 amount) external;\n}\n"},"lib/cash/src/types/orders/OrderRequests.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @notice The base parameters required for a creating a mortgage or expanding the balance sheet of a mortgage\n * @param collateralAmounts The amounts of collateral to borrow against for each origination pool. This will be escrowed in the Consol contract.\n * @param totalPeriods The total number of periods that the mortgage will last\n * @param originationPools The addresses of the origination pools to use\n * @param isCompounding Whether the mortgage is compounding\n * @param expiration The expiration of the mortgage\n */\nstruct BaseRequest {\n uint256[] collateralAmounts;\n uint8 totalPeriods;\n address[] originationPools;\n bool isCompounding;\n uint256 expiration;\n}\n\n/**\n * @notice The parameters required for a creating a mortgage request\n * @param base The base parameters required for a creating a mortgage\n * @param mortgageId The mortgageId of the mortgage NFT to be created\n * @param collateral The address of the collateral token\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param conversionQueues The addresses of the conversion queues to use. Ignored in expansion requests.\n * @param hasPaymentPlan Whether the mortgage is hasPaymentPlan (periodic payment plan vs single payment)\n */\nstruct CreationRequest {\n BaseRequest base;\n string mortgageId;\n address collateral;\n address subConsol;\n address[] conversionQueues;\n bool hasPaymentPlan;\n}\n\n/**\n * @notice The parameters required for a request to expand the balance of a mortgage\n * @param base The base parameters required for a request to expand the balance of a mortgage\n * @param tokenId The tokenId of the mortgage NFT to be expanded\n */\nstruct ExpansionRequest {\n BaseRequest base;\n uint256 tokenId;\n}\n"},"src/interfaces/IWNT.sol":{"content":"pragma solidity >=0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IWNT is IERC20 {\n /**\n * @notice Deposit native tokens into the WNT contract\n */\n function deposit() external payable;\n\n /**\n * @notice Withdraw native tokens from the WNT contract\n * @param wad The amount of WNT to withdraw\n */\n function withdraw(uint256 wad) external;\n\n /**\n * @notice Approve a spender to spend a certain amount of WNT\n * @param guy The address of the spender\n * @param wad The amount of WNT to approve\n * @return bool Whether the approval was successful\n */\n function approve(address guy, uint256 wad) external returns (bool);\n}\n"},"lib/cash/src/types/OPoolConfigId.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {OriginationPoolConfig} from \"./OriginationPoolConfig.sol\";\n\ntype OPoolConfigId is bytes32;\n\n/**\n * @title OPoolConfigIdLibrary\n * @author SocksNFlops\n * @notice Library for computing the ID of a origination pool config\n */\nlibrary OPoolConfigIdLibrary {\n /**\n * @dev Returns value equal to keccak256(abi.encode(OPoolConfig))\n * @param oPoolConfig The origination pool config to compute the ID for\n * @return oPoolConfigId The ID of the origination pool config\n */\n function toId(OriginationPoolConfig memory oPoolConfig) internal pure returns (OPoolConfigId oPoolConfigId) {\n return OPoolConfigId.wrap(keccak256(abi.encode(oPoolConfig)));\n }\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolScheduler.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IOriginationPoolSchedulerEvents} from \"./IOriginationPoolSchedulerEvents.sol\";\nimport {IOriginationPoolSchedulerErrors} from \"./IOriginationPoolSchedulerErrors.sol\";\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\nimport {IPausable} from \"../IPausable/IPausable.sol\";\n\n/**\n * @notice A record of the last deployment address, epoch, and timestamp for a given origination pool config\n * @param deploymentAddress The address of the last deployment\n * @param epoch The epoch number of the last deployment\n * @param timestamp The timestamp of the last deployment\n */\nstruct LastDeploymentRecord {\n address deploymentAddress;\n uint256 epoch;\n uint256 timestamp;\n}\n\n/**\n * @title Interface for the OriginationPoolFactory contract\n * @author SocksNFlops\n * @notice Interface for the OriginationPoolFactory contract\n */\ninterface IOriginationPoolScheduler is IOriginationPoolSchedulerEvents, IOriginationPoolSchedulerErrors, IPausable {\n /**\n * @notice Set the general manager address\n * @param newGeneralManager The address of the new general manager\n */\n function setGeneralManager(address newGeneralManager) external;\n\n /**\n * @notice Get the general manager address\n * @return The address of the general manager\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Set the admin address that is assigned to the origination pools on deployment\n * @param newOpoolAdmin The address of the new origination pool admin\n */\n function setOpoolAdmin(address newOpoolAdmin) external;\n\n /**\n * @notice Get the admin address that is assigned to the origination pools on deployment\n * @return The address of the origination pool admin\n */\n function oPoolAdmin() external view returns (address);\n\n /**\n * @notice Get the number of origination pool configs\n * @return The number of origination pool configs\n */\n function configLength() external view returns (uint256);\n\n /**\n * @notice Get the origination pool config ID at the given index\n * @param index The index of the origination pool config to get the ID for\n * @return oPoolConfigId The ID of the origination pool config\n */\n function configIdAt(uint256 index) external view returns (OPoolConfigId oPoolConfigId);\n\n /**\n * @notice Get the origination pool config at the given index\n * @param index The index of the origination pool config to get\n * @return config The origination pool config\n */\n function configAt(uint256 index) external view returns (OriginationPoolConfig memory);\n\n /**\n * @notice Get the last deployment address from the given config index\n * @param index The index of the origination pool config to get the last deployment address from\n * @return lastDeploymentRecord The last deployment record\n */\n function lastConfigDeployment(uint256 index) external view returns (LastDeploymentRecord memory lastDeploymentRecord);\n\n /**\n * @notice Get the last deployment address from the given config ID\n * @param oPoolConfigId The ID of the origination pool config to get the last deployment address from\n * @return lastDeploymentRecord The last deployment record\n */\n function lastConfigDeployment(OPoolConfigId oPoolConfigId)\n external\n view\n returns (LastDeploymentRecord memory lastDeploymentRecord);\n\n /**\n * @notice Add a new origination pool config\n * @param config The origination pool config to add\n */\n function addConfig(OriginationPoolConfig memory config) external;\n\n /**\n * @notice Remove an origination pool config\n * @param config The origination pool config to remove\n */\n function removeConfig(OriginationPoolConfig memory config) external;\n\n /**\n * @notice Get the current epoch. Indexed from 1\n * @return currentEpoch The current epoch\n */\n function currentEpoch() external view returns (uint256);\n\n /**\n * @notice Deploy a new origination pool\n * @param oPoolConfigId The ID of the origination pool config to deploy\n * @return deploymentAddress The address of the deployed origination pool\n */\n function deployOriginationPool(OPoolConfigId oPoolConfigId) external returns (address deploymentAddress);\n\n /**\n * @notice Predict the origination pool address for the given config ID and current epoch. If already deployed, will return the already deployed address.\n * @param oPoolConfigId The ID of the origination pool config to predict the address for\n * @return deploymentAddress The predicted deployment address\n */\n function predictOriginationPool(OPoolConfigId oPoolConfigId) external view returns (address deploymentAddress);\n\n /**\n * @notice Check if an origination pool is registered (deployed by the scheduler)\n * @param originationPool The address of the origination pool to check\n * @return registered Whether the origination pool is registered\n */\n function isRegistered(address originationPool) external view returns (bool registered);\n\n /**\n * @notice Update the registration of an origination pool\n * @param originationPool The address of the origination pool to update the registration for\n * @param registered Whether the origination pool is registered\n */\n function updateRegistration(address originationPool, bool registered) external;\n}\n"},"src/interfaces/IRouter/IRouter.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {CreationRequest} from \"@core/types/orders/OrderRequests.sol\";\nimport {OPoolConfigId} from \"@core/types/OPoolConfigId.sol\";\nimport {IRouterErrors} from \"./IRouterErrors.sol\";\n\n/**\n * @title IRouter\n * @author @SocksNFlops\n * @notice Interface for the Router contract meant to facilitate user interactions with core contracts of the Cash protocol.\n */\ninterface IRouter is IRouterErrors {\n /**\n * @notice The address of the general manager contract\n * @return The address of the general manager contract\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice The address of the rollover vault contract\n * @return The address of the rollover vault contract\n */\n function rolloverVault() external view returns (address);\n\n /**\n * @notice The address of the fulfillment vault contract\n * @return The address of the fulfillment vault contract\n */\n function fulfillmentVault() external view returns (address);\n\n /**\n * @notice The address of the Pyth contract\n * @return The address of the Pyth contract\n */\n function pyth() external view returns (address);\n\n /**\n * @notice The address of the wrapped native token\n * @return The address of the wrapped native token\n */\n function wrappedNativeToken() external view returns (address);\n\n /**\n * @notice The address of the USDX token contract\n * @return The address of the USDX token contract\n */\n function usdx() external view returns (address);\n\n /**\n * @notice The address of the Consol token contract\n * @return The address of the Consol token contract\n */\n function consol() external view returns (address);\n\n /**\n * @notice The address of the origination pool scheduler contract\n * @return The address of the origination pool scheduler contract\n */\n function originationPoolScheduler() external view returns (address);\n\n /**\n * @notice Approve all the collaterals to be spent by the general manager\n */\n function approveCollaterals() external;\n\n /**\n * @notice Approve all the usdTokens to be spent by the USDX contract (for depositing into USDX)\n */\n function approveUsdTokens() external;\n\n /**\n * @notice Calculates the amounts that will be collected from the borrower for a given creation request before sending the request to the general manager\n * @param creationRequest The creation request\n * @return collateralCollected The amount of collateral that will be collected from the borrower\n * @return usdxCollected The amount of USDX that will be collected from the borrower\n * @return paymentAmount The amount of USDX that will be paid to the fulfilller\n * @return collateralDecimals The decimals of the collateral token\n */\n function calculateCollectedAmounts(CreationRequest calldata creationRequest)\n external\n view\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Request a mortgage\n * @param usdToken The address of the usdToken to pull in\n * @param creationRequest The creation request\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n * @param maxCollected The maximum amount that can be collected from the borrower (in USDX if non-compounding, in collateral if compounding)\n * @return collateralCollected The amount of collateral collected\n * @return usdxCollected The amount of USDX collected\n * @return paymentAmount The amount of payment to be made\n * @return collateralDecimals The decimals of the collateral\n */\n function requestMortgage(\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n external\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Request a mortgage\n * @param priceUpdates The price updates to send to the Pyth contract\n * @param usdToken The address of the usdToken to pull in\n * @param creationRequest The creation request\n * @param isNative Whether the collateral is the native token or not (i.e., whype: 0x555...)\n * @param maxCollected The maximum amount that can be collected from the borrower (in USDX if non-compounding, in collateral if compounding)\n * @return collateralCollected The amount of collateral collected\n * @return usdxCollected The amount of USDX collected\n * @return paymentAmount The amount of payment to be made\n * @return collateralDecimals The decimals of the collateral\n */\n function updatePriceFeedsAndRequestMortgage(\n bytes[] calldata priceUpdates,\n address usdToken,\n CreationRequest calldata creationRequest,\n bool isNative,\n uint256 maxCollected\n )\n external\n payable\n returns (uint256 collateralCollected, uint256 usdxCollected, uint256 paymentAmount, uint8 collateralDecimals);\n\n /**\n * @notice Make a periodic payment on a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID\n * @param inputAmount The amount of input token to pull in\n */\n function periodPay(address inputToken, uint256 tokenId, uint256 inputAmount) external;\n\n /**\n * @notice Make a penalty payment on a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID\n * @param inputAmount The amount of input token to pull in\n */\n function penaltyPay(address inputToken, uint256 tokenId, uint256 inputAmount) external;\n\n /**\n * @notice Refinance a mortgage\n * @param inputToken The address of the input token to pull in\n * @param tokenId The token ID of the mortgage to refinance\n * @param newTotalPeriods The new total periods of the mortgage\n */\n function refinance(address inputToken, uint256 tokenId, uint8 newTotalPeriods) external;\n\n /**\n * @notice Deposit into an origination pool\n * @param oPoolConfigId The OPoolConfigId of the origination pool to deposit into\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function originationPoolDeposit(OPoolConfigId oPoolConfigId, address usdToken, uint256 usdTokenAmount) external;\n\n /**\n * @notice Quotes the amount of output token that would be received for a given amount of input token\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param inputAmount The amount of input token to convert\n * @return outputAmount The amount of output token received\n */\n function convert(address inputToken, address outputToken, uint256 inputAmount)\n external\n view\n returns (uint256 outputAmount);\n\n /**\n * @notice Wraps tokens from usdToken -> usdx -> consol\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param inputAmount The amount of input token to convert\n */\n function wrap(address inputToken, address outputToken, uint256 inputAmount) external;\n\n /**\n * @notice Deposit into the rollover vault\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function rolloverVaultDeposit(address usdToken, uint256 usdTokenAmount) external;\n\n /**\n * @notice Deposit into the fulfillment vault\n * @param usdToken The address of the usdToken to pull in\n * @param usdTokenAmount The amount of usdToken to pull in\n */\n function fulfillmentVaultDeposit(address usdToken, uint256 usdTokenAmount) external;\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFT.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IMortgageNFTEvents} from \"./IMortgageNFTEvents.sol\";\nimport {IMortgageNFTErrors} from \"./IMortgageNFTErrors.sol\";\n\n/**\n * @title IMortgageNFT\n * @author Socks&Flops\n * @notice The interface for the MortgageNFT contract, a non-fungible token that represents ownership of a mortgage position in LoanManager\n */\ninterface IMortgageNFT is IERC721, IMortgageNFTEvents, IMortgageNFTErrors {\n /**\n * @notice Returns the general manager address\n * @return The general manager address\n */\n function generalManager() external view returns (address);\n\n /**\n * @notice Returns the NFT metadata generator address\n * @return The NFT metadata generator address\n */\n function nftMetadataGenerator() external view returns (address);\n\n /**\n * @notice Mints a mortgage NFT. Only callable by the loan manager.\n * @param to The address to mint the mortgage NFT to\n * @param mortgageId The string identifier of the mortage position\n * @return tokenId The tokenId of the newly minted mortgage NFT\n */\n function mint(address to, string memory mortgageId) external returns (uint256 tokenId);\n\n /**\n * @notice Burns a mortgage NFT. Only callable by the loan manager.\n * @param tokenId The ID of the mortgage NFT to burn\n */\n function burn(uint256 tokenId) external;\n\n /**\n * @notice Returns the mortgageId for a given tokenID\n * @param tokenId The tokenId to get the mortgageId for\n * @return mortgageId The corresponding mortgageId\n */\n function getMortgageId(uint256 tokenId) external view returns (string memory mortgageId);\n\n /**\n * @notice Returns the tokenId for a given mortgageId\n * @param mortgageId The mortgageId to get the tokenId for\n * @return tokenId The coresponding tokenId\n */\n function getTokenId(string memory mortgageId) external view returns (uint256 tokenId);\n\n /**\n * @notice Returns the owner of a given mortgage ID\n * @param mortgageId The mortgage ID to get the owner for\n * @return owner The owner of the mortgage ID\n */\n function ownerOf(string memory mortgageId) external view returns (address owner);\n\n /**\n * @notice Returns the last tokenId created\n * @return lastTokenIdCreated The last tokenId created\n */\n function lastTokenIdCreated() external view returns (uint256);\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFTErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IMortgageNFTErrors\n * @author Socks&Flops\n */\ninterface IMortgageNFTErrors {\n /**\n * @notice Emitted when a mortgageId is already taken\n * @param tokenId The ID of the mortgage NFT with the taken mortgageId\n * @param mortgageId The mortageId of the mortgage\n */\n error MortgageIdAlreadyTaken(uint256 tokenId, string mortgageId);\n\n /**\n * @notice Emitted when a non-owner attempts to update a mortgageId\n * @param owner The owner of the mortgage NFT\n * @param caller The caller of the function\n */\n error OnlyOwner(address owner, address caller);\n\n /**\n * @notice Emitted when a non-general manager attempts to update a mortgage NFT\n * @param generalManager The general manager address\n * @param caller The caller of the function\n */\n error OnlyGeneralManager(address generalManager, address caller);\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC20InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC20InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\n * @param needed Minimum amount required to perform a transfer.\n */\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC20InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n * @param spender Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n /**\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n * Used in balance queries.\n * @param owner Address of the current owner of a token.\n */\n error ERC721InvalidOwner(address owner);\n\n /**\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\n * @param tokenId Identifier number of a token.\n */\n error ERC721NonexistentToken(uint256 tokenId);\n\n /**\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param tokenId Identifier number of a token.\n * @param owner Address of the current owner of a token.\n */\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC721InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC721InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param tokenId Identifier number of a token.\n */\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC721InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n /**\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n * @param balance Current balance for the interacting account.\n * @param needed Minimum amount required to perform a transfer.\n * @param tokenId Identifier number of a token.\n */\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n /**\n * @dev Indicates a failure with the token `sender`. Used in transfers.\n * @param sender Address whose tokens are being transferred.\n */\n error ERC1155InvalidSender(address sender);\n\n /**\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\n * @param receiver Address to which tokens are being transferred.\n */\n error ERC1155InvalidReceiver(address receiver);\n\n /**\n * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n * @param owner Address of the current owner of a token.\n */\n error ERC1155MissingApprovalForAll(address operator, address owner);\n\n /**\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n * @param approver Address initiating an approval operation.\n */\n error ERC1155InvalidApprover(address approver);\n\n /**\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n * @param operator Address that may be allowed to operate on tokens without being their owner.\n */\n error ERC1155InvalidOperator(address operator);\n\n /**\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n * Used in batch transfers.\n * @param idsLength Length of the array of token identifiers\n * @param valuesLength Length of the array of token amounts\n */\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Floor, // Toward negative infinity\n Ceil, // Toward positive infinity\n Trunc, // Toward zero\n Expand // Away from zero\n }\n\n /**\n * @dev Return the 512-bit addition of two uint256.\n *\n * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n */\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n assembly (\"memory-safe\") {\n low := add(a, b)\n high := lt(low, a)\n }\n }\n\n /**\n * @dev Return the 512-bit multiplication of two uint256.\n *\n * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n */\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = high * 2²⁵⁶ + low.\n assembly (\"memory-safe\") {\n let mm := mulmod(a, b, not(0))\n low := mul(a, b)\n high := sub(sub(mm, low), lt(mm, low))\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a + b;\n success = c >= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a - b;\n success = c <= a;\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n uint256 c = a * b;\n assembly (\"memory-safe\") {\n // Only true when the multiplication doesn't overflow\n // (c / a == b) || (a == 0)\n success := or(eq(div(c, a), b), iszero(a))\n }\n // equivalent to: success ? c : 0\n result = c * SafeCast.toUint(success);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `DIV` opcode returns zero when the denominator is 0.\n result := div(a, b)\n }\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n unchecked {\n success = b > 0;\n assembly (\"memory-safe\") {\n // The `MOD` opcode returns zero when the denominator is 0.\n result := mod(a, b)\n }\n }\n }\n\n /**\n * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryAdd(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n */\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n (, uint256 result) = trySub(a, b);\n return result;\n }\n\n /**\n * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n */\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n (bool success, uint256 result) = tryMul(a, b);\n return ternary(success, result, type(uint256).max);\n }\n\n /**\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n *\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n * one branch when needed, making this function more expensive.\n */\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n unchecked {\n // branchless ternary works because:\n // b ^ (a ^ b) == a\n // b ^ 0 == b\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\n }\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a > b, a, b);\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return ternary(a < b, a, b);\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds towards infinity instead\n * of rounding towards zero.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n if (b == 0) {\n // Guarantee the same behavior as in a regular Solidity division.\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n\n // The following calculation ensures accurate ceiling division without overflow.\n // Since a is non-zero, (a - 1) / b will not overflow.\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n // but the largest value we can obtain is type(uint256).max - 1, which happens\n // when a = type(uint256).max and b = 1.\n unchecked {\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n }\n }\n\n /**\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n * denominator == 0.\n *\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n * Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n\n // Handle non-overflow cases, 256 by 256 division.\n if (high == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return low / denominator;\n }\n\n // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n if (denominator <= high) {\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [high low].\n uint256 remainder;\n assembly (\"memory-safe\") {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n high := sub(high, gt(remainder, low))\n low := sub(low, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n uint256 twos = denominator & (0 - denominator);\n assembly (\"memory-safe\") {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [high low] by twos.\n low := div(low, twos)\n\n // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from high into low.\n low |= high * twos;\n\n // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n // works in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n inverse *= 2 - denominator * inverse; // inverse mod 2³²\n inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n // is no longer required.\n result = low * inverse;\n return result;\n }\n }\n\n /**\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n }\n\n /**\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n */\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n unchecked {\n (uint256 high, uint256 low) = mul512(x, y);\n if (high >= 1 << n) {\n Panic.panic(Panic.UNDER_OVERFLOW);\n }\n return (high << (256 - n)) | (low >> n);\n }\n }\n\n /**\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n */\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n }\n\n /**\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n *\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n *\n * If the input value is not inversible, 0 is returned.\n *\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n */\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n unchecked {\n if (n == 0) return 0;\n\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n // ax + ny = 1\n // ax = 1 + (-y)n\n // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n // If the remainder is 0 the gcd is n right away.\n uint256 remainder = a % n;\n uint256 gcd = n;\n\n // Therefore the initial coefficients are:\n // ax + ny = gcd(a, n) = n\n // 0a + 1n = n\n int256 x = 0;\n int256 y = 1;\n\n while (remainder != 0) {\n uint256 quotient = gcd / remainder;\n\n (gcd, remainder) = (\n // The old remainder is the next gcd to try.\n remainder,\n // Compute the next remainder.\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n // where gcd is at most n (capped to type(uint256).max)\n gcd - remainder * quotient\n );\n\n (x, y) = (\n // Increment the coefficient of a.\n y,\n // Decrement the coefficient of n.\n // Can overflow, but the result is casted to uint256 so that the\n // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n x - y * int256(quotient)\n );\n }\n\n if (gcd != 1) return 0; // No inverse exists.\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n }\n }\n\n /**\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n *\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n *\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n */\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n unchecked {\n return Math.modExp(a, p - 2, p);\n }\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n *\n * Requirements:\n * - modulus can't be zero\n * - underlying staticcall to precompile must succeed\n *\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n * interpreted as 0.\n */\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n (bool success, uint256 result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n * to operate modulo 0 or if the underlying precompile reverted.\n *\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n * of a revert, but the result may be incorrectly interpreted as 0.\n */\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n if (m == 0) return (false, 0);\n assembly (\"memory-safe\") {\n let ptr := mload(0x40)\n // | Offset | Content | Content (Hex) |\n // |-----------|------------|--------------------------------------------------------------------|\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n mstore(ptr, 0x20)\n mstore(add(ptr, 0x20), 0x20)\n mstore(add(ptr, 0x40), 0x20)\n mstore(add(ptr, 0x60), b)\n mstore(add(ptr, 0x80), e)\n mstore(add(ptr, 0xa0), m)\n\n // Given the result < m, it's guaranteed to fit in 32 bytes,\n // so we can use the memory scratch space located at offset 0.\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n result := mload(0x00)\n }\n }\n\n /**\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\n */\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n (bool success, bytes memory result) = tryModExp(b, e, m);\n if (!success) {\n Panic.panic(Panic.DIVISION_BY_ZERO);\n }\n return result;\n }\n\n /**\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n */\n function tryModExp(\n bytes memory b,\n bytes memory e,\n bytes memory m\n ) internal view returns (bool success, bytes memory result) {\n if (_zeroBytes(m)) return (false, new bytes(0));\n\n uint256 mLen = m.length;\n\n // Encode call args in result and move the free memory pointer\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n assembly (\"memory-safe\") {\n let dataPtr := add(result, 0x20)\n // Write result on top of args to avoid allocating extra memory.\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n // Overwrite the length.\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n mstore(result, mLen)\n // Set the memory pointer after the returned data.\n mstore(0x40, add(dataPtr, mLen))\n }\n }\n\n /**\n * @dev Returns whether the provided byte array is zero.\n */\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n for (uint256 i = 0; i < byteArray.length; ++i) {\n if (byteArray[i] != 0) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n * towards zero.\n *\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n * using integer operations.\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n unchecked {\n // Take care of easy edge cases when a == 0 or a == 1\n if (a <= 1) {\n return a;\n }\n\n // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n // the current value as `ε_n = | x_n - sqrt(a) |`.\n //\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n // bigger than any uint256.\n //\n // By noticing that\n // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n // to the msb function.\n uint256 aa = a;\n uint256 xn = 1;\n\n if (aa >= (1 << 128)) {\n aa >>= 128;\n xn <<= 64;\n }\n if (aa >= (1 << 64)) {\n aa >>= 64;\n xn <<= 32;\n }\n if (aa >= (1 << 32)) {\n aa >>= 32;\n xn <<= 16;\n }\n if (aa >= (1 << 16)) {\n aa >>= 16;\n xn <<= 8;\n }\n if (aa >= (1 << 8)) {\n aa >>= 8;\n xn <<= 4;\n }\n if (aa >= (1 << 4)) {\n aa >>= 4;\n xn <<= 2;\n }\n if (aa >= (1 << 2)) {\n xn <<= 1;\n }\n\n // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n //\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n // This is going to be our x_0 (and ε_0)\n xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n // From here, Newton's method give us:\n // x_{n+1} = (x_n + a / x_n) / 2\n //\n // One should note that:\n // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n // = ((x_n² + a) / (2 * x_n))² - a\n // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n // = (x_n² - a)² / (2 * x_n)²\n // = ((x_n² - a) / (2 * x_n))²\n // ≥ 0\n // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n //\n // This gives us the proof of quadratic convergence of the sequence:\n // ε_{n+1} = | x_{n+1} - sqrt(a) |\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\n // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n // = | (x_n - sqrt(a))² / (2 * x_n) |\n // = | ε_n² / (2 * x_n) |\n // = ε_n² / | (2 * x_n) |\n //\n // For the first iteration, we have a special case where x_0 is known:\n // ε_1 = ε_0² / | (2 * x_0) |\n // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n // ≤ 2**(2*e-4) / (3 * 2**(e-1))\n // ≤ 2**(e-3) / 3\n // ≤ 2**(e-3-log2(3))\n // ≤ 2**(e-4.5)\n //\n // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n // ε_{n+1} = ε_n² / | (2 * x_n) |\n // ≤ (2**(e-k))² / (2 * 2**(e-1))\n // ≤ 2**(2*e-2*k) / 2**e\n // ≤ 2**(e-2*k)\n xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above\n xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5\n xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9\n xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18\n xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36\n xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72\n\n // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n // sqrt(a) or sqrt(a) + 1.\n return xn - SafeCast.toUint(xn > a / xn);\n }\n }\n\n /**\n * @dev Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n }\n }\n\n /**\n * @dev Return the log in base 2 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log2(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // If upper 8 bits of 16-bit half set, add 8 to result\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n // If upper 4 bits of 8-bit half set, add 4 to result\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n // Shifts value right by the current result and use it as an index into this lookup table:\n //\n // | x (4 bits) | index | table[index] = MSB position |\n // |------------|---------|-----------------------------|\n // | 0000 | 0 | table[0] = 0 |\n // | 0001 | 1 | table[1] = 0 |\n // | 0010 | 2 | table[2] = 1 |\n // | 0011 | 3 | table[3] = 1 |\n // | 0100 | 4 | table[4] = 2 |\n // | 0101 | 5 | table[5] = 2 |\n // | 0110 | 6 | table[6] = 2 |\n // | 0111 | 7 | table[7] = 2 |\n // | 1000 | 8 | table[8] = 3 |\n // | 1001 | 9 | table[9] = 3 |\n // | 1010 | 10 | table[10] = 3 |\n // | 1011 | 11 | table[11] = 3 |\n // | 1100 | 12 | table[12] = 3 |\n // | 1101 | 13 | table[13] = 3 |\n // | 1110 | 14 | table[14] = 3 |\n // | 1111 | 15 | table[15] = 3 |\n //\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n assembly (\"memory-safe\") {\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n }\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n }\n }\n\n /**\n * @dev Return the log in base 10 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n }\n }\n\n /**\n * @dev Return the log in base 256 of a positive value rounded towards zero.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 x) internal pure returns (uint256 r) {\n // If value has upper 128 bits set, log2 result is at least 128\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n // If upper 64 bits of 128-bit half set, add 64 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n // If upper 32 bits of 64-bit half set, add 32 to result\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n // If upper 16 bits of 32-bit half set, add 16 to result\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n }\n }\n\n /**\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n */\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n return uint8(rounding) % 2 == 1;\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/IPyth.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"./PythStructs.sol\";\nimport \"./IPythEvents.sol\";\n\n/// @title Consume prices from the Pyth Network (https://pyth.network/).\n/// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely.\n/// @author Pyth Data Association\ninterface IPyth is IPythEvents {\n /// @notice Returns the price of a price feed without any sanity checks.\n /// @dev This function returns the most recent price update in this contract without any recency checks.\n /// This function is unsafe as the returned price update may be arbitrarily far in the past.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use `getPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the price that is no older than `age` seconds of the current time.\n /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.\n /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.\n /// However, if the price is not recent this function returns the latest available price.\n ///\n /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that\n /// the returned price is recent or useful for any particular application.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds\n /// of the current time.\n /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Update price feeds with given update messages.\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n /// Prices will be updated if they are more recent than the current stored prices.\n /// The call will succeed even if the update is not the most recent.\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n function updatePriceFeeds(bytes[] calldata updateData) external payable;\n\n /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is\n /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the\n /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime\n /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have\n /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.\n /// Otherwise, it calls updatePriceFeeds method to update the prices.\n ///\n /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`\n function updatePriceFeedsIfNecessary(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64[] calldata publishTimes\n ) external payable;\n\n /// @notice Returns the required fee to update an array of price updates.\n /// @param updateData Array of price update data.\n /// @return feeAmount The required fee in Wei.\n function getUpdateFee(\n bytes[] calldata updateData\n ) external view returns (uint feeAmount);\n\n /// @notice Returns the required fee to update a TWAP price.\n /// @param updateData Array of price update data.\n /// @return feeAmount The required fee in Wei.\n function getTwapUpdateFee(\n bytes[] calldata updateData\n ) external view returns (uint feeAmount);\n\n /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published\n /// within `minPublishTime` and `maxPublishTime`.\n ///\n /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;\n /// otherwise, please consider using `updatePriceFeeds`. This method will not store the price updates on-chain.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdates(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minPublishTime,\n uint64 maxPublishTime\n ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);\n\n /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published\n /// within `minPublishTime` and `maxPublishTime,` but choose to store price updates if `storeUpdatesIfFresh`.\n ///\n /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;\n /// otherwise, please consider using `updatePriceFeeds`. This method may store the price updates on-chain, if they\n /// are more recent than the current stored prices.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n /// This method will eventually allow the caller to determine whether parsed price feeds should update\n /// the stored values as well.\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minAllowedPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxAllowedPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @param storeUpdatesIfFresh flag for the parse function to\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdatesWithConfig(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minAllowedPublishTime,\n uint64 maxAllowedPublishTime,\n bool checkUniqueness,\n bool checkUpdateDataIsMinimal,\n bool storeUpdatesIfFresh\n )\n external\n payable\n returns (\n PythStructs.PriceFeed[] memory priceFeeds,\n uint64[] memory slots\n );\n\n /// @notice Parse time-weighted average price (TWAP) from two consecutive price updates for the given `priceIds`.\n ///\n /// This method calculates TWAP between two data points by processing the difference in cumulative price values\n /// divided by the time period. It requires exactly two updates that contain valid price information\n /// for all the requested price IDs.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the updateData array.\n ///\n /// @dev Reverts if:\n /// - The transferred fee is not sufficient\n /// - The updateData is invalid or malformed\n /// - The updateData array does not contain exactly 2 updates\n /// - There is no update for any of the given `priceIds`\n /// - The time ordering between data points is invalid (start time must be before end time)\n /// @param updateData Array containing exactly two price updates (start and end points for TWAP calculation)\n /// @param priceIds Array of price ids to calculate TWAP for\n /// @return twapPriceFeeds Array of TWAP price feeds corresponding to the given `priceIds` (with the same order)\n function parseTwapPriceFeedUpdates(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds\n )\n external\n payable\n returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds);\n\n /// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are\n /// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,\n /// this method will return the first update. This method may store the price updates on-chain, if they\n /// are more recent than the current stored prices.\n ///\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range and uniqueness condition.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdatesUnique(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minPublishTime,\n uint64 maxPublishTime\n ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/PythErrors.sol":{"content":"// SPDX-License-Identifier: Apache 2\n\npragma solidity ^0.8.0;\n\nlibrary PythErrors {\n // Function arguments are invalid (e.g., the arguments lengths mismatch)\n // Signature: 0xa9cb9e0d\n error InvalidArgument();\n // Update data is coming from an invalid data source.\n // Signature: 0xe60dce71\n error InvalidUpdateDataSource();\n // Update data is invalid (e.g., deserialization error)\n // Signature: 0xe69ffece\n error InvalidUpdateData();\n // Insufficient fee is paid to the method.\n // Signature: 0x025dbdd4\n error InsufficientFee();\n // There is no fresh update, whereas expected fresh updates.\n // Signature: 0xde2c57fa\n error NoFreshUpdate();\n // There is no price feed found within the given range or it does not exists.\n // Signature: 0x45805f5d\n error PriceFeedNotFoundWithinRange();\n // Price feed not found or it is not pushed on-chain yet.\n // Signature: 0x14aebe68\n error PriceFeedNotFound();\n // Requested price is stale.\n // Signature: 0x19abf40e\n error StalePrice();\n // Given message is not a valid Wormhole VAA.\n // Signature: 0x2acbe915\n error InvalidWormholeVaa();\n // Governance message is invalid (e.g., deserialization error).\n // Signature: 0x97363b35\n error InvalidGovernanceMessage();\n // Governance message is not for this contract.\n // Signature: 0x63daeb77\n error InvalidGovernanceTarget();\n // Governance message is coming from an invalid data source.\n // Signature: 0x360f2d87\n error InvalidGovernanceDataSource();\n // Governance message is old.\n // Signature: 0x88d1b847\n error OldGovernanceMessage();\n // The wormhole address to set in SetWormholeAddress governance is invalid.\n // Signature: 0x13d3ed82\n error InvalidWormholeAddressToSet();\n // The twap update data is invalid.\n error InvalidTwapUpdateData();\n // The twap update data set is invalid.\n error InvalidTwapUpdateDataSet();\n // The Input Price is negative.\n error NegativeInputPrice();\n // The Input Exponent is invalid.\n error InvalidInputExpo();\n // The combined price is greater than int64.max.\n error CombinedPriceOverflow();\n // The exponent is greater than 77 or less than -77.\n error ExponentOverflow();\n}\n"},"lib/cash/src/libraries/MortgageMath.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {MortgagePosition, MortgageStatus} from \"../types/MortgagePosition.sol\";\nimport {Constants} from \"./Constants.sol\";\n\n/**\n * @title MortgageMath\n * @author SocksNFlops\n * @notice Library for running operations on MortgagePositions\n */\nlibrary MortgageMath {\n using MortgageMath for MortgagePosition;\n\n /**\n * @notice Thrown when a periodPay, penaltyPay, or refinance amount is zero\n * @param mortgage The mortgage position\n */\n error ZeroAmount(MortgagePosition mortgage);\n /**\n * @notice Thrown when a payment is greater than the termBalance\n * @param mortgage The mortgage position\n * @param amount The amount of the payment\n */\n error CannotOverpay(MortgagePosition mortgage, uint256 amount);\n /**\n * @notice Thrown when a mortgage position has unpaid penalties that need to be settled\n * @param mortgage The mortgage position\n */\n error UnpaidPenalties(MortgagePosition mortgage);\n /**\n * @notice Thrown when a penalty payment is greater than the penalty accrued\n * @param mortgage The mortgage position\n * @param amount The amount of the penalty\n */\n error CannotOverpayPenalty(MortgagePosition mortgage, uint256 amount);\n /**\n * @notice Thrown when a mortgage position has unpaid payments that need to be settled\n * @param mortgage The mortgage position\n */\n error UnpaidPayments(MortgagePosition mortgage);\n /**\n * @notice Thrown when a mortgage position has missed payments that need to be settled\n * @param mortgage The mortgage position\n */\n error MissedPayments(MortgagePosition mortgage);\n /**\n * @notice Thrown when a mortgage position is not foreclosable\n * @param mortgage The mortgage position\n * @param maxMissedPayments The maximum number of missed payments\n */\n error NotForeclosable(MortgagePosition mortgage, uint8 maxMissedPayments);\n /**\n * @notice Thrown when the conversion trigger price is not met\n * @param mortgage The mortgage position\n * @param currentPrice The current price of the collateral\n */\n error ConversionTriggerPriceNotMet(MortgagePosition mortgage, uint256 currentPrice);\n /**\n * @notice Thrown when a mortgage position is not convertible\n * @param mortgage The mortgage position\n * @param amountConverting The amount of principal being converted\n * @param collateralConverting The amount of collateral being converted\n */\n error CannotOverConvert(MortgagePosition mortgage, uint256 amountConverting, uint256 collateralConverting);\n /**\n * @notice Thrown when a mortgage position is not partially prepayable (i.e., does not have a payment plan) and the payment is less than the termBalance\n * @param mortgage The mortgage position\n */\n error CannotPartialPrepay(MortgagePosition mortgage);\n\n /**\n * @dev Copies a mortgage position\n * @param mortgagePosition The mortgage position to copy\n * @return The copied mortgage position\n */\n function copy(MortgagePosition memory mortgagePosition) internal pure returns (MortgagePosition memory) {\n return MortgagePosition({\n tokenId: mortgagePosition.tokenId,\n collateral: mortgagePosition.collateral,\n collateralDecimals: mortgagePosition.collateralDecimals,\n collateralAmount: mortgagePosition.collateralAmount,\n collateralConverted: mortgagePosition.collateralConverted,\n subConsol: mortgagePosition.subConsol,\n interestRate: mortgagePosition.interestRate,\n conversionPremiumRate: mortgagePosition.conversionPremiumRate,\n dateOriginated: mortgagePosition.dateOriginated,\n termOriginated: mortgagePosition.termOriginated,\n termBalance: mortgagePosition.termBalance,\n amountBorrowed: mortgagePosition.amountBorrowed,\n amountPrior: mortgagePosition.amountPrior,\n termPaid: mortgagePosition.termPaid,\n termConverted: mortgagePosition.termConverted,\n amountConverted: mortgagePosition.amountConverted,\n penaltyAccrued: mortgagePosition.penaltyAccrued,\n penaltyPaid: mortgagePosition.penaltyPaid,\n paymentsMissed: mortgagePosition.paymentsMissed,\n totalPeriods: mortgagePosition.totalPeriods,\n status: mortgagePosition.status,\n hasPaymentPlan: mortgagePosition.hasPaymentPlan\n });\n }\n\n /**\n * @dev Evaluates if two mortgage positions are equal\n * @param mortgagePosition The mortgage position to evaluate\n * @param other The other mortgage position to evaluate\n * @return True if the mortgage positions are equal, false otherwise\n */\n function equals(MortgagePosition memory mortgagePosition, MortgagePosition memory other)\n internal\n pure\n returns (bool)\n {\n return (mortgagePosition.tokenId == other.tokenId && mortgagePosition.collateral == other.collateral\n && mortgagePosition.collateralDecimals == other.collateralDecimals\n && mortgagePosition.collateralAmount == other.collateralAmount\n && mortgagePosition.collateralConverted == other.collateralConverted\n && mortgagePosition.subConsol == other.subConsol && mortgagePosition.interestRate == other.interestRate\n && mortgagePosition.conversionPremiumRate == other.conversionPremiumRate\n && mortgagePosition.dateOriginated == other.dateOriginated\n && mortgagePosition.termOriginated == other.termOriginated && mortgagePosition.termBalance == other.termBalance\n && mortgagePosition.amountBorrowed == other.amountBorrowed && mortgagePosition.amountPrior == other.amountPrior\n && mortgagePosition.termPaid == other.termPaid && mortgagePosition.termConverted == other.termConverted\n && mortgagePosition.amountConverted == other.amountConverted\n && mortgagePosition.penaltyAccrued == other.penaltyAccrued && mortgagePosition.penaltyPaid == other.penaltyPaid\n && mortgagePosition.paymentsMissed == other.paymentsMissed\n && mortgagePosition.totalPeriods == other.totalPeriods && mortgagePosition.status == other.status\n && mortgagePosition.hasPaymentPlan == other.hasPaymentPlan);\n }\n\n /**\n * @dev Converts a payment amount to the principal amount being paid off\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @return The principal amount of the payment\n */\n function convertPaymentToPrincipal(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n if (mortgagePosition.termBalance == 0) {\n return 0;\n }\n return Math.mulDiv(\n amount,\n mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior,\n mortgagePosition.termBalance,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the delta in principal created from a payment\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @return The principal delta created\n */\n function calculatePrincipalDelta(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n return mortgagePosition.convertPaymentToPrincipal(\n mortgagePosition.termPaid + mortgagePosition.termConverted + amount\n ) - mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid + mortgagePosition.termConverted);\n }\n\n /**\n * @dev Converts a principal amount to the total debt being paid\n * @param mortgagePosition The mortgage position\n * @param amount The amount of principal\n * @return The payment amount\n */\n function convertPrincipalToPayment(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (uint256)\n {\n if (mortgagePosition.termBalance == 0) {\n return 0;\n }\n return Math.mulDiv(\n amount,\n mortgagePosition.termBalance,\n mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior,\n Math.Rounding.Ceil\n );\n }\n\n /**\n * @dev Defined as the amount of principal that is left to be repaid (not including interest)\n * @param mortgagePosition The mortgage position\n * @return The amount of principal that is left to be repaid\n */\n function principalRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.amountBorrowed - mortgagePosition.amountConverted - mortgagePosition.amountPrior\n - mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid + mortgagePosition.termConverted);\n }\n\n /**\n * @dev Defined as the amount of debt left to be repaid in the current term (includes interest)\n * @param mortgagePosition The mortgage position\n * @return The amount of debt that is left to be repaid\n */\n function termRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.termBalance - mortgagePosition.termConverted - mortgagePosition.termPaid;\n }\n\n /**\n * @dev Defined as the amount of collateral left to be converted\n * @param mortgagePosition The mortgage position\n * @return The amount of collateral that is left to be converted\n */\n function collateralRemaining(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return mortgagePosition.collateralAmount - mortgagePosition.collateralConverted;\n }\n\n /**\n * @dev Calculates the term balance of a mortgage position using the simple interest formula\n * @dev termBalance = debt * (1 + interestRate * number of years)\n * @dev termBalance = debt * (BPS + interestBPS * number of years) / BPS\n * @dev termBalance = debt * (BPS * PERIODS_PER_YEAR + interestBPS * totalPeriods) / (BPS * PERIODS_PER_YEAR)\n * @param principal The principal amount of the mortgage\n * @param interestRate The interest rate of the mortgage\n * @param totalPeriods The total number of periods of the mortgage\n * @param periodsLeft The number of periods left to be paid\n * @return termBalance The term balance of the mortgage position\n */\n function calculateTermBalance(uint256 principal, uint256 interestRate, uint8 totalPeriods, uint8 periodsLeft)\n internal\n pure\n returns (uint256 termBalance)\n {\n // Apply simple interest formula to calculate the total owed\n termBalance = Math.mulDiv(\n principal,\n Constants.BPS * Constants.PERIODS_PER_YEAR + (interestRate * totalPeriods),\n (Constants.BPS * Constants.PERIODS_PER_YEAR),\n Math.Rounding.Floor\n );\n // Round it up so that the termBalance is a multiple of the periodsLeft (each month has the same payment)\n termBalance += (periodsLeft - (termBalance % periodsLeft)) % periodsLeft;\n }\n\n /**\n * @dev Calculates the monthly payment of a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The monthly payment\n */\n function monthlyPayment(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n // If the mortgage does not have a payment plan, the mortgage is paid in full at the end of the term\n if (!mortgagePosition.hasPaymentPlan) {\n return 0;\n }\n // Otherwise, calculate the monthly payment\n return mortgagePosition.termBalance / mortgagePosition.totalPeriods;\n }\n\n /**\n * @dev Calculates the purchase price of a mortgage position by dividing the amount borrowed by the collateral amount\n * @param mortgagePosition The mortgage position\n * @return The purchase price\n */\n function purchasePrice(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return Math.mulDiv(\n mortgagePosition.amountBorrowed,\n 2 * (10 ** mortgagePosition.collateralDecimals),\n mortgagePosition.collateralAmount,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the price at which the collateral must be in order for the mortgage position to be convertible\n * @param mortgagePosition The mortgage position\n * @return The price at which the collateral must be in order for the mortgage position to be convertible\n */\n function conversionTriggerPrice(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n return Math.mulDiv(\n (Constants.BPS + mortgagePosition.conversionPremiumRate) * mortgagePosition.amountBorrowed,\n 2 * (10 ** mortgagePosition.collateralDecimals),\n Constants.BPS * mortgagePosition.collateralAmount,\n Math.Rounding.Floor\n );\n }\n\n /**\n * @dev Calculates the amount of principal that has been forfeited after a foreclosure. Returns 0 if the mortgage position is not foreclosed.\n * @param mortgagePosition The mortgage position\n * @return The amount of principal that has been forfeited\n */\n function amountForfeited(MortgagePosition memory mortgagePosition) internal pure returns (uint256) {\n if (mortgagePosition.status != MortgageStatus.FORECLOSED) {\n return 0;\n }\n return mortgagePosition.amountPrior + mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid);\n }\n\n /**\n * @dev Creates a new mortgage position\n * @param tokenId The token ID of the mortgage position\n * @param collateral The address of the collateral\n * @param collateralDecimals The number of decimals of the collateral\n * @param subConsol The address of the subConsol\n * @param collateralAmount The amount of collateral\n * @param amountBorrowed The amount of principal borrowed\n * @param interestRate The interest rate of the mortgage\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param totalPeriods The total number of periods of the mortgage\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @return The new mortgage position\n */\n function createNewMortgagePosition(\n uint256 tokenId,\n address collateral,\n uint8 collateralDecimals,\n address subConsol,\n uint256 collateralAmount,\n uint256 amountBorrowed,\n uint16 interestRate,\n uint16 conversionPremiumRate,\n uint8 totalPeriods,\n bool hasPaymentPlan\n ) internal view returns (MortgagePosition memory) {\n return MortgagePosition({\n tokenId: tokenId,\n collateral: collateral,\n collateralDecimals: collateralDecimals,\n collateralAmount: collateralAmount,\n collateralConverted: 0,\n subConsol: subConsol,\n interestRate: interestRate,\n conversionPremiumRate: conversionPremiumRate,\n dateOriginated: uint32(block.timestamp),\n termOriginated: uint32(block.timestamp),\n termBalance: calculateTermBalance(amountBorrowed, interestRate, totalPeriods, totalPeriods),\n amountBorrowed: amountBorrowed,\n amountPrior: 0,\n termPaid: 0,\n termConverted: 0,\n amountConverted: 0,\n penaltyAccrued: 0,\n penaltyPaid: 0,\n paymentsMissed: 0,\n totalPeriods: totalPeriods,\n hasPaymentPlan: hasPaymentPlan,\n status: MortgageStatus.ACTIVE\n });\n }\n\n /**\n * @dev Calculates the current number of periods that have been paid for a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The number of periods paid\n */\n function periodsPaid(MortgagePosition memory mortgagePosition) internal pure returns (uint8) {\n // Calculate the number of periods paid based on the fraction of (termPaid+termConverted)/termBalance\n if (mortgagePosition.termBalance == 0) {\n return mortgagePosition.totalPeriods;\n }\n\n return uint8(\n Math.mulDiv(\n mortgagePosition.totalPeriods,\n mortgagePosition.termPaid + mortgagePosition.termConverted,\n mortgagePosition.termBalance,\n Math.Rounding.Floor\n )\n );\n }\n\n /**\n * @dev Updates the mortgage position with a periodic payment\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the payment\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @return The updated mortgage position and the principal payment\n * @return principalPayment The principal payment\n * @return refund The amount of the refund in the case of overpayment\n */\n function periodPay(MortgagePosition memory mortgagePosition, uint256 amount, uint256 latePenaltyWindow)\n internal\n view\n returns (MortgagePosition memory, uint256 principalPayment, uint256 refund)\n {\n // Revert if the amount is zero\n if (amount == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Ensure that the amount is not greater than the termBalance. Refund the surplus.\n uint256 _termRemaining = mortgagePosition.termRemaining();\n if (_termRemaining == 0 && amount > 0) {\n revert CannotOverpay(mortgagePosition, amount);\n }\n // If the mortgage does not have a payment plan, the mortgage is paid in full at the end of the term\n if (!mortgagePosition.hasPaymentPlan && amount < mortgagePosition.termRemaining()) {\n revert CannotPartialPrepay(mortgagePosition);\n }\n // Calculate the refund and subtract it from the amount\n if (amount > _termRemaining) {\n refund = amount - _termRemaining;\n amount = _termRemaining;\n }\n // Calculate principal payment\n principalPayment = mortgagePosition.calculatePrincipalDelta(amount);\n\n // Update the termPaid\n mortgagePosition.termPaid += amount;\n\n // Make sure paymentsMissed is up to date\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If the mortgage is paid in full, there are no more missed payments since and additional penalties can no longer be applied\n if (_periodsPaid == mortgagePosition.totalPeriods) {\n mortgagePosition.paymentsMissed = 0;\n } else {\n // If the mortgage has a payment plan, the number of missed payments is the difference between the periods since origination and the periods paid\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n mortgagePosition.paymentsMissed =\n _periodsPaid > periodsSinceOrigination ? 0 : periodsSinceOrigination - _periodsPaid;\n }\n\n // Return the updated mortgage position\n return (mortgagePosition, principalPayment, refund);\n }\n\n /**\n * @dev Calculates the number of periods since the term origination\n * @param mortgagePosition The mortgage position\n * @param latePaymentWindow The number of days after the due date that a payment is still considered on time\n * @return periods The number of periods since the term origination\n */\n function periodsSinceTermOrigination(MortgagePosition memory mortgagePosition, uint256 latePaymentWindow)\n internal\n view\n returns (uint8 periods)\n {\n if (mortgagePosition.termOriginated == 0) {\n return 0;\n }\n // Calculate the number of since origination\n periods = uint8((block.timestamp - mortgagePosition.termOriginated) / Constants.PERIOD_DURATION);\n // If the late payment window can impact the number of periods, subtract one\n if (\n periods > 0\n && (block.timestamp - mortgagePosition.termOriginated) % Constants.PERIOD_DURATION <= latePaymentWindow\n ) {\n periods -= 1;\n }\n }\n\n /**\n * @dev Calculates the penalty amount for a mortgage position given a number of additional payments missed and the current penalty rate\n * @param mortgagePosition The mortgage position\n * @param additionalPaymentsMissed The number of additional payments missed\n * @param penaltyRate The penalty rate\n * @return The penalty amount\n */\n function calculatePenaltyAmount(\n MortgagePosition memory mortgagePosition,\n uint8 additionalPaymentsMissed,\n uint16 penaltyRate\n ) internal pure returns (uint256) {\n // This is monthlyPayment * additionalPaymentsMissed * (1 + penaltyRate)\n // Mortgages without a payment plan don't have monthlyPayments, so we use the termBalance and totalPeriods instead\n return Math.mulDiv(\n mortgagePosition.termBalance,\n uint256(additionalPaymentsMissed) * penaltyRate,\n mortgagePosition.totalPeriods * Constants.BPS,\n Math.Rounding.Ceil\n );\n }\n\n /**\n * @dev Applies missing penalties to a mortgage position\n * @param mortgagePosition The mortgage position\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @param penaltyRate The penalty rate\n * @return The updated mortgage position\n * @return penaltyAmount The penalty amount\n * @return additionalPaymentsMissed The number of additional payments missed\n */\n function applyPenalties(MortgagePosition memory mortgagePosition, uint256 latePenaltyWindow, uint16 penaltyRate)\n internal\n view\n returns (MortgagePosition memory, uint256 penaltyAmount, uint8 additionalPaymentsMissed)\n {\n // Calculate the number of periods missed\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If _periodsPaid >= periodsSinceOrigination, then it is not possible to have missed payments\n // If periodsPaid = totalPeriods, then it is not possible to have missed payments\n if (periodsSinceOrigination > _periodsPaid && _periodsPaid < mortgagePosition.totalPeriods) {\n if (mortgagePosition.hasPaymentPlan) {\n // If the mortgage does have a payment plan, then delta is (periodsSinceOrigination - _periodsPaid)\n additionalPaymentsMissed = periodsSinceOrigination - _periodsPaid - mortgagePosition.paymentsMissed;\n } else if (periodsSinceOrigination >= mortgagePosition.totalPeriods) {\n // If the mortgage does not have a payment plan, then delta is (periodsSinceOrigination - totalPeriods + 1)\n additionalPaymentsMissed =\n periodsSinceOrigination - mortgagePosition.totalPeriods + 1 - mortgagePosition.paymentsMissed;\n }\n // If periodsMissed > paymentsMissed, then you have addition missed payments and penalties to apply\n if (additionalPaymentsMissed > 0) {\n penaltyAmount = mortgagePosition.calculatePenaltyAmount(additionalPaymentsMissed, penaltyRate);\n mortgagePosition.penaltyAccrued += penaltyAmount;\n mortgagePosition.paymentsMissed += additionalPaymentsMissed;\n }\n }\n return (mortgagePosition, penaltyAmount, additionalPaymentsMissed);\n }\n\n /**\n * @dev Pays a penalty for a mortgage position\n * @param mortgagePosition The mortgage position\n * @param amount The amount of the penalty\n * @return The updated mortgage position\n * @return refund The amount of the refund in the case of overpayment\n */\n function penaltyPay(MortgagePosition memory mortgagePosition, uint256 amount)\n internal\n pure\n returns (MortgagePosition memory, uint256 refund)\n {\n // Revert if the amount is zero\n if (amount == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Ensure that the amount is not greater than the penaltyAccrued. Refund the surplus.\n uint256 penaltyRemaining = mortgagePosition.penaltyAccrued - mortgagePosition.penaltyPaid;\n if (penaltyRemaining == 0 && amount > 0) {\n revert CannotOverpayPenalty(mortgagePosition, amount);\n }\n if (amount > penaltyRemaining) {\n refund = amount - penaltyRemaining;\n amount = penaltyRemaining;\n }\n // Increase the penalty paid by the amount\n mortgagePosition.penaltyPaid += amount;\n // paymentsMissed does not change until they make a payment.\n return (mortgagePosition, refund);\n }\n\n /**\n * @dev Redeems a mortgage position\n * @param mortgagePosition The mortgage position\n * @return The updated mortgage position\n */\n function redeem(MortgagePosition memory mortgagePosition) internal pure returns (MortgagePosition memory) {\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are unpaid payments\n if (mortgagePosition.termBalance > mortgagePosition.termPaid + mortgagePosition.termConverted) {\n revert UnpaidPayments(mortgagePosition);\n }\n // Update the status and return the updated mortgage position\n mortgagePosition.status = MortgageStatus.REDEEMED;\n return mortgagePosition;\n }\n\n /**\n * @dev Helper function to refinance/expand a mortgage position\n * @param mortgagePosition The mortgage position\n * @param principalIn The amount of principal to add to the mortgage position. 0 for refinance, >0 for expansion\n * @param newInterestRate The new interest rate.\n * @param newTotalPeriods The new total number of periods. Should stay the same for expansion.\n * @return The updated mortgage position\n */\n function _refinanceHelper(\n MortgagePosition memory mortgagePosition,\n uint256 principalIn,\n uint16 newInterestRate,\n uint8 newTotalPeriods\n ) private view returns (MortgagePosition memory) {\n uint256 principalPaid = mortgagePosition.convertPaymentToPrincipal(mortgagePosition.termPaid);\n uint256 principalConverted = mortgagePosition.convertPaymentToPrincipal(\n mortgagePosition.termPaid + mortgagePosition.termConverted\n ) - principalPaid;\n mortgagePosition.termBalance = calculateTermBalance(\n mortgagePosition.principalRemaining() + principalIn, newInterestRate, newTotalPeriods, newTotalPeriods\n );\n mortgagePosition.interestRate = newInterestRate;\n mortgagePosition.totalPeriods = newTotalPeriods;\n mortgagePosition.amountPrior += principalPaid;\n mortgagePosition.termOriginated = uint32(block.timestamp);\n mortgagePosition.termPaid = 0;\n mortgagePosition.amountConverted += principalConverted;\n mortgagePosition.termConverted = 0;\n return mortgagePosition;\n }\n\n /**\n * @dev Refinances a mortgage position\n * @param mortgagePosition The mortgage position\n * @param refinanceRate The refinance rate\n * @param newInterestRate The new interest rate\n * @param newTotalPeriods The new total number of periods\n * @return The updated mortgage position\n * @return refinanceFee The refinance fee\n */\n function refinance(\n MortgagePosition memory mortgagePosition,\n uint16 refinanceRate,\n uint16 newInterestRate,\n uint8 newTotalPeriods\n ) internal view returns (MortgagePosition memory, uint256 refinanceFee) {\n // Revert if the termRemaining is 0 (i.e. the mortgage is already paid in full)\n if (mortgagePosition.termRemaining() == 0) {\n revert ZeroAmount(mortgagePosition);\n }\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are missed payments\n if (mortgagePosition.paymentsMissed > 0) {\n revert MissedPayments(mortgagePosition);\n }\n\n // Calculate the refinance fee as a percentage of the principalRemaining\n refinanceFee = Math.mulDiv(mortgagePosition.principalRemaining(), refinanceRate, Constants.BPS, Math.Rounding.Ceil);\n\n // Add refinance fee into penaltyAccrued and penaltyPaid\n mortgagePosition.penaltyAccrued += refinanceFee;\n mortgagePosition.penaltyPaid += refinanceFee;\n\n // // Update the mortgagePosition with the new values\n mortgagePosition = _refinanceHelper(mortgagePosition, 0, newInterestRate, newTotalPeriods);\n\n // Return the updated mortgage position and the refinance fee\n return (mortgagePosition, refinanceFee);\n }\n\n /**\n * @dev Forecloses a mortgage position\n * @param mortgagePosition The mortgage position\n * @param maxMissedPayments The maximum number of missed payments\n * @return The updated mortgage position\n */\n function foreclose(MortgagePosition memory mortgagePosition, uint8 maxMissedPayments)\n internal\n pure\n returns (MortgagePosition memory)\n {\n // Revert if paymentsMissed is less than or equal to maxMissedPayments\n if (mortgagePosition.paymentsMissed <= maxMissedPayments) {\n revert NotForeclosable(mortgagePosition, maxMissedPayments);\n }\n\n // Update the status and return the updated mortgage position\n mortgagePosition.status = MortgageStatus.FORECLOSED;\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n\n /**\n * @dev Converts a mortgage position by reducing the principal and collateral\n * @param mortgagePosition The mortgage position\n * @param currentPrice The current price of the collateral\n * @param principalConverting The amount of principal to convert\n * @param collateralConverting The amount of collateral to convert\n * @param latePenaltyWindow The number of days after the due date that a payment is still considered on time\n * @return The updated mortgage position\n */\n function convert(\n MortgagePosition memory mortgagePosition,\n uint256 currentPrice,\n uint256 principalConverting,\n uint256 collateralConverting,\n uint256 latePenaltyWindow\n ) internal view returns (MortgagePosition memory) {\n // Check three conditions:\n // 1. Current price is greater than or equal to the conversion trigger price\n if (mortgagePosition.conversionTriggerPrice() > currentPrice) {\n revert ConversionTriggerPriceNotMet(mortgagePosition, currentPrice);\n }\n // 2. principalConverting is not greater than principalRemaining\n // 3. collateralConverting is not greater than collateralRemaining\n if (\n mortgagePosition.conversionTriggerPrice() > currentPrice\n || principalConverting > mortgagePosition.principalRemaining()\n || collateralConverting > mortgagePosition.collateralRemaining()\n ) {\n revert CannotOverConvert(mortgagePosition, principalConverting, collateralConverting);\n }\n\n // Update the termConverted, amountConverted, and collateralConverted fields\n mortgagePosition.termConverted += mortgagePosition.convertPrincipalToPayment(principalConverting);\n mortgagePosition.collateralConverted += collateralConverting;\n\n // Make sure paymentsMissed is up to date\n uint8 _periodsPaid = mortgagePosition.periodsPaid();\n // If the mortgage is paid in full, there are no more missed payments since and additional penalties can no longer be applied\n if (_periodsPaid == mortgagePosition.totalPeriods) {\n mortgagePosition.paymentsMissed = 0;\n } else if (mortgagePosition.hasPaymentPlan) {\n // If the mortgage has a payment plan, the number of missed payments is the difference between the periods since origination and the periods paid\n uint8 periodsSinceOrigination = mortgagePosition.periodsSinceTermOrigination(latePenaltyWindow);\n mortgagePosition.paymentsMissed =\n _periodsPaid > periodsSinceOrigination ? 0 : periodsSinceOrigination - _periodsPaid;\n }\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n\n /**\n * @dev Calculates the new interest rate for an existing mortgage position given a new principal amount, interest rate, and computes a weighted average\n * @param mortgagePosition The mortgage position\n * @param amountIn The amount of principal to add to the mortgage position\n * @param newInterestRate The new interest rate\n * @return The new average interest rate\n */\n function calculateNewAverageInterestRate(\n MortgagePosition memory mortgagePosition,\n uint256 amountIn,\n uint16 newInterestRate\n ) internal pure returns (uint16) {\n return uint16(\n (mortgagePosition.interestRate * mortgagePosition.principalRemaining() + newInterestRate * amountIn)\n / (mortgagePosition.principalRemaining() + amountIn)\n );\n }\n\n /**\n * @dev Expands the balance sheet of a mortgage position\n * @param mortgagePosition The mortgage position to expand the balance sheet of\n * @param amountIn The amount of principal to add to the mortgage position\n * @param collateralAmountIn The amount of collateral to add to the mortgage position\n * @param newInterestRate The new interest rate to set for the mortgage position\n * @return The updated mortgage position\n */\n function expandBalanceSheet(\n MortgagePosition memory mortgagePosition,\n uint256 amountIn,\n uint256 collateralAmountIn,\n uint16 newInterestRate\n ) internal view returns (MortgagePosition memory) {\n // Revert if there are unpaid penalties\n if (mortgagePosition.penaltyAccrued > mortgagePosition.penaltyPaid) {\n revert UnpaidPenalties(mortgagePosition);\n }\n // Revert if there are missed payments\n if (mortgagePosition.paymentsMissed > 0) {\n revert MissedPayments(mortgagePosition);\n }\n // Calculate the new interest rate\n uint16 averageInterestRate = mortgagePosition.calculateNewAverageInterestRate(amountIn, newInterestRate);\n\n // Update the mortgagePosition with the new values\n mortgagePosition = _refinanceHelper(mortgagePosition, amountIn, averageInterestRate, mortgagePosition.totalPeriods);\n mortgagePosition.collateralAmount += collateralAmountIn;\n mortgagePosition.amountBorrowed += amountIn;\n\n // Return the updated mortgage position\n return mortgagePosition;\n }\n}\n"},"lib/cash/src/types/MortgagePosition.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgageStatus} from \"./enums/MortgageStatus.sol\";\n\n/**\n * @notice The complete state of a mortgage position\n * @param tokenId Numerical identifier for the mortgage\n * @param collateral The address of the collateral token\n * @param collateralDecimals The decimals of the collateral token\n * @param collateralAmount The amount of collateral escrowed in the Consol contract\n * @param collateralConverted The amount of collateral that has been withdrawn as a result of a conversion\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param interestRate The interest rate of the mortgage, determined at time of initialization\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param dateOriginated The date the mortgage was originated\n * @param termOriginated The beginning of the term of the mortgage. Will differ from `dateOriginated` if the mortgage is refinanced.\n * @param termBalance The total balance of the mortgage for the current term.\n * @param amountBorrowed The amount borrowed by the borrower\n * @param amountPrior The cumulative amount of principal paid off in prior terms\n * @param termPaid The amount paid by the borrower for the current term\n * @param termConverted The amount of the current term paid via conversion in the current term.\n * @param amountConverted The amount of the principal that has been forgiven as a result of a conversion in previous terms. Excludes the current term.\n * @param penaltyAccrued Sum of penalties accrued. This number is never decremented.\n * @param penaltyPaid The penalty paid by the borrower. Incremented with every call to penaltyPay()\n * @param paymentsMissed The number of payments missed by the borrower. It records the number of penalties that have already been applied. Reset to 0 when mortgage is paid in full.\n * @param totalPeriods The total number of periods that the mortgage will last\n * @param hasPaymentPlan Whether the mortgage has a payment plan\n * @param status The status of the mortgage\n */\nstruct MortgagePosition {\n uint256 tokenId;\n address collateral;\n uint8 collateralDecimals;\n uint256 collateralAmount;\n uint256 collateralConverted;\n address subConsol;\n uint16 interestRate;\n uint16 conversionPremiumRate;\n uint32 dateOriginated;\n uint32 termOriginated;\n uint256 termBalance;\n uint256 amountBorrowed;\n uint256 amountPrior; // This one is cumulative amounts of principal paid off in prior terms\n uint256 termPaid; // This one is only for the current term\n uint256 termConverted; // This is only for the current term\n uint256 amountConverted; // This one is cumulative amounts of principal converted in previous terms\n uint256 penaltyAccrued;\n uint256 penaltyPaid;\n uint8 paymentsMissed;\n uint8 totalPeriods;\n bool hasPaymentPlan;\n MortgageStatus status;\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVault.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ILiquidityVaultEvents} from \"./ILiquidityVaultEvents.sol\";\nimport {ILiquidityVaultErrors} from \"./ILiquidityVaultErrors.sol\";\n\n/**\n * @title ILiquidityVault\n * @author @SocksNFlops\n * @notice Interface for LiquidityVault, a yield-bearing vault that enables depositing tokens for redeemable shares that earn yield.\n */\ninterface ILiquidityVault is IERC20, ILiquidityVaultEvents, ILiquidityVaultErrors {\n /**\n * @notice The role for the keeper\n * @return The role for the keeper\n */\n // solhint-disable-next-line func-name-mixedcase\n function KEEPER_ROLE() external view returns (bytes32);\n\n /**\n * @notice\n * @return The role for the whitelist\n */\n // solhint-disable-next-line func-name-mixedcase\n function WHITELIST_ROLE() external view returns (bytes32);\n\n /**\n * @notice Whether the whitelist is enforced.\n * @return Whether the whitelist is enforced.\n */\n function whitelistEnforced() external view returns (bool);\n\n /**\n * @notice Enforces the whitelist.\n * @param enforced Whether the whitelist is enforced.\n */\n function setWhitelistEnforced(bool enforced) external;\n\n /**\n * @notice The decimals offset. The number of decimals to offset the shares by. Used to protect against inflation attacks.\n * @return The decimals offset\n */\n function decimalsOffset() external view returns (uint8);\n\n /**\n * @notice The total assets of the vault\n * @return The total assets of the vault\n */\n function totalAssets() external view returns (uint256);\n\n /**\n * @notice The address of the depositable asset.\n * @return The address of the depositable asset.\n */\n function depositableAssets() external view returns (address[] memory);\n\n /**\n * @notice The addresses of the redeemable assets.\n * @return The addresses of the redeemable assets.\n */\n function redeemableAssets() external view returns (address[] memory);\n\n /**\n * @notice Sets the paused state of the vault.\n * @param paused The paused state of the vault.\n */\n function setPaused(bool paused) external;\n\n /**\n * @notice Deposits the specified amount of depositable asset into the vault.\n * @param depositableAsset The address of the depositable asset to deposit.\n * @param assets The amount of depositable asset to deposit.\n */\n function deposit(address depositableAsset, uint256 assets) external;\n\n /**\n * @notice Redeems the specified amount of shares for the redeemable asset.\n * @param shares The amount of shares to redeem.\n */\n function redeem(uint256 shares) external;\n}\n"},"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev The `account` is missing a role.\n */\n error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n /**\n * @dev The caller of a function is not the expected one.\n *\n * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n */\n error AccessControlBadConfirmation();\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted to signal this.\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `callerConfirmation`.\n */\n function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"},"lib/cash/src/types/orders/MortgageParams.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @notice The parameters for creating a mortgage position\n * @param owner The address of the owner of the mortgage\n * @param tokenId The tokenId of the mortgage NFT\n * @param collateral The address of the collateral token\n * @param collateralDecimals The decimals of the collateral token\n * @param collateralAmount The amount of collateral escrowed in the Consol contract\n * @param subConsol The address of the SubConsol contract holding the collateral\n * @param interestRate The interest rate of the mortgage\n * @param conversionPremiumRate The rate at which the value of the collateral must grow before being convertible.\n * @param amountBorrowed The total amount being borrowed from all origination pools\n * @param totalPeriods The total umber of periods that the mortgage will last\n * @param hasPaymentPlan Whether the mortgage is hasPaymentPlan (periodic payment plan vs single payment)\n */\nstruct MortgageParams {\n address owner;\n uint256 tokenId;\n address collateral;\n uint8 collateralDecimals;\n uint256 collateralAmount;\n address subConsol;\n uint16 interestRate;\n uint16 conversionPremiumRate;\n uint256 amountBorrowed;\n uint8 totalPeriods;\n bool hasPaymentPlan;\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManagerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILoanManagerErrors\n * @author Socks&Flops\n * @notice Interface for all errors in the LoanManager contract\n */\ninterface ILoanManagerEvents {\n /**\n * @notice Emitted when a mortgage is created\n * @param tokenId The numerical index of the mortgageNFT\n * @param owner The owner of the mortgage\n * @param collateral The collateral address\n * @param collateralAmount The collateral amount\n * @param amountBorrowed The amount borrowed\n */\n event CreateMortgage(\n uint256 indexed tokenId,\n address indexed owner,\n address indexed collateral,\n uint256 collateralAmount,\n uint256 amountBorrowed\n );\n\n /**\n * @notice Emitted when a mortgage position has a monthly payment paid\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountPaid The amount paid\n * @param periodsPaid The number of periods paid\n */\n event PeriodPay(uint256 indexed tokenId, uint256 amountPaid, uint8 periodsPaid);\n\n /**\n * @notice Emitted when a mortgage position has a penalty paid\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountPaid The amount paid\n */\n event PenaltyPay(uint256 indexed tokenId, uint256 amountPaid);\n\n /**\n * @notice Emitted when a penalty is imposed on a mortgage position\n * @param tokenId The numerical index of the mortgageNFT\n * @param penaltyAmount The penalty amount added to the mortgage position\n * @param additionalMissedPayments The number of missed payments added to the mortgage position\n * @param penaltyAccrued The total penalty accrued so far\n * @param paymentsMissed The total number of payments missed so far\n */\n event PenaltyImposed(\n uint256 indexed tokenId,\n uint256 penaltyAmount,\n uint8 additionalMissedPayments,\n uint256 penaltyAccrued,\n uint8 paymentsMissed\n );\n\n /**\n * @notice Emitted when a mortgage is redeemed\n * @param tokenId The numerical index of the mortgageNFT\n */\n event RedeemMortgage(uint256 indexed tokenId);\n\n /**\n * @notice Emitted when a mortgage is refinanced\n * @param tokenId The numerical index of the mortgageNFT\n * @param timestamp The timestamp of the refinance\n * @param refinanceFee The refinance fee\n * @param interestRate The interest rate\n * @param principalRemaining The principal remaining\n */\n event RefinanceMortgage(\n uint256 indexed tokenId, uint256 timestamp, uint256 refinanceFee, uint16 interestRate, uint256 principalRemaining\n );\n\n /**\n * @notice Emitted when a mortgage is foreclosed\n * @param tokenId The numerical index of the mortgageNFT\n */\n event ForecloseMortgage(uint256 indexed tokenId);\n\n /**\n * @notice Emitted when a mortgage is converted\n * @param tokenId The numerical index of the mortgageNFT\n * @param amount The amount of the mortgage that is being converted\n * @param collateralAmount The amount of the collateral that is being converted\n * @param receiver The address receiving the converted collateral\n */\n event ConvertMortgage(uint256 indexed tokenId, uint256 amount, uint256 collateralAmount, address receiver);\n\n /**\n * @notice Emitted when the balance sheet of a mortgage position is expanded\n * @param tokenId The numerical index of the mortgageNFT\n * @param amountIn The amount of the principal being added to the mortgage position\n * @param collateralAmountIn The amount of collateral being added to the mortgage position\n * @param newInterestRate The new interest rate of the mortgage position\n */\n event ExpandBalanceSheet(\n uint256 indexed tokenId, uint256 amountIn, uint256 collateralAmountIn, uint16 newInterestRate\n );\n}\n"},"lib/cash/src/interfaces/ILoanManager/ILoanManagerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {MortgageStatus} from \"../../types/MortgagePosition.sol\";\n\n/**\n * @title ILoanManagerErrors\n * @author Socks&Flops\n * @notice Interface for all errors in the LoanManager contract\n */\ninterface ILoanManagerErrors {\n /**\n * @notice Thrown when a non-general manager attempts to call an operation that requires general manager access\n * @param caller The address of the caller\n * @param generalManager The address of the general manager\n */\n error OnlyGeneralManager(address caller, address generalManager);\n\n /**\n * @notice Thrown when the amount borrowed is below the minimum threshold\n * @param amountBorrowed The amount borrowed\n * @param minAmountBorrowed The minimum amount borrowed\n */\n error AmountBorrowedBelowMinimum(uint256 amountBorrowed, uint256 minAmountBorrowed);\n\n /**\n * @notice Thrown when a mortgage position does not exist\n * @param tokenId The tokenId of the mortgage\n */\n error MortgagePositionDoesNotExist(uint256 tokenId);\n\n /**\n * @notice Thrown when a mortgage position is not active\n * @param tokenId The tokenId of the mortgage\n * @param status The status of the mortgage\n */\n error MortgagePositionNotActive(uint256 tokenId, MortgageStatus status);\n\n /**\n * @notice Thrown when a non-mortgage owner attempts to call an operation that requires ownership\n * @param tokenId The tokenId of the mortgage\n * @param owner The owner of the mortgage\n * @param caller The caller of the function\n */\n error OnlyMortgageOwner(uint256 tokenId, address owner, address caller);\n}\n"},"lib/cash/src/interfaces/IConsolFlashSwap.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolFlashSwap\n * @author SocksNFlops\n * @notice Any contract that calls IConsol#flashSwap must implement this interface\n */\ninterface IConsolFlashSwap {\n /**\n * @notice Thrown when a non-Consol contract attempts to call IConsolFlashSwap#flashSwapCallback\n * @param caller The address of the caller\n * @param consol The address of the Consol contract\n */\n error OnlyConsol(address caller, address consol);\n\n /**\n * @notice Called to `msg.sender` after transferring to the recipient from IConsol#flashSwap.\n * @dev In the implementation you must repay the inputTokens sent in the outputToken currency\n * @param inputToken The address of the input token\n * @param outputToken The address of the output token\n * @param amount The amount of tokens to swap\n * @param data The data to pass into the callback\n */\n function flashSwapCallback(address inputToken, address outputToken, uint256 amount, bytes calldata data) external;\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManagerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.24;\n\n/**\n * @title IGeneralManagerEvents\n * @author @SocksNFlops\n * @notice Events emitted by the GeneralManager contract\n */\ninterface IGeneralManagerEvents {\n /**\n * @notice Emitted when the penalty rate is set\n * @param oldPenaltyRate The old penalty rate\n * @param newPenaltyRate The new penalty rate\n */\n event PenaltyRateSet(uint16 oldPenaltyRate, uint16 newPenaltyRate);\n\n /**\n * @notice Emitted when the refinance rate is set\n * @param oldRefinanceRate The old refinance rate\n * @param newRefinanceRate The new refinance rate\n */\n event RefinanceRateSet(uint16 oldRefinanceRate, uint16 newRefinanceRate);\n\n /**\n * @notice Emitted when the insurance fund address is set\n * @param oldInsuranceFund The old insurance fund address\n * @param newInsuranceFund The new insurance fund address\n */\n event InsuranceFundSet(address oldInsuranceFund, address newInsuranceFund);\n\n /**\n * @notice Emitted when the interest rate oracle address is set\n * @param oldInterestRateOracle The old interest rate oracle address\n * @param newInterestRateOracle The new interest rate oracle address\n */\n event InterestRateOracleSet(address oldInterestRateOracle, address newInterestRateOracle);\n\n /**\n * @notice Emitted when the conversion premium rate is set\n * @param oldConversionPremiumRate The old conversion premium rate\n * @param newConversionPremiumRate The new conversion premium rate\n */\n event ConversionPremiumRateSet(uint16 oldConversionPremiumRate, uint16 newConversionPremiumRate);\n\n /**\n * @notice Emitted when the origination pool scheduler address is set\n * @param oldOriginationPoolScheduler The old origination pool scheduler address\n * @param newOriginationPoolScheduler The new origination pool scheduler address\n */\n event OriginationPoolSchedulerSet(address oldOriginationPoolScheduler, address newOriginationPoolScheduler);\n\n /**\n * @notice Emitted when the loan manager address is set\n * @param oldLoanManager The old loan manager address\n * @param newLoanManager The new loan manager address\n */\n event LoanManagerSet(address oldLoanManager, address newLoanManager);\n\n /**\n * @notice Emitted when the order pool address is set\n * @param oldOrderPool The old order pool address\n * @param newOrderPool The new order pool address\n */\n event OrderPoolSet(address oldOrderPool, address newOrderPool);\n\n /**\n * @notice Emitted when the supported mortgage period terms are updated\n * @param collateral The address of the collateral\n * @param mortgagePeriods The mortgage period\n * @param isSupported Whether the mortgage period terms are supported\n */\n event SupportedMortgagePeriodTermsUpdated(address indexed collateral, uint8 mortgagePeriods, bool isSupported);\n\n /**\n * @notice Emitted when a price oracle is set\n * @param collateral The address of the collateral\n * @param priceOracle The address of the new oracle\n */\n event PriceOracleSet(address indexed collateral, address indexed priceOracle);\n\n /**\n * @notice Emitted when the minimum cap for a collateral is set\n * @param collateral The address of the collateral\n * @param minimumCap The minimum cap\n */\n event MinimumCapSet(address indexed collateral, uint256 minimumCap);\n\n /**\n * @notice Emitted when the maximum cap for a collateral is set\n * @param collateral The address of the collateral\n * @param maximumCap The maximum cap\n */\n event MaximumCapSet(address indexed collateral, uint256 maximumCap);\n\n /**\n * @notice Emitted when the price spread is set\n * @param oldPriceSpread The old price spread\n * @param newPriceSpread The new price spread\n */\n event PriceSpreadSet(uint16 oldPriceSpread, uint16 newPriceSpread);\n}\n"},"lib/cash/src/interfaces/IGeneralManager/IGeneralManagerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.24;\n\nimport {CreationRequest} from \"../../types/orders/OrderRequests.sol\";\n\n/**\n * @title IGeneralManagerErrors\n * @author @SocksNFlops\n * @notice Errors emitted by the GeneralManager contract\n */\ninterface IGeneralManagerErrors {\n /**\n * @notice The origination pool is not registered with the scheduler\n * @param originationPool The address of the origination pool\n */\n error InvalidOriginationPool(address originationPool);\n\n /**\n * @notice The origination pools array is empty\n */\n error EmptyOriginationPools();\n\n /**\n * @notice Duplicate origination pools provided in request\n * @param originationPool The address of the origination pool\n */\n error DuplicateOriginationPool(address originationPool);\n\n /**\n * @notice The subConsol is not backed by the collateral or is not supported by the consol\n * @param collateral The address of the collateral\n * @param subConsol The address of the subConsol\n * @param consol The address of the consol\n */\n error InvalidSubConsol(address collateral, address subConsol, address consol);\n\n /**\n * @notice The total periods exceed the maximum possible number of periods\n * @param totalPeriods The total periods\n * @param maxTotalPeriods The maximum possible number of periods\n */\n error TotalPeriodsExceedsMaximum(uint8 totalPeriods, uint8 maxTotalPeriods);\n\n /**\n * @notice The total periods are invalid\n * @param collateral The address of the collateral\n * @param totalPeriods The total periods\n */\n error InvalidTotalPeriods(address collateral, uint8 totalPeriods);\n\n /**\n * @notice The origination pools list length does not match the collateral amounts list length\n * @param originationPoolsListLength The length of the origination pools list\n * @param collateralAmountsListLength The length of the collateral amounts list\n */\n error OriginationPoolsListLengthMismatch(uint256 originationPoolsListLength, uint256 collateralAmountsListLength);\n\n /**\n * @notice The caller is not the order pool\n * @param caller The address of the caller\n * @param orderPool The address of the order pool\n */\n error OnlyOrderPool(address caller, address orderPool);\n\n /**\n * @notice The conversion queue is not registered\n * @param conversionQueue The address of the conversion queue\n */\n error InvalidConversionQueue(address conversionQueue);\n\n /**\n * @notice The mortgage is already enqueued in the conversion queue\n * @param tokenId The tokenId of the mortgage\n * @param conversionQueue The address of the conversion queue\n */\n error MortgageAlreadyEnqueuedInConversionQueue(uint256 tokenId, address conversionQueue);\n\n /**\n * @notice Thrown when the caller is not the owner of the mortgageNFT\n * @param caller The caller of the function\n * @param owner The owner of the mortgageNFT\n * @param tokenId The tokenId of the mortgageNFT\n */\n error NotMortgageOwner(address caller, address owner, uint256 tokenId);\n\n /**\n * @notice Thrown when a compounding mortgage is being created and a conversion queue is not provided\n * @param creationRequest The create request\n */\n error CompoundingMustConvert(CreationRequest creationRequest);\n\n /**\n * @notice Thrown when a non-compounding mortgage is being created and the hasPaymentPlan flag is not set to true\n * @param creationRequest The create request\n */\n error NonCompoundingMustHavePaymentPlan(CreationRequest creationRequest);\n\n /**\n * @notice Thrown when the total periods of the expansion request does not match the existing mortgage position\n * @param totalPeriods The total periods of the expansion request\n * @param existingTotalPeriods The total periods of the existing mortgage position\n */\n error ExpansionTotalPeriodsMismatch(uint8 totalPeriods, uint8 existingTotalPeriods);\n\n /**\n * @notice Thrown when the amount borrowed is below the minimum cap for the collateral\n * @param collateral The address of the collateral\n * @param amountBorrowed The amount borrowed\n * @param minimumCap The minimum cap\n */\n error MinimumCapNotMet(address collateral, uint256 amountBorrowed, uint256 minimumCap);\n\n /**\n * @notice Thrown when the amount borrowed is above the maximum cap for the collateral\n * @param collateral The address of the collateral\n * @param amountBorrowed The amount borrowed\n * @param maximumCap The maximum cap\n */\n error MaximumCapExceeded(address collateral, uint256 amountBorrowed, uint256 maximumCap);\n\n /**\n * @notice Thrown when the caller sends too little gas to the contract\n * @param sentGas The amount of gas sent\n * @param requiredGas The required gas\n */\n error InsufficientGas(uint256 sentGas, uint256 requiredGas);\n\n /**\n * @notice Failed Withdraw Native Gas.\n * @param amount The amount of native gas to withdraw\n */\n error FailedToWithdrawNativeGas(uint256 amount);\n}\n"},"lib/cash/src/interfaces/IOriginationPoolDeployCallback.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IOriginationPoolDeployCallback\n * @author SocksNFlops\n * @notice Any contract that calls IOriginationPool#deploy must implement this interface\n */\ninterface IOriginationPoolDeployCallback {\n /**\n * @notice Called to `msg.sender` after transferring to the recipient from IOriginationPool#deploy.\n * @dev In the implementation you must repay the pool the tokens sent by flash after the pool multiplier has been applied.\n * @param amount The amount of consol sent to the callback\n * @param returnAmount The amount of consol to return to the origination pool\n * @param data Any data passed through by the caller via the IOriginationPool#deploy call\n */\n function originationPoolDeployCallback(uint256 amount, uint256 returnAmount, bytes calldata data) external;\n}\n"},"lib/cash/src/types/orders/OriginationParameters.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {MortgageParams} from \"../orders/MortgageParams.sol\";\n\n/**\n * @notice The parameters for originating a mortgage creation or balance sheet expansion\n * @param mortgageParams The parameters for the mortgage\n * @param fulfiller The address of the fulfiller\n * @param originationPools The addresses of the origination pools to deploy funds from\n * @param borrowAmounts The amounts being borrowed from each origination pool. Sum must be equal to mortgageParams.amountBorrowed\n * @param conversionQueues The addresses of the conversion queues to use\n * @param hintPrevIds The hintPrevIds of the mortgage\n * @param expansion Whether the mortgage is a balance sheet expansion of an existing position\n * @param purchaseAmount The amount of USDX to purchase\n */\nstruct OriginationParameters {\n MortgageParams mortgageParams;\n address fulfiller;\n address[] originationPools;\n uint256[] borrowAmounts;\n address[] conversionQueues;\n uint256[] hintPrevIds;\n bool expansion;\n uint256 purchaseAmount;\n}\n"},"lib/cash/src/interfaces/IPausable/IPausable.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IPausableErrors} from \"./IPausableErrors.sol\";\n\n/**\n * @title IPausable\n * @author @SocksNFlops\n * @notice Interface for the pausable contract\n */\ninterface IPausable is IPausableErrors {\n /**\n * @notice Pause or unpause the contract\n * @param pause The new paused state\n */\n function setPaused(bool pause) external;\n\n /**\n * @notice Get the paused state of the contract\n * @return The paused state of the contract\n */\n function paused() external view returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n /*\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n * 0xb0202a11 ===\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n */\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n * @param from The address which you want to send tokens from.\n * @param to The address which you want to transfer to.\n * @param value The amount of tokens to be transferred.\n * @param data Additional data with no specified format, sent in call to `to`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value) external returns (bool);\n\n /**\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n * @param spender The address which will spend the funds.\n * @param value The amount of tokens to be spent.\n * @param data Additional data with no specified format, sent in call to `spender`.\n * @return A boolean value indicating whether the operation succeeded unless throwing.\n */\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPoolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IOriginationPoolEvents\n * @author SocksNFlops\n * @notice Events for the OriginationPool contract\n */\ninterface IOriginationPoolEvents {\n /**\n * @notice Event for a deposit\n * @param user The user\n * @param token The token\n * @param amount The amount of USDTokens being deposited\n * @param mintAmount The amount of OriginationPool tokens being minted\n */\n event Deposit(address indexed user, address indexed token, uint256 amount, uint256 mintAmount);\n\n /**\n * @notice Event for a deploy\n * @param user The user\n * @param token The token\n * @param amount The amount of USDTokens being deployed\n * @param receiptAmount The amount of OriginationPool tokens being returned\n */\n event Deploy(address indexed user, address indexed token, uint256 amount, uint256 receiptAmount);\n\n /**\n * @notice Event for a redeem\n * @param user The user\n * @param amount The amount of OriginationPool tokens being redeemed\n */\n event Redeem(address indexed user, uint256 amount);\n}\n"},"lib/cash/src/interfaces/IOriginationPool/IOriginationPoolErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OriginationPoolPhase} from \"../../types/enums/OriginationPoolPhase.sol\";\n\n/**\n * @title IOriginationPoolErrors\n * @author SocksNFlops\n * @notice Errors for the OriginationPool contract\n */\ninterface IOriginationPoolErrors {\n /**\n * @notice Error for incorrect phase\n * @param requiredPhase The required phase\n * @param currentPhase The current phase\n */\n error IncorrectPhase(OriginationPoolPhase requiredPhase, OriginationPoolPhase currentPhase);\n\n /**\n * @notice Error for pool limit exceeded\n * @param poolLimit The pool limit\n * @param amount The amount\n */\n error PoolLimitExceeded(uint256 poolLimit, uint256 amount);\n\n /**\n * @notice Error for insufficient consol returned\n * @param requiredAmount The required amount\n * @param amountReturned The amount returned\n */\n error InsufficientConsolReturned(uint256 requiredAmount, uint256 amountReturned);\n\n /**\n * @notice Error for insufficient amount passed to a function\n * @param amount The amount\n * @param minimumAmount The minimum amount\n */\n error InsufficientAmount(uint256 amount, uint256 minimumAmount);\n}\n"},"lib/cash/src/types/enums/OriginationPoolPhase.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @notice The phases of the Origination Pool\n */\nenum OriginationPoolPhase {\n /// @notice Lenders can deposit funds into the pool to provide liquidity for mortgage origination\n DEPOSIT,\n /// @notice Pool funds are actively deployed for mortgage origination and new deposits/withdrawals are disabled\n DEPLOY,\n /// @notice Lenders can redeem their funds from the pool along with earned fees from mortgage originations\n REDEMPTION\n}\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVault.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IMultiTokenVaultEvents} from \"./IMultiTokenVaultEvents.sol\";\nimport {IMultiTokenVaultErrors} from \"./IMultiTokenVaultErrors.sol\";\nimport {IRebasingERC20} from \"../IRebasingERC20/IRebasingERC20.sol\";\n\n/**\n * @title IMultiTokenVault\n * @author Socks&Flops\n * @notice Interface for the MultiTokenVault contract. Assumes all supported tokens deposited have same UOA.\n */\ninterface IMultiTokenVault is IRebasingERC20, IMultiTokenVaultEvents, IMultiTokenVaultErrors {\n /**\n * @notice Add a supported token to the MultiTokenVault\n * @param token The address of the token to add\n */\n function addSupportedToken(address token) external;\n\n /**\n * @notice Remove a supported token from the MultiTokenVault\n * @param token The address of the token to remove\n */\n function removeSupportedToken(address token) external;\n\n /**\n * @notice Get the list of supported tokens\n * @return The list of supported tokens\n */\n function getSupportedTokens() external view returns (address[] memory);\n\n /**\n * @notice Check if a token is supported\n * @param token The address of the token to check\n * @return isSupported True if the token is supported, false otherwise\n */\n function isTokenSupported(address token) external view returns (bool isSupported);\n\n /**\n * @notice Calculates the amount of tokens minted/burned in a deposit/withdraw operation\n * @param token The address of the token to deposit/withdraw\n * @param amount The amount of tokens to deposit/withdraw\n * @return The mint/burn amount\n */\n function convertAmount(address token, uint256 amount) external view returns (uint256);\n\n /**\n * @notice Calculates the amount of underlying tokens required to deposit/withdraw a given amount of tokens\n * @param token The address of the token to deposit/withdraw\n * @param amount The amount of tokens minted/burned as a result of the deposit/withdraw operation\n * @return The amount of underlying tokens required to deposit/withdraw the given amount of tokens\n */\n function convertUnderlying(address token, uint256 amount) external view returns (uint256);\n\n /**\n * @notice Deposit tokens into the MultiTokenVault and mint an equivalent amount of the MultiTokenVault token.\n * @param token The address of the token to deposit\n * @param amount The amount of tokens to deposit\n */\n function deposit(address token, uint256 amount) external;\n\n /**\n * @notice Withdraw tokens from the MultiTokenVault and burn an equivalent amount of the MultiTokenVault token.\n * @param token The address of the token to withdraw\n * @param amount The amount of tokens to withdraw\n */\n function withdraw(address token, uint256 amount) external;\n\n /**\n * @notice Forfeit tokens from the MultiTokenVault. Redistributes the forfeited tokens to the existing holders.\n * @param amount The amount of tokens to forfeit\n */\n function forfeit(uint256 amount) external;\n\n /**\n * @notice Given shares and an amount, this will burn shares until the amount is reached.\n * @dev This is achieved by burning all of the shares and minting the amount. Will no-op if attempting to mint more than the shares correspond to.\n * @param shares The amount of shares to burn\n * @param amount The amount of tokens to mint\n */\n function burnExcessShares(uint256 shares, uint256 amount) external;\n\n /**\n * @notice Set the absolute maximum cap for an underlying token.\n * @param token The address of the token to set the cap for\n * @param _maximumCap The new maximum cap for the token denominated in the UOA. Default is type(uint256).max.\n */\n function setMaximumCap(address token, uint256 _maximumCap) external;\n\n /**\n * @notice Get the absolute maximum cap for a token\n * @param token The address of the token to get the cap for\n * @return The maximum cap for the token denominated in the UOA.\n */\n function maximumCap(address token) external view returns (uint256);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsolErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolErrors\n * @author SocksNFlops\n * @notice Interface for the Consol errors.\n */\ninterface IConsolErrors {\n /**\n * @notice Forfeited assets pool is not set.\n */\n error ForfeitedAssetsPoolNotSet();\n\n /**\n * @notice Insufficient tokens returned.\n * @param amount The amount of tokens that were expected to be returned\n * @param actualAmount The amount of tokens that were returned\n */\n error InsufficientTokensReturned(uint256 amount, uint256 actualAmount);\n}\n"},"lib/cash/src/interfaces/IConsol/IConsolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IConsolEvents\n * @author SocksNFlops\n * @notice Interface for the Consol contract events.\n */\ninterface IConsolEvents {\n /**\n * @notice Emitted when a flash swap is made.\n * @param inputToken The input token\n * @param outputToken The output token\n * @param amount The amount of tokens swapped\n * @param actualAmount The amount of tokens returned\n */\n event FlashSwap(address indexed inputToken, address indexed outputToken, uint256 amount, uint256 actualAmount);\n}\n"},"lib/cash/src/interfaces/ISubConsol/ISubConsolEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ISubConsolEvents\n * @author Socks&Flops\n * @notice Interface for the SubConsolEvents.\n */\ninterface ISubConsolEvents {\n /**\n * @notice Emitted when collateral is deposited into the SubConsol contract\n * @param account The address of the account that deposited\n * @param collateralAmount The amount of collateral deposited\n * @param mintAmount The amount of subconsol minted\n */\n event Deposit(address indexed account, uint256 collateralAmount, uint256 mintAmount);\n\n /**\n * @notice Emitted when collateral is withdrawn from the SubConsol contract\n * @param account The address of the account that withdrew\n * @param collateralAmount The amount of collateral withdrawn\n * @param burnAmount The amount of subconsol burned\n */\n event Withdraw(address indexed account, uint256 collateralAmount, uint256 burnAmount);\n\n /**\n * @notice Emitted when the yield strategy is set\n * @param yieldStrategy The address of the yield strategy\n */\n event YieldStrategySet(address indexed yieldStrategy);\n\n /**\n * @notice Emitted when the yield amount is updated\n * @param yieldAmount The amount of yield in the yield strategy\n */\n event YieldAmountUpdated(uint256 yieldAmount);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDXEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IUSDXEvents {\n /**\n * @notice Emitted when a new token is added to the MultiTokenVault\n * @param token The address of the token that was added\n * @param numerator The numerator for the token\n * @param denominator The denominator for the token\n */\n event TokenScalarsAdded(address indexed token, uint256 numerator, uint256 denominator);\n}\n"},"lib/cash/src/interfaces/IUSDX/IUSDXErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IUSDXErrors {\n /**\n * @notice Emitted when the token scalars are invalid\n * @param token The address of the token that has invalid scalars\n * @param numerator The numerator for the token\n * @param denominator The denominator for the token\n */\n error InvalidTokenScalars(address token, uint256 numerator, uint256 denominator);\n}\n"},"lib/cash/src/types/OriginationPoolConfig.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {OPoolConfigIdLibrary} from \"./OPoolConfigId.sol\";\n\nusing OPoolConfigIdLibrary for OriginationPoolConfig global;\n\n/**\n * @notice The configuration for a recurring origination pool deployment\n * @param namePrefix The prefix for the name of the pool\n * @param symbolPrefix The prefix for the symbol of the pool\n * @param consol The consol token for the pool\n * @param usdx The USDX token for the pool\n * @param depositPhaseDuration The duration of the deposit phase\n * @param deployPhaseDuration The duration of the deploy phase\n * @param defaultPoolLimit The starting pool limit (for first deployment)\n * @param poolLimitGrowthRateBps The rate at which the pool limit grows each epoch if the previous pool limit was reached\n * @param poolMultiplierBps The pool multiplier in basis points\n */\nstruct OriginationPoolConfig {\n string namePrefix;\n string symbolPrefix;\n address consol;\n address usdx;\n uint32 depositPhaseDuration;\n uint32 deployPhaseDuration;\n uint256 defaultPoolLimit;\n uint16 poolLimitGrowthRateBps;\n uint16 poolMultiplierBps;\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolSchedulerEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\n\ninterface IOriginationPoolSchedulerEvents {\n /**\n * @notice Emitted when a new origination pool config is added\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n */\n event OriginationPoolConfigAdded(OPoolConfigId oPoolConfigId, OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice Emitted when an origination pool config is removed\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n */\n event OriginationPoolConfigRemoved(OPoolConfigId oPoolConfigId, OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice Emitted when an origination pool is deployed\n * @param oPoolConfigId The ID of the origination pool config\n * @param oPoolConfig The origination pool config\n * @param deploymentAddress The address of the deployment\n * @param deploymentEpoch The epoch of the deployment\n * @param deploymentTimestamp The timestamp of the deployment\n */\n event OriginationPoolDeployed(\n OPoolConfigId indexed oPoolConfigId,\n OriginationPoolConfig indexed oPoolConfig,\n address indexed deploymentAddress,\n uint256 deploymentEpoch,\n uint256 deploymentTimestamp\n );\n\n /**\n * @notice Emitted when an origination pool is updated\n * @param originationPool The address of the origination pool\n * @param registered Whether the origination pool is registered\n */\n event OriginationPoolRegistryUpdated(address indexed originationPool, bool registered);\n}\n"},"lib/cash/src/interfaces/IOriginationPoolScheduler/IOriginationPoolSchedulerErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {OriginationPoolConfig} from \"../../types/OriginationPoolConfig.sol\";\nimport {OPoolConfigId} from \"../../types/OPoolConfigId.sol\";\n\ninterface IOriginationPoolSchedulerErrors {\n /**\n * @notice The new admin does not have the DEFAULT_ADMIN_ROLE\n * @param newOpoolAdmin The address of the new admin\n */\n error InvalidOpoolAdmin(address newOpoolAdmin);\n\n /**\n * @notice The origination pool config already exists\n * @param oPoolConfig The origination pool config that already exists\n */\n error OriginationPoolConfigAlreadyExists(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool config does not exist\n * @param oPoolConfig The origination pool config that does not exist\n */\n error OriginationPoolConfigDoesNotExist(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool config is invalid\n * @param oPoolConfig The origination pool config that is invalid\n */\n error InvalidOriginationPoolConfig(OriginationPoolConfig oPoolConfig);\n\n /**\n * @notice The origination pool has already been deployed this epoch\n * @param oPoolConfig The origination pool config\n * @param deploymentAddress The address of the deployment\n * @param deploymentEpoch The epoch of the deployment\n * @param deploymentTimestamp The timestamp of the deployment\n */\n error OriginationPoolAlreadyDeployedThisEpoch(\n OriginationPoolConfig oPoolConfig, address deploymentAddress, uint256 deploymentEpoch, uint256 deploymentTimestamp\n );\n\n /**\n * @notice The origination pool config id does not exist\n * @param oPoolConfigId The origination pool config id that does not exist\n */\n error OriginationPoolConfigIdDoesNotExist(OPoolConfigId oPoolConfigId);\n}\n"},"src/interfaces/IRouter/IRouterErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IRouterErrors\n * @author @SocksNFlops\n * @notice Errors for the Router contract\n */\ninterface IRouterErrors {\n /**\n * @notice Thrown when the collected amount exceeds the maximum permitted collected amount\n * @param token The token that was collected\n * @param collectedAmount The amount that was collected\n * @param maxColllected The maximum amount that can be collected\n */\n error CollectedAmountExceedsMaximum(address token, uint256 collectedAmount, uint256 maxColllected);\n\n /**\n * @notice Thrown when the vault's whitelist is enforced and the sender is not whitelisted\n * @param vault The address of the vault\n * @param sender The address of the sender\n */\n error VaultWhitelistEnforced(address vault, address sender);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC-721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n * a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC-721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n * {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n * a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 tokenId) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the address zero.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},"lib/cash/src/interfaces/IMortgageNFT/IMortgageNFTEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IMortgageNFTEvents\n * @author Socks&Flops\n */\ninterface IMortgageNFTEvents {\n /**\n * @notice Emitted when a mortgageId is updated\n * @param tokenId The numerical index of the mortgageNFT\n * @param mortgageId The new id of the mortgage\n */\n event MortgageIdUpdate(uint256 tokenId, string mortgageId);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n * using Panic for uint256;\n *\n * // Use any of the declared internal constants\n * function foo() { Panic.GENERIC.panic(); }\n *\n * // Alternatively\n * function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n /// @dev generic / unspecified error\n uint256 internal constant GENERIC = 0x00;\n /// @dev used by the assert() builtin\n uint256 internal constant ASSERT = 0x01;\n /// @dev arithmetic underflow or overflow\n uint256 internal constant UNDER_OVERFLOW = 0x11;\n /// @dev division or modulo by zero\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\n /// @dev enum conversion error\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n /// @dev invalid encoding in storage\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n /// @dev empty array pop\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n /// @dev array out of bounds access\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n /// @dev resource error (too large allocation or too large array)\n uint256 internal constant RESOURCE_ERROR = 0x41;\n /// @dev calling invalid internal function\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n /// @dev Reverts with a panic code. Recommended to use with\n /// the internal constants with predefined codes.\n function panic(uint256 code) internal pure {\n assembly (\"memory-safe\") {\n mstore(0x00, 0x4e487b71)\n mstore(0x20, code)\n revert(0x1c, 0x24)\n }\n }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n /**\n * @dev Value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n /**\n * @dev An int value doesn't fit in an uint of `bits` size.\n */\n error SafeCastOverflowedIntToUint(int256 value);\n\n /**\n * @dev Value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n /**\n * @dev An uint value doesn't fit in an int of `bits` size.\n */\n error SafeCastOverflowedUintToInt(uint256 value);\n\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n if (value > type(uint248).max) {\n revert SafeCastOverflowedUintDowncast(248, value);\n }\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n if (value > type(uint240).max) {\n revert SafeCastOverflowedUintDowncast(240, value);\n }\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n if (value > type(uint232).max) {\n revert SafeCastOverflowedUintDowncast(232, value);\n }\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n if (value > type(uint224).max) {\n revert SafeCastOverflowedUintDowncast(224, value);\n }\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n if (value > type(uint216).max) {\n revert SafeCastOverflowedUintDowncast(216, value);\n }\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n if (value > type(uint208).max) {\n revert SafeCastOverflowedUintDowncast(208, value);\n }\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n if (value > type(uint200).max) {\n revert SafeCastOverflowedUintDowncast(200, value);\n }\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n if (value > type(uint192).max) {\n revert SafeCastOverflowedUintDowncast(192, value);\n }\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n if (value > type(uint184).max) {\n revert SafeCastOverflowedUintDowncast(184, value);\n }\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n if (value > type(uint176).max) {\n revert SafeCastOverflowedUintDowncast(176, value);\n }\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n if (value > type(uint168).max) {\n revert SafeCastOverflowedUintDowncast(168, value);\n }\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n if (value > type(uint160).max) {\n revert SafeCastOverflowedUintDowncast(160, value);\n }\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n if (value > type(uint152).max) {\n revert SafeCastOverflowedUintDowncast(152, value);\n }\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n if (value > type(uint144).max) {\n revert SafeCastOverflowedUintDowncast(144, value);\n }\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n if (value > type(uint136).max) {\n revert SafeCastOverflowedUintDowncast(136, value);\n }\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) {\n revert SafeCastOverflowedUintDowncast(128, value);\n }\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n if (value > type(uint120).max) {\n revert SafeCastOverflowedUintDowncast(120, value);\n }\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n if (value > type(uint112).max) {\n revert SafeCastOverflowedUintDowncast(112, value);\n }\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n if (value > type(uint104).max) {\n revert SafeCastOverflowedUintDowncast(104, value);\n }\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n if (value > type(uint96).max) {\n revert SafeCastOverflowedUintDowncast(96, value);\n }\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n if (value > type(uint88).max) {\n revert SafeCastOverflowedUintDowncast(88, value);\n }\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n if (value > type(uint80).max) {\n revert SafeCastOverflowedUintDowncast(80, value);\n }\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n if (value > type(uint72).max) {\n revert SafeCastOverflowedUintDowncast(72, value);\n }\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n if (value > type(uint64).max) {\n revert SafeCastOverflowedUintDowncast(64, value);\n }\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n if (value > type(uint56).max) {\n revert SafeCastOverflowedUintDowncast(56, value);\n }\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n if (value > type(uint48).max) {\n revert SafeCastOverflowedUintDowncast(48, value);\n }\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n if (value > type(uint40).max) {\n revert SafeCastOverflowedUintDowncast(40, value);\n }\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n if (value > type(uint32).max) {\n revert SafeCastOverflowedUintDowncast(32, value);\n }\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n if (value > type(uint24).max) {\n revert SafeCastOverflowedUintDowncast(24, value);\n }\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n if (value > type(uint16).max) {\n revert SafeCastOverflowedUintDowncast(16, value);\n }\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n if (value > type(uint8).max) {\n revert SafeCastOverflowedUintDowncast(8, value);\n }\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n if (value < 0) {\n revert SafeCastOverflowedIntToUint(value);\n }\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(248, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(240, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(232, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(224, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(216, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(208, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(200, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(192, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(184, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(176, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(168, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(160, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(152, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(144, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(136, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(128, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(120, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(112, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(104, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(96, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(88, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(80, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(72, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(64, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(56, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(48, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(40, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(32, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(24, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(16, value);\n }\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n if (downcasted != value) {\n revert SafeCastOverflowedIntDowncast(8, value);\n }\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n if (value > uint256(type(int256).max)) {\n revert SafeCastOverflowedUintToInt(value);\n }\n return int256(value);\n }\n\n /**\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n */\n function toUint(bool b) internal pure returns (uint256 u) {\n assembly (\"memory-safe\") {\n u := iszero(iszero(b))\n }\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/PythStructs.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\ncontract PythStructs {\n // A price with a degree of uncertainty, represented as a price +- a confidence interval.\n //\n // The confidence interval roughly corresponds to the standard error of a normal distribution.\n // Both the price and confidence are stored in a fixed-point numeric representation,\n // `x * (10^expo)`, where `expo` is the exponent.\n //\n // Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how\n // to how this price safely.\n struct Price {\n // Price\n int64 price;\n // Confidence interval around the price\n uint64 conf;\n // Price exponent\n int32 expo;\n // Unix timestamp describing when the price was published\n uint publishTime;\n }\n\n // PriceFeed represents a current aggregate price from pyth publisher feeds.\n struct PriceFeed {\n // The price ID.\n bytes32 id;\n // Latest available price\n Price price;\n // Latest available exponentially-weighted moving average price\n Price emaPrice;\n }\n\n struct TwapPriceFeed {\n // The price ID.\n bytes32 id;\n // Start time of the TWAP\n uint64 startTime;\n // End time of the TWAP\n uint64 endTime;\n // TWAP price\n Price twap;\n // Down slot ratio represents the ratio of price feed updates that were missed or unavailable\n // during the TWAP period, expressed as a fixed-point number between 0 and 1e6 (100%).\n // For example:\n // - 0 means all price updates were available\n // - 500_000 means 50% of updates were missed\n // - 1_000_000 means all updates were missed\n // This can be used to assess the quality/reliability of the TWAP calculation.\n // Applications should define a maximum acceptable ratio (e.g. 100000 for 10%)\n // and revert if downSlotsRatio exceeds it.\n uint32 downSlotsRatio;\n }\n\n // Information used to calculate time-weighted average prices (TWAP)\n struct TwapPriceInfo {\n // slot 1\n int128 cumulativePrice;\n uint128 cumulativeConf;\n // slot 2\n uint64 numDownSlots;\n uint64 publishSlot;\n uint64 publishTime;\n uint64 prevPublishTime;\n // slot 3\n int32 expo;\n }\n}\n"},"lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/IPythEvents.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/// @title IPythEvents contains the events that Pyth contract emits.\n/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.\ninterface IPythEvents {\n /// @dev Emitted when the price feed with `id` has received a fresh update.\n /// @param id The Pyth Price Feed ID.\n /// @param publishTime Publish time of the given price update.\n /// @param price Price of the given price update.\n /// @param conf Confidence interval of the given price update.\n event PriceFeedUpdate(\n bytes32 indexed id,\n uint64 publishTime,\n int64 price,\n uint64 conf\n );\n\n /// @dev Emitted when the TWAP price feed with `id` has received a fresh update.\n /// @param id The Pyth Price Feed ID.\n /// @param startTime Start time of the TWAP.\n /// @param endTime End time of the TWAP.\n /// @param twapPrice Price of the TWAP.\n /// @param twapConf Confidence interval of the TWAP.\n /// @param downSlotsRatio Down slot ratio of the TWAP.\n event TwapPriceFeedUpdate(\n bytes32 indexed id,\n uint64 startTime,\n uint64 endTime,\n int64 twapPrice,\n uint64 twapConf,\n uint32 downSlotsRatio\n );\n}\n"},"lib/cash/src/libraries/Constants.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n/**\n * @title Constants\n * @author SocksNFlops\n * @notice Constants for the Cash Protocol\n */\nlibrary Constants {\n /**\n * @notice The number of basis points in a whole. Used in percentage and rate calculations.\n * @return BPS The number of basis points in a whole\n */\n uint256 public constant BPS = 10_000;\n /**\n * @notice The number of seconds per period (one month per period)\n * @return PERIOD_DURATION The number of seconds per period\n */\n uint256 public constant PERIOD_DURATION = 30 days;\n /**\n * @notice The number of periods for every year\n * @return PERIODS_PER_YEAR The number of periods for every year\n */\n uint256 public constant PERIODS_PER_YEAR = 12;\n /**\n * @notice The number of seconds after the due date that a payment is still considered on time\n * @return LATE_PAYMENT_WINDOW The number of seconds after the due date that a payment is still considered on time\n */\n uint256 public constant LATE_PAYMENT_WINDOW = 3 days;\n /**\n * @notice The maximum amount of missed payments before a mortgage can be foreclosed\n * @return MAXIMUM_MISSED_PAYMENTS The maximum amount of missed payments before a mortgage can be foreclosed\n */\n uint8 public constant MAXIMUM_MISSED_PAYMENTS = 2;\n /**\n * @notice The minimum amount borrowed for a mortgage\n * @return MINIMUM_AMOUNT_BORROWED The minimum amount borrowed for a mortgage\n */\n uint256 public constant MINIMUM_AMOUNT_BORROWED = 1e18;\n /**\n * @notice The duration of a single epoch for deploying origination pools. A new batch of origination pools is deployable every epoch.\n * @return EPOCH_DURATION The duration of a single epoch for deploying origination pools\n */\n uint256 public constant EPOCH_DURATION = 1 days;\n /**\n * @notice The offset for the epoch start time. This guarantees that every epoch starts at Friday 2am GMT every week\n * @return EPOCH_OFFSET The offset for the epoch start time\n */\n uint256 public constant EPOCH_OFFSET = 12 hours;\n /**\n * @notice The minimum permitted USDX deposit for an origination pool\n * @return MINIMUM_ORIGINATION_DEPOSIT The minimum permitted USDX deposit for an origination pool\n */\n uint256 public constant MINIMUM_ORIGINATION_DEPOSIT = 1e18;\n\n /**\n * @notice The maximum possible number of periods for a mortgage\n * @return MAX_TOTAL_PERIODS The maximum number of periods for a mortgage\n */\n uint8 public constant MAX_TOTAL_PERIODS = 244;\n}\n"},"lib/cash/src/types/enums/MortgageStatus.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @notice The status of a mortgage position\n */\nenum MortgageStatus {\n /// @notice Mortgage is active and operational, with payments being made according to the payment plan\n ACTIVE,\n /// @notice Mortgage has been foreclosed due to excessive missed payments\n FORECLOSED,\n /// @notice Mortgage has been fully paid off and redeemed by the borrower, with collateral returned\n REDEEMED\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVaultEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILiquidityVaultEvents\n * @author @SocksNFlops\n * @notice Interface for events emitted by LiquidityVaults.\n */\ninterface ILiquidityVaultEvents {\n /**\n * @notice Emitted when a user deposits assets into the vault.\n * @param user The address of the user who deposited the assets.\n * @param depositableAsset The address of the depositable asset.\n * @param amountDeposited The amount of depositable asset sent.\n * @param sharesMinted The amount of shares minted.\n */\n event Deposited(\n address indexed user, address indexed depositableAsset, uint256 amountDeposited, uint256 sharesMinted\n );\n\n /**\n * @notice Emitted when a user redeems assets from the vault.\n * @param user The address of the user who redeemed the assets.\n * @param redeemableAssets The addresses of the redeemable assets.\n * @param amountsRedeemed The amounts of redeemable assets received.\n * @param sharesBurned The amount of shares burned.\n */\n event Redeemed(\n address indexed user, address[] indexed redeemableAssets, uint256[] amountsRedeemed, uint256 sharesBurned\n );\n\n /**\n * @notice Emitted when the whitelist is enforced.\n * @param enforced Whether the whitelist is enforced.\n */\n event WhitelistEnforced(bool enforced);\n\n /**\n * @notice Emitted when the redeemable assets are updated.\n * @param redeemableAssets The addresses of the redeemable assets.\n */\n event RedeemableAssetsUpdated(address[] indexed redeemableAssets);\n\n /**\n * @notice Emitted when the depositable assets are updated.\n * @param depositableAssets The addresses of the depositable assets.\n */\n event DepositableAssetsUpdated(address[] indexed depositableAssets);\n}\n"},"src/interfaces/ILiquidityVault/ILiquidityVaultErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title ILiquidityVaultErrors\n * @author @SocksNFlops\n * @notice Interface for errors emitted by LiquidityVaults.\n */\ninterface ILiquidityVaultErrors {\n /**\n * @notice Thrown when the depositable asset is not in the depositable assets list\n * @param asset The address of the asset that is not depositable\n */\n error AssetNotDepositable(address asset);\n}\n"},"lib/cash/src/interfaces/IPausable/IPausableErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n/**\n * @title IPausableErrors\n * @author @SocksNFlops\n * @notice Errors for the pausable contract\n */\ninterface IPausableErrors {\n /**\n * @notice Error for paused pool\n */\n error Paused();\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVaultEvents.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IMultiTokenVaultEvents {\n /**\n * @notice Emitted when a new token is added to the MultiTokenVault\n * @param token The address of the token that was added\n */\n event TokenAdded(address indexed token);\n\n /**\n * @notice Emitted when a token is removed from the MultiTokenVault\n * @param token The address of the token that was removed\n */\n event TokenRemoved(address indexed token);\n\n /**\n * @notice Emitted when an account deposits a token\n * @param account The address of the account that deposited\n * @param token The address of the token that was deposited\n * @param amount The amount of the token that was deposited\n * @param mintAmount The amount that was minted from the deposit\n */\n event Deposit(address indexed account, address indexed token, uint256 amount, uint256 mintAmount);\n\n /**\n * @notice Emitted when an account withdraws a token\n * @param account The address of the account that withdrew\n * @param token The address of the token that was withdrawn\n * @param amount The amount of the token that was withdrawn\n * @param burnAmount The amount that was burned from the withdraw\n */\n event Withdraw(address indexed account, address indexed token, uint256 amount, uint256 burnAmount);\n\n /**\n * @notice Emitted when the maximum cap for a token is set\n * @param token The address of the token that was set\n * @param maximumCap The new maximum cap for the token denominated in the UOA.\n */\n event MaximumCapSet(address indexed token, uint256 maximumCap);\n}\n"},"lib/cash/src/interfaces/IMultiTokenVault/IMultiTokenVaultErrors.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\ninterface IMultiTokenVaultErrors {\n /**\n * @notice Thrown when a token is the zero address\n */\n error TokenIsZeroAddress();\n\n /**\n * @notice Thrown when a token is already supported by the MultiTokenVault\n * @param token The address of the token that is already supported\n */\n error TokenAlreadySupported(address token);\n\n /**\n * @notice Thrown when a token is not supported by the MultiTokenVault\n * @param token The address of the token that is not supported\n */\n error TokenNotSupported(address token);\n\n /**\n * @notice Thrown when a deposit/withdraw is too small that no tokens will be minted/burned\n * @param amount The amount of tokens being deposited/withdrawn\n */\n error AmountTooSmall(uint256 amount);\n\n /**\n * @notice Thrown when a token's maximum cap is exceeded\n * @param token The address of the token that exceeded its cap\n * @param amount The total amount of tokens deposited\n * @param maximumCap The maximum allowed amount for this token\n */\n error MaxmimumCapExceeded(address token, uint256 amount, uint256 maximumCap);\n}\n"},"lib/cash/src/interfaces/IRebasingERC20/IRebasingERC20.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IRebasingERC20Events} from \"./IRebasingERC20Events.sol\";\n\ninterface IRebasingERC20 is IERC20, IRebasingERC20Events {\n /**\n * @notice The total amount of the shares token\n * @return The total amount of the shares token\n */\n function totalShares() external view returns (uint256);\n\n /**\n * @notice Converts the amount of underlying token to the corresponding amount of shares\n * @param assets The amount of underlying token\n * @return The corresponding amount of shares\n */\n function convertToShares(uint256 assets) external view returns (uint256);\n\n /**\n * @notice Converts the amount of shares to the corresponding amount of underlying token\n * @param shares The amount of shares\n * @return The corresponding amount of underlying token\n */\n function convertToAssets(uint256 shares) external view returns (uint256);\n\n /**\n * @notice The amount of shares that the account has\n * @param account The address of the account\n * @return The amount of shares that the account has\n */\n function sharesOf(address account) external view returns (uint256);\n\n /**\n * @notice The decimals offset. The number of decimals to offset the shares by. Used to protect against inflation attacks.\n * @return The decimals offset\n */\n function decimalsOffset() external view returns (uint8);\n}\n"},"lib/cash/src/interfaces/IRebasingERC20/IRebasingERC20Events.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IRebasingERC20Events is IERC20 {\n /**\n * @notice Emitted when shares/balances are transferred\n * @param from The address of the sender\n * @param to The address of the recipient\n * @param amount The amount of shares transferred\n * @param shares The amount of shares transferred\n */\n event TransferShares(address indexed from, address indexed to, uint256 amount, uint256 shares);\n}\n"}},"settings":{"remappings":["forge-std/=lib/forge-std/src/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@core/=lib/cash/src/","@hyper-evm-lib/=lib/hyper-evm-lib/","@mock-contracts/=lib/cash/lib/mock-contracts/src/","@pythnetwork/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/solidity/","cash/=lib/cash/","createx/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/createx/src/","ds-test/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/","hyper-evm-lib/=lib/hyper-evm-lib/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin-foundry-upgrades/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades/src/","pyth-crosschain/=lib/cash/lib/pyth-crosschain/","solady/=lib/cash/lib/pyth-crosschain/lazer/contracts/evm/lib/createx/lib/solady/","solidity-stringutils/=lib/cash/lib/pyth-crosschain/target_chains/ethereum/sdk/stylus/pyth-mock-solidity/lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/"],"optimizer":{"enabled":true,"runs":10000},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.bytecode.sourceMap","evm.bytecode.linkReferences","evm.deployedBytecode.object","evm.deployedBytecode.sourceMap","evm.deployedBytecode.linkReferences","evm.deployedBytecode.immutableReferences","evm.methodIdentifiers","metadata"]}},"evmVersion":"prague","viaIR":false,"libraries":{}}}