Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x0055c00ba4Dec5ed545A5419C4d430daDa8cb1CE
Balance 0 ETH
Nonce 1
Code Size 18236 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

18236 bytes
0x608060405234801561001057600080fd5b50600436106103425760003560e01c80637d41c86e116101b8578063c45a015511610104578063d7c0ca48116100a2578063e345f4b61161007c578063e345f4b6146106f3578063f4070e2d14610706578063fae8ed3d14610729578063fc72ed5b1461073c57600080fd5b8063d7c0ca48146106ba578063d905777e146106cd578063e15e990a146106e057600080fd5b8063cbe52ae3116100de578063cbe52ae31461066d578063ce96cb7714610680578063d4dd043814610694578063d784d426146106a757600080fd5b8063c45a01551461064a578063c63d75b614610652578063caf901dd1461066557600080fd5b8063a58c3eff11610171578063ba321f9f1161014b578063ba321f9f14610614578063bbc6f1dc1461061c578063c31245251461062f578063c3fbb6fd1461063757600080fd5b8063a58c3eff146105db578063ab42685c146105ee578063acec338a1461060157600080fd5b80637d41c86e1461056857806382fe535a1461057b5780638772a23a1461058e57806387c2f4ae146105a25780638b1c4990146105b55780639e5df6c2146105c857600080fd5b8063402d267d116102925780635dd28449116102305780636ed93dd01161020a5780636ed93dd01461052157806376687d3d1461052b5780637b99adb1146105345780637bd243de1461054757600080fd5b80635dd28449146104e857806360af6ad3146104f157806367e2ba231461051957600080fd5b80634148c5e51161026c5780634148c5e514610489578063494666b61461049c5780635c60da1b146104af5780635cf2ed57146104b757600080fd5b8063402d267d146104505780634046af2b1461046357806340504ba01461047657600080fd5b80631b8f1830116102ff5780633291f012116102d95780633291f0121461040f57806338d52e0f146104175780633b35e8041461042a5780633b99bcee1461043d57600080fd5b80631b8f1830146103d657806326af24b7146103e95780632ebada04146103fc57600080fd5b806301e1d1141461034757806302db6cd31461036257806302fb0c5e1461038d5780630c340a24146103b157806316f0115b146103b957806319e9cd7b146103cc575b600080fd5b61034f61074f565b6040519081526020015b60405180910390f35b600254610375906001600160a01b031681565b6040516001600160a01b039091168152602001610359565b6006546103a190600160a01b900460ff1681565b6040519015158152602001610359565b610375610891565b600454610375906001600160a01b031681565b6103d4610910565b005b61034f6103e436600461429a565b610a40565b6103d46103f736600461429a565b610b42565b6103d461040a366004614079565b610d48565b6103d4610e97565b600354610375906001600160a01b031681565b610375610438366004614079565b610ee5565b6103d461044b366004614301565b611117565b61034f61045e366004614079565b6113e0565b600154610375906001600160a01b031681565b6103d46104843660046140b3565b611406565b6103d46104973660046140ec565b61164f565b6103d46104aa36600461416f565b611752565b610375611d28565b6104cb6104c536600461416f565b91309150565b604080519283526001600160a01b03909116602083015201610359565b61034f60085481565b6105046104ff3660046142bf565b611d32565b60408051928352602083019190915201610359565b61034f611f33565b61034f620f424081565b61034f60075481565b6103d4610542366004614268565b612003565b61055a61055536600461420c565b61204f565b60405161035992919061454e565b6103d46105763660046142bf565b612603565b600654610375906001600160a01b031681565b6006546103a190600160a81b900460ff1681565b6103d46105b0366004614268565b61283a565b6103d46105c3366004614268565b6128c1565b6103d46105d6366004614079565b61295a565b61034f6105e9366004614268565b612a74565b600554610375906001600160a01b031681565b6103d461060f36600461419b565b612af3565b600b5461034f565b61034f61062a36600461416f565b612ba4565b610375612c31565b6103d461064536600461411a565b612c73565b610375612d70565b61034f610660366004614079565b612d7a565b6103a1612e21565b61034f61067b36600461416f565b612e3f565b61034f61068e366004614079565b50600090565b6103d46106a236600461437a565b612e79565b6103d46106b5366004614079565b612ee4565b6103d46106c8366004614079565b612f75565b61034f6106db366004614079565b612fd7565b600c54610375906001600160a01b031681565b6105046107013660046142bf565b6130eb565b6103a1610714366004614079565b60096020526000908152604090205460ff1681565b610375610737366004614268565b613159565b6103d461074a366004614079565b613183565b600354600480546040516370a0823160e01b81526001600160a01b039182169281019290925260009216906370a082319060240160206040518083038186803b15801561079b57600080fd5b505afa1580156107af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d39190614281565b600b5490915060005b8181101561088c57600b81815481106107f7576107f76146ca565b6000918252602091829020015460408051637b6f05e960e11b815290516001600160a01b039092169263f6de0bd292600480840193829003018186803b15801561084057600080fd5b505afa158015610854573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108789190614281565b61088290846145f9565b92506001016107dc565b505090565b600061089b612c31565b6001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b1580156108d357600080fd5b505afa1580156108e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090b9190614096565b905090565b610918613406565b6002546001600160a01b0316331461096f5760405162461bcd60e51b815260206004820152601560248201527414134e9054110e9393d517d4115391125391d7d411605a1b60448201526064015b60405180910390fd5b610977612c31565b600154604051632f97305960e01b81526001600160a01b039182166004820152336024820152911690632f97305990604401600060405180830381600087803b1580156109c357600080fd5b505af11580156109d7573d6000803e3d6000fd5b50506002546001546040516001600160a01b039283169450911691507fff9949a1e16bc5d8386effb58bc7d620cff72179b0ad2bf1fcc1f58b09522a6d90600090a360028054600180546001600160a01b03199081166001600160a01b03841617909155169055565b6000610a4a613406565b600054600114610a6c5760405162461bcd60e51b81526004016109669061458b565b6002600055610a796134ce565b6006546040516301b8f18360e41b8152600481018590526001600160a01b0384811660248301819052927f4b171f7fc0550bd6b41ba56e9b2b88100206431510ba9427518f3485198db36d92911690631b8f183090604401602060405180830381600087803b158015610aeb57600080fd5b505af1158015610aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b239190614281565b60405181815290935060200160405180910390a2600160005592915050565b610b4a613406565b610b52613516565b6001600160a01b03811615610b675780610b69565b335b6005546040516339bc590360e11b8152600481018590526001600160a01b038084166024830152929350911690637378b20690604401600060405180830381600087803b158015610bb957600080fd5b505af1158015610bcd573d6000803e3d6000fd5b50505050610bd9612c31565b6040516323396b5360e11b81523060048201526001600160a01b039190911690634672d6a69060240160206040518083038186803b158015610c1a57600080fd5b505afa158015610c2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c529190614281565b6003546005546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b158015610c9957600080fd5b505afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd19190614281565b1015610d115760405162461bcd60e51b815260206004820152600f60248201526e28269d2ba19d2122a627abafa6a4a760891b6044820152606401610966565b6040518281527f197c9d0c5e4013c0533a69753717932d354db643259ac08a83f71c835729ad769060200160405180910390a15050565b610d50613406565b610d5861355c565b610d60612c31565b60405163305c9e0560e01b81527f504f4f4c5f5045524d495353494f4e5f4d414e4147455200000000000000000060048201526001600160a01b038381166024830152919091169063305c9e059060440160206040518083038186803b158015610dc957600080fd5b505afa158015610ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0191906141b8565b610e4d5760405162461bcd60e51b815260206004820152601860248201527f504d3a5350504d3a494e56414c49445f494e5354414e434500000000000000006044820152606401610966565b600c80546001600160a01b0319166001600160a01b0383169081179091556040517f269618c20ead34aabc3811b327fd482daf7368845178bdf8f1a7022dfff3a43f90600090a250565b610e9f613406565b610ea76135b8565b6006805460ff60a81b1916600160a81b1790556040517f88f39e22620812dfcec36b8475764a7450bda154d389facf6d2708fbea7d640790600090a1565b6000610eef613406565b610ef761355c565b610eff612c31565b6001600160a01b031663305c9e05836040518263ffffffff1660e01b8152600401610f2a91906145ae565b60206040518083038186803b158015610f4257600080fd5b505afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a91906141b8565b610fbf5760405162461bcd60e51b8152602060048201526016602482015275504d3a414c4d3a494e56414c49445f464143544f525960501b6044820152606401610966565b604080513060208201526001600160a01b0384169163517b657f910160408051808303601f19018152828252600b543060208501529183019190915290606001604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401611032929190614569565b602060405180830381600087803b15801561104c57600080fd5b505af1158015611060573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110849190614096565b6001600160a01b038116600081815260096020526040808220805460ff19166001908117909155600b8054918201815583527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b031916841790555192935090917f870b352f9e61b22ce039fe5f1976fa831c1e76b68d0f7b86965abb7fad3d81129190a2919050565b61111f613406565b6000611129612c31565b6001549091506001600160a01b03163314156112765760405163fd4c5b3760e01b81526001600160a01b0382169063fd4c5b379061117290339030906000903690600401614471565b60206040518083038186803b15801561118a57600080fd5b505afa15801561119e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c291906141b8565b61120e5760405162461bcd60e51b815260206004820152601760248201527f504d3a553a494e56414c49445f53434845445f43414c4c0000000000000000006044820152606401610966565b604051635ad5b6f760e11b81526001600160a01b0382169063b5ab6dee9061123f9033906000903690600401614516565b600060405180830381600087803b15801561125957600080fd5b505af115801561126d573d6000803e3d6000fd5b50505050611336565b806001600160a01b031663be7c13f76040518163ffffffff1660e01b815260040160206040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190614096565b6001600160a01b0316336001600160a01b0316146113365760405162461bcd60e51b815260206004820152600c60248201526b0a09a74aa749c9ebe82aaa8960a31b6044820152606401610966565b7faaaa7ee6b0c2f4ee1fa7312c7d5b3623a434da5a1a9ce3cb6e629caa23454ab6848484604051611369939291906145df565b60405180910390a161137961360a565b6001600160a01b031663fe69f7088585856040518463ffffffff1660e01b81526004016113a8939291906145df565b600060405180830381600087803b1580156113c257600080fd5b505af11580156113d6573d6000803e3d6000fd5b5050505050505050565b6000611400826113ee61074f565b68140e99195c1bdcda5d60ba1b613639565b92915050565b61140e613406565b6000546001146114305760405162461bcd60e51b81526004016109669061458b565b600260005561143d6136f8565b611445612c31565b60405163305c9e0560e01b8152714c495155494441544f525f464143544f525960701b60048201526001600160a01b038381166024830152919091169063305c9e059060440160206040518083038186803b1580156114a357600080fd5b505afa1580156114b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114db91906141b8565b61151b5760405162461bcd60e51b8152602060048201526011602482015270504d3a54443a4e4f545f464143544f525960781b6044820152606401610966565b600080600061152985613801565b604051630202825d60e51b81526001600160a01b038781166004830152868116602483015291909116906340504ba090604401606060405180830381600087803b15801561157657600080fd5b505af115801561158a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ae91906141d5565b925092509250826115f5576040516001600160a01b038616907f371cc890361cf16190aac5797dcbc15218efceb8445aac6f43ff106481d5ca3390600090a2505050611646565b6115ff82826138df565b846001600160a01b03167ff753ba3c7c9e5d6813c50ab20dfd8e33f496ce2bc7e72e08e547e0d2aff151338360405161163a91815260200190565b60405180910390a25050505b50506001600055565b611657613406565b61165f613516565b6001600160a01b038216600081815260096020908152604091829020805460ff191685151590811790915591519182527fac652c7a6beddf064facb796d2f0424ff7b07dd67d2143b843402ff99b48c310910160405180910390a260005b600b5481101561171457826001600160a01b0316600b82815481106116e4576116e46146ca565b6000918252602090912001546001600160a01b0316141561170457505050565b61170d81614699565b90506116bd565b5060405162461bcd60e51b8152602060048201526012602482015271504d3a53494c4d3a494e56414c49445f4c4d60701b6044820152606401610966565b61175a613406565b60005460011461177c5760405162461bcd60e51b81526004016109669061458b565b60026000908155600354600480546040805163c45a015560e01b815290516001600160a01b0394851695949092169392339263c45a0155928083019260209291829003018186803b1580156117d057600080fd5b505afa1580156117e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118089190614096565b90506000611814612c31565b9050846118635760405162461bcd60e51b815260206004820152601760248201527f504d3a52463a494e56414c49445f5052494e434950414c0000000000000000006044820152606401610966565b60405163305c9e0560e01b81526001600160a01b0382169063305c9e059061188f9085906004016145ae565b60206040518083038186803b1580156118a757600080fd5b505afa1580156118bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118df91906141b8565b6119235760405162461bcd60e51b8152602060048201526015602482015274504d3a52463a494e56414c49445f464143544f525960581b6044820152606401610966565b6040516335a2735f60e11b81523360048201526001600160a01b03831690636b44e6be9060240160206040518083038186803b15801561196257600080fd5b505afa158015611976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199a91906141b8565b6119df5760405162461bcd60e51b8152602060048201526016602482015275504d3a52463a494e56414c49445f494e5354414e434560501b6044820152606401610966565b3360009081526009602052604090205460ff16611a2d5760405162461bcd60e51b815260206004820152600c60248201526b504d3a52463a4e4f545f4c4d60a01b6044820152606401610966565b826001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a6657600080fd5b505afa158015611a7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9e9190614281565b611ade5760405162461bcd60e51b8152602060048201526011602482015270504d3a52463a5a45524f5f535550504c5960781b6044820152606401610966565b611ae88185613bd2565b611b345760405162461bcd60e51b815260206004820152601860248201527f504d3a52463a494e53554646494349454e545f434f56455200000000000000006044820152606401610966565b60065460408051632d0e609160e21b815290516000926001600160a01b03169163b4398244916004808301926020929190829003018186803b158015611b7957600080fd5b505afa158015611b8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb19190614281565b90506001600160a01b038716611c095760405162461bcd60e51b815260206004820152601960248201527f504d3a52463a494e56414c49445f44455354494e4154494f4e000000000000006044820152606401610966565b611c1585858989613cd2565b611c575760405162461bcd60e51b815260206004820152601360248201527214134e94918e9514905394d1915497d1905253606a1b6044820152606401610966565b6040516370a0823160e01b81526001600160a01b0385811660048301528291908716906370a082319060240160206040518083038186803b158015611c9b57600080fd5b505afa158015611caf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd39190614281565b1015611d1a5760405162461bcd60e51b8152602060048201526016602482015275504d3a52463a4c4f434b45445f4c495155494449545960501b6044820152606401610966565b505060016000555050505050565b600061090b613d49565b600080611d3d613406565b600054600114611d5f5760405162461bcd60e51b81526004016109669061458b565b6002600055611d6c6134ce565b826001600160a01b0316846001600160a01b03161480611e14575060048054604051636eb1769f60e11b81526001600160a01b038781169382019390935285831660248201526000929091169063dd62ed3e9060440160206040518083038186803b158015611dda57600080fd5b505afa158015611dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e129190614281565b115b611e555760405162461bcd60e51b8152602060048201526012602482015271504d3a50523a4e4f5f414c4c4f57414e434560701b6044820152606401610966565b600654604051634f721ddb60e11b8152600481018790526001600160a01b03868116602483015290911690639ee43bb6906044016040805180830381600087803b158015611ea257600080fd5b505af1158015611eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eda9190614356565b60408051838152602081018390529294509092506001600160a01b038616917f7ad3c51fdfaa55fae7fe0d0cf9efb279d8a3aa02914048280d3d1bdbe560d67a910160405180910390a260016000559094909350915050565b600b54600090815b81811015611feb57600b8181548110611f5657611f566146ca565b60009182526020918290200154604080516367e2ba2360e01b815290516001600160a01b03909216926367e2ba2392600480840193829003018186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd79190614281565b611fe190846145f9565b9250600101611f3b565b50611ffd82611ff861074f565b613d73565b91505090565b61200b613406565b61201361355c565b60078190556040518181527f3ff20538222f568f27ff436c0c49dfd3e48d5b8f86533a3f759dc1c7089775ab906020015b60405180910390a150565b6000606061205b612c31565b604051634c532de160e01b81526001600160e01b03196000351660048201526001600160a01b039190911690634c532de19060240160206040518083038186803b1580156120a857600080fd5b505afa1580156120bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e091906141b8565b1561211257505060408051808201909152600c81526b14134e90d0ce94105554d15160a21b60208201526000906125fa565b600061211e8585613d89565b805190915060006121348360015b602002015190565b90508865140e9b5a5b9d60d21b148061215f5750886f140e9b5a5b9d15da5d1a14195c9b5a5d60821b145b156121e15760048054845160405163b3d7f6b960e01b8152928301526001600160a01b03169063b3d7f6b99060240160206040518083038186803b1580156121a657600080fd5b505afa1580156121ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121de9190614281565b91505b8867503a72656465656d60c01b148061220657508869503a776974686472617760b01b145b156122195761221683600261212c565b90505b8869281d3a3930b739b332b960b11b14806122445750886d503a7472616e7366657246726f6d60901b145b156123ac576040805160028082526060820183526000926020830190803683370190505090508969281d3a3930b739b332b960b11b146122995761228984600061212c565b61229485600161212c565b6122a5565b886122a585600061212c565b826000815181106122b8576122b86146ca565b60200260200101836001815181106122d2576122d26146ca565b6001600160a01b039384166020918202929092010152918116909152600c546040516334dd0fbb60e01b81529116906334dd0fbb9061231990309085908f906004016144b1565b60206040518083038186803b15801561233157600080fd5b505afa158015612345573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236991906141b8565b6123a65760006040518060400160405280601181526020017014134e90d0ce9393d517d0531313d5d151607a1b81525095509550505050506125fa565b50612472565b600c54604051630dace25b60e31b81523060048201526001600160a01b038381166024830152604482018c905290911690636d6712d89060640160206040518083038186803b1580156123fe57600080fd5b505afa158015612412573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243691906141b8565b6124725760006040518060400160405280601181526020017014134e90d0ce9393d517d0531313d5d151607a1b815250945094505050506125fa565b8867503a72656465656d60c01b148061249757508869503a776974686472617760b01b145b806124b25750886d503a72656d6f766553686172657360901b145b806124ce5750886e503a7265717565737452656465656d60881b145b806124ec57508870503a72657175657374576974686472617760781b145b8061250357508869281d3a3930b739b332b960b11b145b8061251e5750886d503a7472616e7366657246726f6d60901b145b1561254157600160405180602001604052806000815250945094505050506125fa565b8868140e99195c1bdcda5d60ba1b148061257057508872140e99195c1bdcda5d15da5d1a14195c9b5a5d606a1b145b8061258357508865140e9b5a5b9d60d21b145b806125a05750886f140e9b5a5b9d15da5d1a14195c9b5a5d60821b145b156125ba576125ae82613dd0565b945094505050506125fa565b60006040518060400160405280601981526020017f504d3a43433a494e56414c49445f46554e4354494f4e5f494400000000000000815250945094505050505b94509492505050565b61260b613406565b60005460011461262d5760405162461bcd60e51b81526004016109669061458b565b600260005561263a6134ce565b6004546006546001600160a01b03918216916126599183911686613e7d565b61269a5760405162461bcd60e51b815260206004820152601260248201527114134e94948e9054141493d59157d190525360721b6044820152606401610966565b826001600160a01b0316826001600160a01b0316141580156126ba575083155b1561278657604051636eb1769f60e11b81526001600160a01b03848116600483015283811660248301526000919083169063dd62ed3e9060440160206040518083038186803b15801561270c57600080fd5b505afa158015612720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127449190614281565b116127865760405162461bcd60e51b8152602060048201526012602482015271504d3a52523a4e4f5f414c4c4f57414e434560701b6044820152606401610966565b6006546040516334c9ac8f60e21b8152600481018690526001600160a01b0385811660248301529091169063d326b23c90604401600060405180830381600087803b1580156127d457600080fd5b505af11580156127e8573d6000803e3d6000fd5b50505050826001600160a01b03167fa1a009bfa4d4ebaf046d2b27cbc657074cb3b637a247a3dbdf767eda4955efc28560405161282791815260200190565b60405180910390a2505060016000555050565b612842613406565b61284a61355c565b620f424081111561288c5760405162461bcd60e51b815260206004820152600c60248201526b28269d29a226a3291d27a7a160a11b6044820152606401610966565b60088190556040518181527f147f457c314a84eed0e31b87c73270d1696cf771a8219a779400326319d6c77690602001612044565b6128c9613406565b6003546005546128e8916001600160a01b039081169133911684613cd2565b61292a5760405162461bcd60e51b815260206004820152601360248201527214134e9110ce9514905394d1915497d1905253606a1b6044820152606401610966565b6040518181527f11cdeb47a11cb4a94ffa87f7d2337ac3695b610f52fb5d80923effc9e0c56e9990602001612044565b612962613406565b6000546001146129845760405162461bcd60e51b81526004016109669061458b565b60026000556129916136f8565b60008061299d83613801565b604051634f2efb6160e11b81526001600160a01b0385811660048301529190911690639e5df6c2906024016040805180830381600087803b1580156129e157600080fd5b505af11580156129f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a199190614356565b91509150612a2782826138df565b826001600160a01b03167ff753ba3c7c9e5d6813c50ab20dfd8e33f496ce2bc7e72e08e547e0d2aff1513383604051612a6291815260200190565b60405180910390a25050600160005550565b6004805460405163a58c3eff60e01b81529182018390526000916001600160a01b039091169063a58c3eff9060240160206040518083038186803b158015612abb57600080fd5b505afa158015612acf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114009190614281565b612afb613406565b612b03612c31565b6001600160a01b0316336001600160a01b031614612b575760405162461bcd60e51b8152602060048201526011602482015270504d3a53413a4e4f545f474c4f42414c5360781b6044820152606401610966565b60068054821515600160a01b0260ff60a01b199091161790556040517f3d5d61d217e7fecd922d11f2a46d0e10cc789ec3f1e4e2c2fa41c4c2f92489bb9061204490831515815260200190565b600654604051632ef1bc7760e21b81526001600160a01b03848116600483015260248201849052600092169063bbc6f1dc906044015b604080518083038186803b158015612bf157600080fd5b505afa158015612c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c299190614356565b949350505050565b6000612c3b61360a565b6001600160a01b0316633a60339a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108d357600080fd5b612c7b613406565b612c8361360a565b6001600160a01b0316336001600160a01b031614612cd65760405162461bcd60e51b815260206004820152601060248201526f504d3a4d3a4e4f545f464143544f525960801b6044820152606401610966565b612ce1838383613ef9565b612d1b5760405162461bcd60e51b815260206004820152600b60248201526a14134e934e91905253115160aa1b6044820152606401610966565b6005546001600160a01b0316612d6b5760405162461bcd60e51b815260206004820152601560248201527414134e934e9111531151d0551157d393d517d4d155605a1b6044820152606401610966565b505050565b600061090b61360a565b600080612d8561074f565b90506000612d9d848365140e9b5a5b9d60d21b613639565b6004805460405163ef8b30f760e01b81529293506001600160a01b03169163ef8b30f791612dd19185910190815260200190565b60206040518083038186803b158015612de957600080fd5b505afa158015612dfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c299190614281565b600061090b612e2e612c31565b6003546001600160a01b0316613bd2565b60065460405163cbe52ae360e01b81526001600160a01b03848116600483015260248201849052600092169063cbe52ae390604401612bda565b612e81613406565b600054600114612ea35760405162461bcd60e51b81526004016109669061458b565b600260005560405162461bcd60e51b815260206004820152601160248201527014134e9495ce9393d517d1539050931151607a1b6044820152606401610966565b612eec613406565b612ef461360a565b6001600160a01b0316336001600160a01b031614612f485760405162461bcd60e51b8152602060048201526011602482015270504d3a53493a4e4f545f464143544f525960781b6044820152606401610966565b6001600160a01b03167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b612f7d613406565b612f856136f8565b600280546001600160a01b0319166001600160a01b03838116918217909255600154604051919216907fc7c986185853ebd33d70a7570381a3a2d859b493edc7286bc07f74882930421f90600090a350565b6006546040516338cdab1160e21b81526001600160a01b038381166004830152600092839291169063e336ac449060240160206040518083038186803b15801561302057600080fd5b505afa158015613034573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130589190614281565b60065460405163a1cfc18760e01b81526001600160a01b03868116600483015292935091169063a1cfc1879060240160206040518083038186803b15801561309f57600080fd5b505afa1580156130b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130d791906141b8565b6130e25760006130e4565b805b9392505050565b6000806130f6613406565b6000546001146131185760405162461bcd60e51b81526004016109669061458b565b600260005560405162461bcd60e51b815260206004820152601160248201527014134e9415ce9393d517d1539050931151607a1b6044820152606401610966565b600b818154811061316957600080fd5b6000918252602090912001546001600160a01b0316905081565b61318b613406565b6131936135b8565b6000816001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b1580156131ce57600080fd5b505afa1580156131e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132069190614096565b9050613210612c31565b60405163305c9e0560e01b81527f5749544844524157414c5f4d414e414745525f464143544f525900000000000060048201526001600160a01b038381166024830152919091169063305c9e059060440160206040518083038186803b15801561327957600080fd5b505afa15801561328d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b191906141b8565b6132f65760405162461bcd60e51b8152602060048201526016602482015275504d3a53574d3a494e56414c49445f464143544f525960501b6044820152606401610966565b6040516335a2735f60e11b81526001600160a01b038381166004830152821690636b44e6be9060240160206040518083038186803b15801561333757600080fd5b505afa15801561334b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336f91906141b8565b6133bb5760405162461bcd60e51b815260206004820152601760248201527f504d3a53574d3a494e56414c49445f494e5354414e43450000000000000000006044820152606401610966565b600680546001600160a01b0319166001600160a01b0384169081179091556040517f0c2851fb58aab3ab4bd3cec7c6162727dcda72195b7119dec5e04f812618c51a90600090a25050565b61340e612c31565b604051634c532de160e01b81526001600160e01b03196000351660048201526001600160a01b039190911690634c532de19060240160206040518083038186803b15801561345b57600080fd5b505afa15801561346f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349391906141b8565b156134cc5760405162461bcd60e51b815260206004820152600960248201526814134e94105554d15160ba1b6044820152606401610966565b565b6004546001600160a01b031633146134cc5760405162461bcd60e51b815260206004820152600b60248201526a14134e9393d517d413d3d360aa1b6044820152606401610966565b6001546001600160a01b031633146134cc5760405162461bcd60e51b815260206004820152600960248201526814134e9393d517d41160ba1b6044820152606401610966565b600654600160a81b900460ff16158061357f57506001546001600160a01b031633145b6134cc5760405162461bcd60e51b815260206004820152600a6024820152690a09a749c9ebe82aaa8960b31b6044820152606401610966565b600654600160a81b900460ff16156134cc5760405162461bcd60e51b815260206004820152601560248201527414134e9053149150511657d0d3d3919251d5549151605a1b6044820152606401610966565b60006136347f7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af15490565b919050565b600c54604051630dace25b60e31b81523060048201526001600160a01b038581166024830152604482018490526000928392911690636d6712d89060640160206040518083038186803b15801561368f57600080fd5b505afa1580156136a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136c791906141b8565b60075490915084811180156136d95750815b6136e45760006136ee565b6136ee8582614652565b9695505050505050565b6001546001600160a01b03163314806137295750613714610891565b6001600160a01b0316336001600160a01b0316145b806137bc5750613737612c31565b6001600160a01b0316630b52d12d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561376f57600080fd5b505afa158015613783573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a79190614096565b6001600160a01b0316336001600160a01b0316145b6134cc5760405162461bcd60e51b8152602060048201526016602482015275504d3a4e4f545f50445f4f525f474f565f4f525f4f4160501b6044820152606401610966565b6000816001600160a01b031663bcead63e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561383c57600080fd5b505afa158015613850573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138749190614096565b6001600160a01b03811660009081526009602052604090205490915060ff166136345760405162461bcd60e51b815260206004820152601b60248201527f504d3a474c4d3a494e56414c49445f4c4f414e5f4d414e4147455200000000006044820152606401610966565b60006138e9612c31565b604051638d16e42b60e01b8152306004820152909150600090620f4240906001600160a01b03841690638d16e42b9060240160206040518083038186803b15801561393357600080fd5b505afa158015613947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061396b9190614281565b6003546005546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b1580156139b257600080fd5b505afa1580156139c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ea9190614281565b6139f49190614633565b6139fe9190614611565b90506000613a0c8285613d73565b90506000613a23613a1d8385614652565b87613d73565b90508115613b2157600560009054906101000a90046001600160a01b03166001600160a01b0316637378b20683866001600160a01b031663a5a276056040518163ffffffff1660e01b815260040160206040518083038186803b158015613a8957600080fd5b505afa158015613a9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac19190614096565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b03166024820152604401600060405180830381600087803b158015613b0857600080fd5b505af1158015613b1c573d6000803e3d6000fd5b505050505b8015613b9157600554600480546040516339bc590360e11b81529182018490526001600160a01b03908116602483015290911690637378b20690604401600060405180830381600087803b158015613b7857600080fd5b505af1158015613b8c573d6000803e3d6000fd5b505050505b60408051838152602081018390527f94b781636ba0868cca92a6b4702ed1bb1c01587bf498019c1b1e69737f91deb8910160405180910390a1505050505050565b6040516323396b5360e11b81523060048201526000906001600160a01b03841690634672d6a69060240160206040518083038186803b158015613c1457600080fd5b505afa158015613c28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c4c9190614281565b6005546040516370a0823160e01b81526001600160a01b039182166004820152908416906370a082319060240160206040518083038186803b158015613c9157600080fd5b505afa158015613ca5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc99190614281565b10159392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052600090613d409086906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613f72565b95945050505050565b60006136347f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000818310613d8257816130e4565b5090919050565b613d91614012565b6040821115613db757613da6828401846143c4565b604084015260208301528152611400565b613dc382840184614334565b6020830152815292915050565b600654600090606090600160a01b900460ff16613e1457505060408051808201909152600c81526b503a4e4f545f41435449564560a01b6020820152600092909150565b600754613e1f61074f565b613e2990856145f9565b1115613e645750506040805180820190915260148152730503a4445504f5349545f47545f4c49515f4341560641b6020820152600092909150565b5050604080516020810190915260008152600192909150565b6040516001600160a01b038316602482015260006044820181905290613eb090859063095ea7b360e01b90606401613d09565b613ebc575060006130e4565b81613ec9575060016130e4565b6040516001600160a01b038416602482015260448101839052612c2990859063095ea7b360e01b90606401613d09565b6000833b80613f0c5760009150506130e4565b846001600160a01b03168484604051613f26929190614445565b600060405180830381855af49150503d8060008114613f61576040519150601f19603f3d011682016040523d82523d6000602084013e613f66565b606091505b50909695505050505050565b60006001600160a01b0383163b613f8b57506000611400565b6060836001600160a01b031683604051613fa59190614455565b6000604051808303816000865af19150503d8060008114613fe2576040519150601f19603f3d011682016040523d82523d6000602084013e613fe7565b606091505b509092509050818015612c29575080511580612c29575080806020019051810190612c2991906141b8565b60405180606001604052806003906020820280368337509192915050565b60008083601f84011261404257600080fd5b50813567ffffffffffffffff81111561405a57600080fd5b60208301915083602082850101111561407257600080fd5b9250929050565b60006020828403121561408b57600080fd5b81356130e4816146e0565b6000602082840312156140a857600080fd5b81516130e4816146e0565b600080604083850312156140c657600080fd5b82356140d1816146e0565b915060208301356140e1816146e0565b809150509250929050565b600080604083850312156140ff57600080fd5b823561410a816146e0565b915060208301356140e1816146f8565b60008060006040848603121561412f57600080fd5b833561413a816146e0565b9250602084013567ffffffffffffffff81111561415657600080fd5b61416286828701614030565b9497909650939450505050565b6000806040838503121561418257600080fd5b823561418d816146e0565b946020939093013593505050565b6000602082840312156141ad57600080fd5b81356130e4816146f8565b6000602082840312156141ca57600080fd5b81516130e4816146f8565b6000806000606084860312156141ea57600080fd5b83516141f5816146f8565b602085015160409095015190969495509392505050565b6000806000806060858703121561422257600080fd5b843593506020850135614234816146e0565b9250604085013567ffffffffffffffff81111561425057600080fd5b61425c87828801614030565b95989497509550505050565b60006020828403121561427a57600080fd5b5035919050565b60006020828403121561429357600080fd5b5051919050565b600080604083850312156142ad57600080fd5b8235915060208301356140e1816146e0565b6000806000606084860312156142d457600080fd5b8335925060208401356142e6816146e0565b915060408401356142f6816146e0565b809150509250925092565b60008060006040848603121561431657600080fd5b83359250602084013567ffffffffffffffff81111561415657600080fd5b6000806040838503121561434757600080fd5b50508035926020909101359150565b6000806040838503121561436957600080fd5b505080516020909101519092909150565b6000806000806080858703121561439057600080fd5b843593506020850135925060408501356143a9816146e0565b915060608501356143b9816146e0565b939692955090935050565b6000806000606084860312156143d957600080fd5b505081359360208301359350604090920135919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151808452614431816020860160208601614669565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b60008251614467818460208701614669565b9190910192915050565b6001600160a01b0385811682528416602082015269504d3a5550475241444560b01b60408201526080606082018190526000906136ee90830184866143f0565b6001600160a01b038481168252606060208084018290528551918401829052600092868201929091906080860190855b818110156144ff5785518516835294830194918301916001016144e1565b505080945050505050826040830152949350505050565b6001600160a01b038416815269504d3a5550475241444560b01b6020820152606060408201819052600090613d4090830184866143f0565b8215158152604060208201526000612c296040830184614419565b60408152600061457c6040830185614419565b90508260208301529392505050565b60208082526009908201526814134e9313d0d2d15160ba1b604082015260600190565b734c4f414e5f4d414e414745525f464143544f525960601b81526001600160a01b0391909116602082015260400190565b838152604060208201526000613d406040830184866143f0565b6000821982111561460c5761460c6146b4565b500190565b60008261462e57634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561464d5761464d6146b4565b500290565b600082821015614664576146646146b4565b500390565b60005b8381101561468457818101518382015260200161466c565b83811115614693576000848401525b50505050565b60006000198214156146ad576146ad6146b4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03811681146146f557600080fd5b50565b80151581146146f557600080fdfea264697066735822122026eba8f092c41fa66013e532c740604a6ebdd10526e8aa8f7e828c5fd78f4feb64736f6c63430008070033

Verified Source Code Full Match

Compiler: v0.8.7+commit.e28d00a7 EVM: london Optimization: Yes (200 runs)
MaplePoolManager.sol 606 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

import { ERC20Helper }           from "../modules/erc20-helper/src/ERC20Helper.sol";
import { IMapleProxyFactory }    from "../modules/maple-proxy-factory/contracts/interfaces/IMapleProxyFactory.sol";
import { IMapleProxied }         from "../modules/maple-proxy-factory/contracts/interfaces/IMapleProxied.sol";
import { MapleProxiedInternals } from "../modules/maple-proxy-factory/contracts/MapleProxiedInternals.sol";

import { MaplePoolManagerStorage } from "./proxy/MaplePoolManagerStorage.sol";

import {
    IERC20Like,
    IGlobalsLike,
    ILoanLike,
    ILoanManagerLike,
    IPoolDelegateCoverLike,
    IPoolLike,
    IPoolPermissionManagerLike,
    IWithdrawalManagerLike
} from "./interfaces/Interfaces.sol";

import { IMaplePoolManager } from "./interfaces/IMaplePoolManager.sol";

/*

   ███╗   ███╗ █████╗ ██████╗ ██╗     ███████╗
   ████╗ ████║██╔══██╗██╔══██╗██║     ██╔════╝
   ██╔████╔██║███████║██████╔╝██║     █████╗
   ██║╚██╔╝██║██╔══██║██╔═══╝ ██║     ██╔══╝
   ██║ ╚═╝ ██║██║  ██║██║     ███████╗███████╗
   ╚═╝     ╚═╝╚═╝  ╚═╝╚═╝     ╚══════╝╚══════╝


   ██████╗  ██████╗  ██████╗ ██╗         ███╗   ███╗ █████╗ ███╗   ██╗ █████╗  ██████╗ ███████╗██████╗
   ██╔══██╗██╔═══██╗██╔═══██╗██║         ████╗ ████║██╔══██╗████╗  ██║██╔══██╗██╔════╝ ██╔════╝██╔══██╗
   ██████╔╝██║   ██║██║   ██║██║         ██╔████╔██║███████║██╔██╗ ██║███████║██║  ███╗█████╗  ██████╔╝
   ██╔═══╝ ██║   ██║██║   ██║██║         ██║╚██╔╝██║██╔══██║██║╚██╗██║██╔══██║██║   ██║██╔══╝  ██╔══██╗
   ██║     ╚██████╔╝╚██████╔╝███████╗    ██║ ╚═╝ ██║██║  ██║██║ ╚████║██║  ██║╚██████╔╝███████╗██║  ██║
   ╚═╝      ╚═════╝  ╚═════╝ ╚══════╝    ╚═╝     ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═╝

*/

contract MaplePoolManager is IMaplePoolManager, MapleProxiedInternals, MaplePoolManagerStorage {

    uint256 public constant HUNDRED_PERCENT = 100_0000;  // Four decimal precision.

    /**************************************************************************************************************************************/
    /*** Modifiers                                                                                                                      ***/
    /**************************************************************************************************************************************/

    modifier nonReentrant() {
        require(_locked == 1, "PM:LOCKED");

        _locked = 2;

        _;

        _locked = 1;
    }

    modifier onlyIfNotConfigured() {
        _revertIfConfigured();
        _;
    }

    modifier onlyPoolDelegateOrNotConfigured() {
        _revertIfConfiguredAndNotPoolDelegate();
        _;
    }

    modifier onlyPool() {
        _revertIfNotPool();
        _;
    }

    modifier onlyPoolDelegate() {
        _revertIfNotPoolDelegate();
        _;
    }

    modifier onlyPoolDelegateOrProtocolAdmins() {
        _revertIfNeitherPoolDelegateNorProtocolAdmins();
        _;
    }

    modifier whenNotPaused() {
        _revertIfPaused();
        _;
    }

    /**************************************************************************************************************************************/
    /*** Migration Functions                                                                                                            ***/
    /**************************************************************************************************************************************/

    // NOTE: Can't add whenProtocolNotPaused modifier here, as globals won't be set until
    //       initializer.initialize() is called, and this function is what triggers that initialization.
    function migrate(address migrator_, bytes calldata arguments_) external override whenNotPaused {
        require(msg.sender == _factory(),        "PM:M:NOT_FACTORY");
        require(_migrate(migrator_, arguments_), "PM:M:FAILED");
        require(poolDelegateCover != address(0), "PM:M:DELEGATE_NOT_SET");
    }

    function setImplementation(address implementation_) external override whenNotPaused {
        require(msg.sender == _factory(), "PM:SI:NOT_FACTORY");
        _setImplementation(implementation_);
    }

    function upgrade(uint256 version_, bytes calldata arguments_) external override whenNotPaused {
        IGlobalsLike globals_ = IGlobalsLike(globals());

        if (msg.sender == poolDelegate) {
            require(globals_.isValidScheduledCall(msg.sender, address(this), "PM:UPGRADE", msg.data), "PM:U:INVALID_SCHED_CALL");

            globals_.unscheduleCall(msg.sender, "PM:UPGRADE", msg.data);
        } else {
            require(msg.sender == globals_.securityAdmin(), "PM:U:NO_AUTH");
        }

        emit Upgraded(version_, arguments_);

        IMapleProxyFactory(_factory()).upgradeInstance(version_, arguments_);
    }

    /**************************************************************************************************************************************/
    /*** Initial Configuration Function                                                                                                 ***/
    /**************************************************************************************************************************************/

    // NOTE: This function is always called atomically during the deployment process so a DoS attack is not possible.
    function completeConfiguration() external override whenNotPaused onlyIfNotConfigured {
        configured = true;

        emit PoolConfigurationComplete();
    }

    /**************************************************************************************************************************************/
    /*** Ownership Transfer Functions                                                                                                   ***/
    /**************************************************************************************************************************************/

    function acceptPoolDelegate() external override whenNotPaused {
        require(msg.sender == pendingPoolDelegate, "PM:APD:NOT_PENDING_PD");

        IGlobalsLike(globals()).transferOwnedPoolManager(poolDelegate, msg.sender);

        emit PendingDelegateAccepted(poolDelegate, pendingPoolDelegate);

        poolDelegate        = pendingPoolDelegate;
        pendingPoolDelegate = address(0);
    }

    function setPendingPoolDelegate(address pendingPoolDelegate_) external override whenNotPaused onlyPoolDelegateOrProtocolAdmins {
        pendingPoolDelegate = pendingPoolDelegate_;

        emit PendingDelegateSet(poolDelegate, pendingPoolDelegate_);
    }

    /**************************************************************************************************************************************/
    /*** Globals Admin Functions                                                                                                        ***/
    /**************************************************************************************************************************************/

    function setActive(bool active_) external override whenNotPaused {
        require(msg.sender == globals(), "PM:SA:NOT_GLOBALS");
        emit SetAsActive(active = active_);
    }

    /**************************************************************************************************************************************/
    /*** Pool Delegate Admin Functions                                                                                                  ***/
    /**************************************************************************************************************************************/

    function addLoanManager(address loanManagerFactory_)
        external override whenNotPaused onlyPoolDelegateOrNotConfigured returns (address loanManager_)
    {
        require(IGlobalsLike(globals()).isInstanceOf("LOAN_MANAGER_FACTORY", loanManagerFactory_), "PM:ALM:INVALID_FACTORY");

        // NOTE: If removing loan managers is allowed in the future, there will be a need to rethink salts here due to collisions.
        loanManager_ = IMapleProxyFactory(loanManagerFactory_).createInstance(
            abi.encode(address(this)),
            keccak256(abi.encode(address(this), loanManagerList.length))
        );

        isLoanManager[loanManager_] = true;

        loanManagerList.push(loanManager_);

        emit LoanManagerAdded(loanManager_);
    }

    function setDelegateManagementFeeRate(uint256 delegateManagementFeeRate_)
        external override whenNotPaused onlyPoolDelegateOrNotConfigured
    {
        require(delegateManagementFeeRate_ <= HUNDRED_PERCENT, "PM:SDMFR:OOB");

        emit DelegateManagementFeeRateSet(delegateManagementFeeRate = delegateManagementFeeRate_);
    }

    function setIsLoanManager(address loanManager_, bool isLoanManager_) external override whenNotPaused onlyPoolDelegate {
        emit IsLoanManagerSet(loanManager_, isLoanManager[loanManager_] = isLoanManager_);

        // Check LoanManager is in the list.
        // NOTE: The factory and instance check are not required as the mapping is being updated for a LoanManager that is in the list.
        for (uint256 i_; i_ < loanManagerList.length; ++i_) {
            if (loanManagerList[i_] == loanManager_) return;
        }

        revert("PM:SILM:INVALID_LM");
    }

    function setLiquidityCap(uint256 liquidityCap_) external override whenNotPaused onlyPoolDelegateOrNotConfigured {
        emit LiquidityCapSet(liquidityCap = liquidityCap_);
    }

    function setWithdrawalManager(address withdrawalManager_) external override whenNotPaused onlyIfNotConfigured {
        address factory_ = IMapleProxied(withdrawalManager_).factory();

        require(IGlobalsLike(globals()).isInstanceOf("WITHDRAWAL_MANAGER_FACTORY", factory_), "PM:SWM:INVALID_FACTORY");
        require(IMapleProxyFactory(factory_).isInstance(withdrawalManager_),                  "PM:SWM:INVALID_INSTANCE");

        emit WithdrawalManagerSet(withdrawalManager = withdrawalManager_);
    }

    function setPoolPermissionManager(address poolPermissionManager_) external override whenNotPaused onlyPoolDelegateOrNotConfigured {
        require(IGlobalsLike(globals()).isInstanceOf("POOL_PERMISSION_MANAGER", poolPermissionManager_), "PM:SPPM:INVALID_INSTANCE");

        emit PoolPermissionManagerSet(poolPermissionManager = poolPermissionManager_);
    }

    /**************************************************************************************************************************************/
    /*** Funding Functions                                                                                                              ***/
    /**************************************************************************************************************************************/

    function requestFunds(address destination_, uint256 principal_) external override whenNotPaused nonReentrant {
        address asset_   = asset;
        address pool_    = pool;
        address factory_ = IMapleProxied(msg.sender).factory();

        IGlobalsLike globals_ = IGlobalsLike(globals());

        // NOTE: Do not need to check isInstance() as the LoanManager is added to the list on `addLoanManager()` or `configure()`.
        require(principal_ != 0,                                         "PM:RF:INVALID_PRINCIPAL");
        require(globals_.isInstanceOf("LOAN_MANAGER_FACTORY", factory_), "PM:RF:INVALID_FACTORY");
        require(IMapleProxyFactory(factory_).isInstance(msg.sender),     "PM:RF:INVALID_INSTANCE");
        require(isLoanManager[msg.sender],                               "PM:RF:NOT_LM");
        require(IERC20Like(pool_).totalSupply() != 0,                    "PM:RF:ZERO_SUPPLY");
        require(_hasSufficientCover(address(globals_), asset_),          "PM:RF:INSUFFICIENT_COVER");

        // Fetching locked liquidity needs to be done prior to transferring the tokens.
        uint256 lockedLiquidity_ = IWithdrawalManagerLike(withdrawalManager).lockedLiquidity();

        // Transfer the required principal.
        require(destination_ != address(0),                                        "PM:RF:INVALID_DESTINATION");
        require(ERC20Helper.transferFrom(asset_, pool_, destination_, principal_), "PM:RF:TRANSFER_FAIL");

        // The remaining liquidity in the pool must be greater or equal to the locked liquidity.
        require(IERC20Like(asset_).balanceOf(pool_) >= lockedLiquidity_, "PM:RF:LOCKED_LIQUIDITY");
    }

    /**************************************************************************************************************************************/
    /*** Loan Default Functions                                                                                                         ***/
    /**************************************************************************************************************************************/

    function finishCollateralLiquidation(address loan_) external override whenNotPaused nonReentrant onlyPoolDelegateOrProtocolAdmins {
        ( uint256 losses_, uint256 platformFees_ ) = ILoanManagerLike(_getLoanManager(loan_)).finishCollateralLiquidation(loan_);

        _handleCover(losses_, platformFees_);

        emit CollateralLiquidationFinished(loan_, losses_);
    }

    function triggerDefault(address loan_, address liquidatorFactory_)
        external override whenNotPaused nonReentrant onlyPoolDelegateOrProtocolAdmins
    {
        require(IGlobalsLike(globals()).isInstanceOf("LIQUIDATOR_FACTORY", liquidatorFactory_), "PM:TD:NOT_FACTORY");

        (
            bool    liquidationComplete_,
            uint256 losses_,
            uint256 platformFees_
        ) = ILoanManagerLike(_getLoanManager(loan_)).triggerDefault(loan_, liquidatorFactory_);

        if (!liquidationComplete_) {
            emit CollateralLiquidationTriggered(loan_);
            return;
        }

        _handleCover(losses_, platformFees_);

        emit CollateralLiquidationFinished(loan_, losses_);
    }

    /**************************************************************************************************************************************/
    /*** Pool Exit Functions                                                                                                            ***/
    /**************************************************************************************************************************************/

    function processRedeem(uint256 shares_, address owner_, address sender_)
        external override whenNotPaused nonReentrant onlyPool returns (uint256 redeemableShares_, uint256 resultingAssets_)
    {
        require(owner_ == sender_ || IPoolLike(pool).allowance(owner_, sender_) > 0, "PM:PR:NO_ALLOWANCE");

        ( redeemableShares_, resultingAssets_ ) = IWithdrawalManagerLike(withdrawalManager).processExit(shares_, owner_);
        emit RedeemProcessed(owner_, redeemableShares_, resultingAssets_);
    }

    function processWithdraw(uint256 assets_, address owner_, address sender_)
        external override whenNotPaused nonReentrant returns (uint256 redeemableShares_, uint256 resultingAssets_)
    {
        assets_; owner_; sender_; redeemableShares_; resultingAssets_;  // Silence compiler warnings
        require(false, "PM:PW:NOT_ENABLED");
    }

    function removeShares(uint256 shares_, address owner_)
        external override whenNotPaused nonReentrant onlyPool returns (uint256 sharesReturned_)
    {
        emit SharesRemoved(
            owner_,
            sharesReturned_ = IWithdrawalManagerLike(withdrawalManager).removeShares(shares_, owner_)
        );
    }

    function requestRedeem(uint256 shares_, address owner_, address sender_) external override whenNotPaused nonReentrant onlyPool {
        address pool_ = pool;

        require(ERC20Helper.approve(pool_, withdrawalManager, shares_), "PM:RR:APPROVE_FAIL");

        if (sender_ != owner_ && shares_ == 0) {
            require(IPoolLike(pool_).allowance(owner_, sender_) > 0, "PM:RR:NO_ALLOWANCE");
        }

        IWithdrawalManagerLike(withdrawalManager).addShares(shares_, owner_);

        emit RedeemRequested(owner_, shares_);
    }

    function requestWithdraw(uint256 shares_, uint256 assets_, address owner_, address sender_)
        external override whenNotPaused nonReentrant
    {
        shares_; assets_; owner_; sender_;  // Silence compiler warnings
        require(false, "PM:RW:NOT_ENABLED");
    }

    /**************************************************************************************************************************************/
    /*** Pool Delegate Cover Functions                                                                                                  ***/
    /**************************************************************************************************************************************/

    function depositCover(uint256 amount_) external override whenNotPaused {
        require(ERC20Helper.transferFrom(asset, msg.sender, poolDelegateCover, amount_), "PM:DC:TRANSFER_FAIL");
        emit CoverDeposited(amount_);
    }

    function withdrawCover(uint256 amount_, address recipient_) external override whenNotPaused onlyPoolDelegate {
        recipient_ = recipient_ == address(0) ? msg.sender : recipient_;

        IPoolDelegateCoverLike(poolDelegateCover).moveFunds(amount_, recipient_);

        require(
            IERC20Like(asset).balanceOf(poolDelegateCover) >= IGlobalsLike(globals()).minCoverAmount(address(this)),
            "PM:WC:BELOW_MIN"
        );

        emit CoverWithdrawn(amount_);
    }

    /**************************************************************************************************************************************/
    /*** View Functions                                                                                                                 ***/
    /**************************************************************************************************************************************/

    function canCall(bytes32 functionId_, address caller_, bytes calldata data_)
        external view override returns (bool canCall_, string memory errorMessage_)
    {
        if (IGlobalsLike(globals()).isFunctionPaused(msg.sig)) return (false, "PM:CC:PAUSED");

        uint256[3] memory params_ = _decodeParameters(data_);

        uint256 assets_ = params_[0];
        address lender_ = _address(params_[1]);

        // For mint functions there's a need to convert shares into assets.
        if (functionId_ == "P:mint" || functionId_ == "P:mintWithPermit") assets_ = IPoolLike(pool).previewMint(params_[0]);

        // Redeem and withdraw require getting the third word from the calldata.
        if ( functionId_ == "P:redeem" || functionId_ == "P:withdraw") lender_ = _address(params_[2]);

        // Transfers need to check both the sender and the recipient.
        if (functionId_ == "P:transfer" || functionId_ == "P:transferFrom") {
            address[] memory lenders_ = new address[](2);

            ( lenders_[0], lenders_[1] ) = functionId_ == "P:transfer" ?
                (caller_,              _address(params_[0])) :
                (_address(params_[0]), _address(params_[1]));

            // Check both lenders in a single call.
            if (!IPoolPermissionManagerLike(poolPermissionManager).hasPermission(address(this), lenders_, functionId_)) {
                return (false, "PM:CC:NOT_ALLOWED");
            }

        } else {
            if (!IPoolPermissionManagerLike(poolPermissionManager).hasPermission(address(this), lender_, functionId_)) {
                return (false, "PM:CC:NOT_ALLOWED");
            }
        }

        if (
            functionId_ == "P:redeem"          ||
            functionId_ == "P:withdraw"        ||
            functionId_ == "P:removeShares"    ||
            functionId_ == "P:requestRedeem"   ||
            functionId_ == "P:requestWithdraw" ||
            functionId_ == "P:transfer"        ||
            functionId_ == "P:transferFrom"
        ) return (true, "");

        if (
            functionId_ == "P:deposit"           ||
            functionId_ == "P:depositWithPermit" ||
            functionId_ == "P:mint"              ||
            functionId_ == "P:mintWithPermit"
        ) return _canDeposit(assets_);

        return (false, "PM:CC:INVALID_FUNCTION_ID");
    }

    function factory() external view override returns (address factory_) {
        factory_ = _factory();
    }

    function globals() public view override returns (address globals_) {
        globals_ = IMapleProxyFactory(_factory()).mapleGlobals();
    }

    function governor() public view override returns (address governor_) {
        governor_ = IGlobalsLike(globals()).governor();
    }

    function hasSufficientCover() public view override returns (bool hasSufficientCover_) {
        hasSufficientCover_ = _hasSufficientCover(globals(), asset);
    }

    function implementation() external view override returns (address implementation_) {
        implementation_ = _implementation();
    }

    function loanManagerListLength() external view override returns (uint256 loanManagerListLength_) {
        loanManagerListLength_ = loanManagerList.length;
    }

    function totalAssets() public view override returns (uint256 totalAssets_) {
        totalAssets_ = IERC20Like(asset).balanceOf(pool);

        uint256 length_ = loanManagerList.length;

        for (uint256 i_; i_ < length_;) {
            totalAssets_ += ILoanManagerLike(loanManagerList[i_]).assetsUnderManagement();
            unchecked { ++i_; }
        }
    }

    /**************************************************************************************************************************************/
    /*** LP Token View Functions                                                                                                        ***/
    /**************************************************************************************************************************************/

    function convertToExitShares(uint256 assets_) public view override returns (uint256 shares_) {
        shares_ = IPoolLike(pool).convertToExitShares(assets_);
    }

    function getEscrowParams(address, uint256 shares_) external view override returns (uint256 escrowShares_, address destination_) {
        // NOTE: `owner_` param not named to avoid compiler warning.
        ( escrowShares_, destination_) = (shares_, address(this));
    }

    function maxDeposit(address receiver_) external view virtual override returns (uint256 maxAssets_) {
        maxAssets_ = _getMaxAssets(receiver_, totalAssets(), "P:deposit");
    }

    function maxMint(address receiver_) external view virtual override returns (uint256 maxShares_) {
        uint256 totalAssets_ = totalAssets();
        uint256 maxAssets_   = _getMaxAssets(receiver_, totalAssets_, "P:mint");

        maxShares_ = IPoolLike(pool).previewDeposit(maxAssets_);
    }

    function maxRedeem(address owner_) external view virtual override returns (uint256 maxShares_) {
        uint256 lockedShares_ = IWithdrawalManagerLike(withdrawalManager).lockedShares(owner_);
        maxShares_            = IWithdrawalManagerLike(withdrawalManager).isInExitWindow(owner_) ? lockedShares_ : 0;
    }

    function maxWithdraw(address owner_) external view virtual override returns (uint256 maxAssets_) {
        owner_;          // Silence compiler warning
        maxAssets_ = 0;  // NOTE: always returns 0 as withdraw is not implemented
    }

    function previewRedeem(address owner_, uint256 shares_) external view virtual override returns (uint256 assets_) {
        ( , assets_ ) = IWithdrawalManagerLike(withdrawalManager).previewRedeem(owner_, shares_);
    }

    function previewWithdraw(address owner_, uint256 assets_) external view virtual override returns (uint256 shares_) {
        ( , shares_ ) = IWithdrawalManagerLike(withdrawalManager).previewWithdraw(owner_, assets_);
    }

    function unrealizedLosses() public view override returns (uint256 unrealizedLosses_) {
        uint256 length_ = loanManagerList.length;

        for (uint256 i_; i_ < length_;) {
            unrealizedLosses_ += ILoanManagerLike(loanManagerList[i_]).unrealizedLosses();
            unchecked { ++i_; }
        }

        // NOTE: Use minimum to prevent underflows in the case that `unrealizedLosses` includes late interest and `totalAssets` does not.
        unrealizedLosses_ = _min(unrealizedLosses_, totalAssets());
    }

    /**************************************************************************************************************************************/
    /*** Internal Helper Functions                                                                                                      ***/
    /**************************************************************************************************************************************/

    function _getLoanManager(address loan_) internal view returns (address loanManager_) {
        loanManager_ = ILoanLike(loan_).lender();

        require(isLoanManager[loanManager_], "PM:GLM:INVALID_LOAN_MANAGER");
    }

    function _handleCover(uint256 losses_, uint256 platformFees_) internal {
        address globals_ = globals();

        uint256 availableCover_ =
            IERC20Like(asset).balanceOf(poolDelegateCover) * IGlobalsLike(globals_).maxCoverLiquidationPercent(address(this)) /
            HUNDRED_PERCENT;

        uint256 toTreasury_ = _min(availableCover_,               platformFees_);
        uint256 toPool_     = _min(availableCover_ - toTreasury_, losses_);

        if (toTreasury_ != 0) {
            IPoolDelegateCoverLike(poolDelegateCover).moveFunds(toTreasury_, IGlobalsLike(globals_).mapleTreasury());
        }

        if (toPool_ != 0) {
            IPoolDelegateCoverLike(poolDelegateCover).moveFunds(toPool_, pool);
        }

        emit CoverLiquidated(toTreasury_, toPool_);
    }

    /**************************************************************************************************************************************/
    /*** Internal Functions                                                                                                             ***/
    /**************************************************************************************************************************************/

    function _address(uint256 word_) internal pure returns (address address_) {
        address_ = address(uint160(word_));
    }

    function _canDeposit(uint256 assets_) internal view returns (bool canDeposit_, string memory errorMessage_) {
        if (!active)                                return (false, "P:NOT_ACTIVE");
        if (assets_ + totalAssets() > liquidityCap) return (false, "P:DEPOSIT_GT_LIQ_CAP");

        return (true, "");
    }

    function _decodeParameters(bytes calldata data_) internal pure returns (uint256[3] memory words) {
        if (data_.length > 64)  {
            ( words[0], words[1], words[2] ) = abi.decode(data_, (uint256, uint256, uint256));
        } else {
            ( words[0], words[1] ) = abi.decode(data_, (uint256, uint256));
        }
    }

    function _getMaxAssets(address receiver_, uint256 totalAssets_, bytes32 functionId_) internal view returns (uint256 maxAssets_) {
        bool    depositAllowed_ = IPoolPermissionManagerLike(poolPermissionManager).hasPermission(address(this),  receiver_, functionId_);
        uint256 liquidityCap_   = liquidityCap;
        maxAssets_              = liquidityCap_ > totalAssets_ && depositAllowed_ ? liquidityCap_ - totalAssets_ : 0;
    }

    function _hasSufficientCover(address globals_, address asset_) internal view returns (bool hasSufficientCover_) {
        hasSufficientCover_ = IERC20Like(asset_).balanceOf(poolDelegateCover) >= IGlobalsLike(globals_).minCoverAmount(address(this));
    }

    function _min(uint256 a_, uint256 b_) internal pure returns (uint256 minimum_) {
        minimum_ = a_ < b_ ? a_ : b_;
    }

    function _revertIfConfigured() internal view {
        require(!configured, "PM:ALREADY_CONFIGURED");
    }

    function _revertIfConfiguredAndNotPoolDelegate() internal view {
        require(!configured || msg.sender == poolDelegate, "PM:NO_AUTH");
    }

    function _revertIfNotPool() internal view {
        require(msg.sender == pool, "PM:NOT_POOL");
    }

    function _revertIfNotPoolDelegate() internal view {
        require(msg.sender == poolDelegate, "PM:NOT_PD");
    }

    function _revertIfNeitherPoolDelegateNorProtocolAdmins() internal view {
        require(
            msg.sender == poolDelegate ||
            msg.sender == governor()   ||
            msg.sender == IGlobalsLike(globals()).operationalAdmin(),
            "PM:NOT_PD_OR_GOV_OR_OA"
        );
    }

    function _revertIfPaused() internal view {
        require(!IGlobalsLike(globals()).isFunctionPaused(msg.sig), "PM:PAUSED");
    }

}
Interfaces.sol 182 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

interface IERC20Like {

    function allowance(address owner_, address spender_) external view returns (uint256 allowance_);

    function balanceOf(address account_) external view returns (uint256 balance_);

    function totalSupply() external view returns (uint256 totalSupply_);

}

interface IGlobalsLike {

    function bootstrapMint(address asset_) external view returns (uint256 bootstrapMint_);

    function governor() external view returns (address governor_);

    function isFunctionPaused(bytes4 sig_) external view returns (bool isFunctionPaused_);

    function isInstanceOf(bytes32 instanceId_, address instance_) external view returns (bool isInstance_);

    function isPoolAsset(address asset_) external view returns (bool isPoolAsset_);

    function isPoolDelegate(address account_) external view returns (bool isPoolDelegate_);

    function isPoolDeployer(address poolDeployer_) external view returns (bool isPoolDeployer_);

    function isValidScheduledCall(address caller_, address contract_, bytes32 functionId_, bytes calldata callData_)
        external view
        returns (bool isValid_);

    function mapleTreasury() external view returns (address mapleTreasury_);

    function maxCoverLiquidationPercent(address poolManager_) external view returns (uint256 maxCoverLiquidationPercent_);

    function migrationAdmin() external view returns (address migrationAdmin_);

    function minCoverAmount(address poolManager_) external view returns (uint256 minCoverAmount_);

    function operationalAdmin() external view returns (address operationalAdmin_);

    function ownedPoolManager(address poolDelegate_) external view returns (address poolManager_);

    function securityAdmin() external view returns (address securityAdmin_);

    function transferOwnedPoolManager(address fromPoolDelegate_, address toPoolDelegate_) external;

    function unscheduleCall(address caller_, bytes32 functionId_, bytes calldata callData_) external;

}

interface ILoanManagerLike {

    function assetsUnderManagement() external view returns (uint256 assetsUnderManagement_);

    function finishCollateralLiquidation(address loan_) external returns (uint256 remainingLosses_, uint256 serviceFee_);

    function triggerDefault(address loan_, address liquidatorFactory_)
        external
        returns (bool liquidationComplete_, uint256 remainingLosses_, uint256 platformFees_);

    function unrealizedLosses() external view returns (uint256 unrealizedLosses_);

}

interface ILoanLike {

    function lender() external view returns (address lender_);

}

interface IMapleProxyFactoryLike {

    function isInstance(address instance_) external view returns (bool isInstance_);

    function mapleGlobals() external view returns (address mapleGlobals_);

}

interface IPoolDelegateCoverLike {

    function moveFunds(uint256 amount_, address recipient_) external;

}

interface IPoolLike is IERC20Like {

    function convertToExitShares(uint256 assets_) external view returns (uint256 shares_);

    function previewDeposit(uint256 assets_) external view returns (uint256 shares_);

    function previewMint(uint256 shares_) external view returns (uint256 assets_);

}

interface IPoolManagerLike {

    function addLoanManager(address loanManagerFactory_) external returns (address loanManager_);

    function canCall(bytes32 functionId_, address caller_, bytes memory data_)
        external view
        returns (bool canCall_, string memory errorMessage_);

    function completeConfiguration() external;

    function getEscrowParams(address owner_, uint256 shares_) external view returns (uint256 escrowShares_, address escrow_);

    function maxDeposit(address receiver_) external view returns (uint256 maxAssets_);

    function maxMint(address receiver_) external view returns (uint256 maxShares_);

    function maxRedeem(address owner_) external view returns (uint256 maxShares_);

    function maxWithdraw(address owner_) external view returns (uint256 maxAssets_);

    function pool() external view returns (address pool_);

    function poolDelegateCover() external view returns (address poolDelegateCover_);

    function previewRedeem(address owner_, uint256 shares_) external view returns (uint256 assets_);

    function previewWithdraw(address owner_, uint256 assets_) external view returns (uint256 shares_);

    function processRedeem(uint256 shares_, address owner_, address sender_)
        external
        returns (uint256 redeemableShares_, uint256 resultingAssets_);

    function processWithdraw(uint256 assets_, address owner_, address sender_)
        external
        returns (uint256 redeemableShares_, uint256 resultingAssets_);

    function removeShares(uint256 shares_, address owner_) external returns (uint256 sharesReturned_);

    function requestRedeem(uint256 shares_, address owner_, address sender_) external;

    function requestWithdraw(uint256 shares_, uint256 assets_, address owner_, address sender_) external;

    function setDelegateManagementFeeRate(uint256 delegateManagementFeeRate_) external;

    function setLiquidityCap(uint256 liquidityCap_) external;

    function setPoolPermissionManager(address poolPermissionManager_) external;

    function setWithdrawalManager(address withdrawalManager_) external;

    function totalAssets() external view returns (uint256 totalAssets_);

    function unrealizedLosses() external view returns (uint256 unrealizedLosses_);

}

interface IPoolPermissionManagerLike {

    function hasPermission(address poolManager, address caller, bytes32 functionId) external view returns (bool allowed);

    function hasPermission(address poolManager, address[] calldata caller, bytes32 functionId) external view returns (bool allowed);

}

interface IWithdrawalManagerLike {

    function addShares(uint256 shares_, address owner_) external;

    function factory() external view returns (address factory_);

    function isInExitWindow(address owner_) external view returns (bool isInExitWindow_);

    function lockedLiquidity() external view returns (uint256 lockedLiquidity_);

    function lockedShares(address owner_) external view returns (uint256 lockedShares_);

    function previewRedeem(address owner_, uint256 shares) external view returns (uint256 redeemableShares, uint256 resultingAssets_);

    function previewWithdraw(address owner_, uint256 assets_) external view returns (uint256 redeemableAssets_, uint256 resultingShares_);

    function processExit(uint256 shares_, address account_) external returns (uint256 redeemableShares_, uint256 resultingAssets_);

    function removeShares(uint256 shares_, address owner_) external returns (uint256 sharesReturned_);

}
ERC20Helper.sol 43 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

import { IERC20Like } from "./interfaces/IERC20Like.sol";

/**
 * @title Small Library to standardize erc20 token interactions.
 */
library ERC20Helper {

    /**************************************************************************************************************************************/
    /*** Internal Functions                                                                                                             ***/
    /**************************************************************************************************************************************/

    function transfer(address token_, address to_, uint256 amount_) internal returns (bool success_) {
        return _call(token_, abi.encodeWithSelector(IERC20Like.transfer.selector, to_, amount_));
    }

    function transferFrom(address token_, address from_, address to_, uint256 amount_) internal returns (bool success_) {
        return _call(token_, abi.encodeWithSelector(IERC20Like.transferFrom.selector, from_, to_, amount_));
    }

    function approve(address token_, address spender_, uint256 amount_) internal returns (bool success_) {
        // If setting approval to zero fails, return false.
        if (!_call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, uint256(0)))) return false;

        // If `amount_` is zero, return true as the previous step already did this.
        if (amount_ == uint256(0)) return true;

        // Return the result of setting the approval to `amount_`.
        return _call(token_, abi.encodeWithSelector(IERC20Like.approve.selector, spender_, amount_));
    }

    function _call(address token_, bytes memory data_) private returns (bool success_) {
        if (token_.code.length == uint256(0)) return false;

        bytes memory returnData;
        ( success_, returnData ) = token_.call(data_);

        return success_ && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));
    }

}
IMaplePoolManager.sol 420 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

import { IMapleProxied } from "../../modules/maple-proxy-factory/contracts/interfaces/IMapleProxied.sol";

import { IMaplePoolManagerStorage } from "./IMaplePoolManagerStorage.sol";

interface IMaplePoolManager is IMapleProxied, IMaplePoolManagerStorage {

    /**************************************************************************************************************************************/
    /*** Events                                                                                                                         ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev   Emitted when a collateral liquidations is finished.
     *  @param loan_             The address of the loan.
     *  @param unrealizedLosses_ The amount of unrealized losses.
     */
    event CollateralLiquidationFinished(address indexed loan_, uint256 unrealizedLosses_);

    /**
     *  @dev   Emitted when a collateral liquidations is triggered.
     *  @param loan_ The address of the loan.
     */
    event CollateralLiquidationTriggered(address indexed loan_);

    /**
     *  @dev   Emitted when cover is deposited.
     *  @param amount_ The amount of cover deposited.
     */
    event CoverDeposited(uint256 amount_);

    /**
     *  @dev   Emitted when cover is liquidated in the case of a loan defaulting.
     *  @param toTreasury_ The amount of cover sent to the Treasury.
     *  @param toPool_     The amount of cover sent to the Pool.
     */
    event CoverLiquidated(uint256 toTreasury_, uint256 toPool_);

    /**
     *  @dev   Emitted when cover is withdrawn.
     *  @param amount_ The amount of cover withdrawn.
     */
    event CoverWithdrawn(uint256 amount_);

    /**
     *  @dev   Emitted when a new management fee rate is set.
     *  @param managementFeeRate_ The amount of management fee rate.
     */
    event DelegateManagementFeeRateSet(uint256 managementFeeRate_);

    /**
     *  @dev   Emitted when a loan manager is set as valid.
     *  @param loanManager_   The address of the loan manager.
     *  @param isLoanManager_ Whether the loan manager is valid.
     */
    event IsLoanManagerSet(address indexed loanManager_, bool isLoanManager_);

    /**
     *  @dev   Emitted when a new liquidity cap is set.
     *  @param liquidityCap_ The value of liquidity cap.
     */
    event LiquidityCapSet(uint256 liquidityCap_);

    /**
     *  @dev   Emitted when a new loan manager is added.
     *  @param loanManager_ The address of the new loan manager.
     */
    event LoanManagerAdded(address indexed loanManager_);

    /**
     *  @dev   Emitted when the pending pool delegate accepts the ownership transfer.
     *  @param previousDelegate_ The address of the previous delegate.
     *  @param newDelegate_      The address of the new delegate.
     */
    event PendingDelegateAccepted(address indexed previousDelegate_, address indexed newDelegate_);

    /**
     *  @dev   Emitted when the pending pool delegate is set.
     *  @param previousDelegate_ The address of the previous delegate.
     *  @param newDelegate_      The address of the new delegate.
     */
    event PendingDelegateSet(address indexed previousDelegate_, address indexed newDelegate_);

    /**
     *  @dev Emitted when the pool configuration is marked as complete.
     */
    event PoolConfigurationComplete();

    /**
     *  @dev   Emitted when the pool permission manager is set.
     *  @param poolPermissionManager_ The address of the pool permission manager.
     */
    event PoolPermissionManagerSet(address indexed poolPermissionManager_);

    /**
     *  @dev   Emitted when a redemption of shares from the pool is processed.
     *  @param owner_            The owner of the shares.
     *  @param redeemableShares_ The amount of redeemable shares.
     *  @param resultingAssets_  The amount of assets redeemed.
     */
    event RedeemProcessed(address indexed owner_, uint256 redeemableShares_, uint256 resultingAssets_);

    /**
     *  @dev   Emitted when a redemption of shares from the pool is requested.
     *  @param owner_  The owner of the shares.
     *  @param shares_ The amount of redeemable shares.
     */
    event RedeemRequested(address indexed owner_, uint256 shares_);

    /**
     *  @dev   Emitted when a pool is sets to be active or inactive.
     *  @param active_ Whether the pool is active.
     */
    event SetAsActive(bool active_);

    /**
     *  @dev   Emitted when shares are removed from the pool.
     *  @param owner_  The address of the owner of the shares.
     *  @param shares_ The amount of shares removed.
     */
    event SharesRemoved(address indexed owner_, uint256 shares_);

    /**
     *  @dev   Emitted when the withdrawal manager is set.
     *  @param withdrawalManager_ The address of the withdrawal manager.
     */
    event WithdrawalManagerSet(address indexed withdrawalManager_);

    /**
     *  @dev   Emitted when withdrawal of assets from the pool is processed.
     *  @param owner_            The owner of the assets.
     *  @param redeemableShares_ The amount of redeemable shares.
     *  @param resultingAssets_  The amount of assets redeemed.
     */
    event WithdrawalProcessed(address indexed owner_, uint256 redeemableShares_, uint256 resultingAssets_);

    /**************************************************************************************************************************************/
    /*** Ownership Transfer Functions                                                                                                   ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev Accepts the role of pool delegate.
     */
    function acceptPoolDelegate() external;

    /**
     *  @dev   Sets an address as the pending pool delegate.
     *  @param pendingPoolDelegate_ The address of the new pool delegate.
     */
    function setPendingPoolDelegate(address pendingPoolDelegate_) external;

    /**************************************************************************************************************************************/
    /*** Administrative Functions                                                                                                       ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Adds a new loan manager.
     *  @param  loanManagerFactory_ The address of the loan manager factory to use.
     *  @return loanManager_        The address of the new loan manager.
     */
    function addLoanManager(address loanManagerFactory_) external returns (address loanManager_);

    /**
     *  @dev Complete the configuration.
     */
    function completeConfiguration() external;

    /**
     *  @dev   Sets a the pool to be active or inactive.
     *  @param active_ Whether the pool is active.
     */
    function setActive(bool active_) external;

    /**
     *  @dev   Sets the value for the delegate management fee rate.
     *  @param delegateManagementFeeRate_ The value for the delegate management fee rate.
     */
    function setDelegateManagementFeeRate(uint256 delegateManagementFeeRate_) external;

    /**
     *  @dev   Sets if the loanManager is valid in the isLoanManager mapping.
     *  @param loanManager_   The address of the loanManager
     *  @param isLoanManager_ Whether the loanManager is valid.
     */
    function setIsLoanManager(address loanManager_, bool isLoanManager_) external;

    /**
     *  @dev   Sets the value for liquidity cap.
     *  @param liquidityCap_ The value for liquidity cap.
     */
    function setLiquidityCap(uint256 liquidityCap_) external;

    /**
     *  @dev   Sets the address of the pool permission manager.
     *  @param poolPermission_ The address of the pool permission manager.
     */
    function setPoolPermissionManager(address poolPermission_) external;

    /**
     *  @dev   Sets the address of the withdrawal manager.
     *  @param withdrawalManager_ The address of the withdrawal manager.
     */
    function setWithdrawalManager(address withdrawalManager_) external;

    /**************************************************************************************************************************************/
    /*** Funding Functions                                                                                                              ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev   LoanManager can request funds from the pool via the poolManager.
     *  @param destination_ The address to send the funds to.
     *  @param principal_   The principal amount to fund the loan with.
     */
    function requestFunds(address destination_, uint256 principal_) external;

    /**************************************************************************************************************************************/
    /*** Liquidation Functions                                                                                                          ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev   Finishes the collateral liquidation
     *  @param loan_ Loan that had its collateral liquidated.
     */
    function finishCollateralLiquidation(address loan_) external;

    /**
     *  @dev   Triggers the default of a loan.
     *  @param loan_              Loan to trigger the default.
     *  @param liquidatorFactory_ Factory used to deploy the liquidator.
     */
    function triggerDefault(address loan_, address liquidatorFactory_) external;

    /**************************************************************************************************************************************/
    /*** Exit Functions                                                                                                                 ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Processes a redemptions of shares for assets from the pool.
     *  @param  shares_           The amount of shares to redeem.
     *  @param  owner_            The address of the owner of the shares.
     *  @param  sender_           The address of the sender of the redeem call.
     *  @return redeemableShares_ The amount of shares redeemed.
     *  @return resultingAssets_  The amount of assets withdrawn.
     */
    function processRedeem(uint256 shares_, address owner_, address sender_)
        external
        returns (uint256 redeemableShares_, uint256 resultingAssets_);

    /**
     *  @dev    Processes a redemptions of shares for assets from the pool.
     *  @param  assets_           The amount of assets to withdraw.
     *  @param  owner_            The address of the owner of the shares.
     *  @param  sender_           The address of the sender of the withdraw call.
     *  @return redeemableShares_ The amount of shares redeemed.
     *  @return resultingAssets_  The amount of assets withdrawn.
     */
    function processWithdraw(uint256 assets_, address owner_, address sender_)
        external
        returns (uint256 redeemableShares_, uint256 resultingAssets_);

    /**
     *  @dev    Requests a redemption of shares from the pool.
     *  @param  shares_         The amount of shares to redeem.
     *  @param  owner_          The address of the owner of the shares.
     *  @return sharesReturned_ The amount of shares withdrawn.
     */
    function removeShares(uint256 shares_, address owner_) external returns (uint256 sharesReturned_);

    /**
     *  @dev   Requests a redemption of shares from the pool.
     *  @param shares_ The amount of shares to redeem.
     *  @param owner_  The address of the owner of the shares.
     *  @param sender_ The address of the sender of the shares.
     */
    function requestRedeem(uint256 shares_, address owner_, address sender_) external;

    /**
     *  @dev   Requests a withdrawal of assets from the pool.
     *  @param shares_ The amount of shares to redeem.
     *  @param assets_ The amount of assets to withdraw.
     *  @param owner_  The address of the owner of the shares.
     *  @param sender_ The address of the sender of the shares.
     */
     function requestWithdraw(uint256 shares_, uint256 assets_, address owner_, address sender_) external;

    /**************************************************************************************************************************************/
    /*** Cover Functions                                                                                                                ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev   Deposits cover into the pool.
     *  @param amount_ The amount of cover to deposit.
     */
    function depositCover(uint256 amount_) external;

    /**
     *  @dev   Withdraws cover from the pool.
     *  @param amount_    The amount of cover to withdraw.
     *  @param recipient_ The address of the recipient.
     */
    function withdrawCover(uint256 amount_, address recipient_) external;

    /**************************************************************************************************************************************/
    /*** LP Token View Functions                                                                                                        ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Returns the amount of exit shares for the input amount.
     *  @param  amount_  Address of the account.
     *  @return shares_  Amount of shares able to be exited.
     */
    function convertToExitShares(uint256 amount_) external view returns (uint256 shares_);

    /**
     *  @dev    Gets the information of escrowed shares.
     *  @param  owner_        The address of the owner of the shares.
     *  @param  shares_       The amount of shares to get the information of.
     *  @return escrowShares_ The amount of escrowed shares.
     *  @return destination_  The address of the destination.
     */
    function getEscrowParams(address owner_, uint256 shares_) external view returns (uint256 escrowShares_, address destination_);

    /**
     *  @dev   Gets the amount of assets that can be deposited.
     *  @param receiver_  The address to check the deposit for.
     *  @param maxAssets_ The maximum amount assets to deposit.
     */
    function maxDeposit(address receiver_) external view returns (uint256 maxAssets_);

    /**
     *  @dev   Gets the amount of shares that can be minted.
     *  @param receiver_  The address to check the mint for.
     *  @param maxShares_ The maximum amount shares to mint.
     */
    function maxMint(address receiver_) external view returns (uint256 maxShares_);

    /**
     *  @dev   Gets the amount of shares that can be redeemed.
     *  @param owner_     The address to check the redemption for.
     *  @param maxShares_ The maximum amount shares to redeem.
     */
    function maxRedeem(address owner_) external view returns (uint256 maxShares_);

    /**
     *  @dev   Gets the amount of assets that can be withdrawn.
     *  @param owner_     The address to check the withdraw for.
     *  @param maxAssets_ The maximum amount assets to withdraw.
     */
    function maxWithdraw(address owner_) external view returns (uint256 maxAssets_);

    /**
     *  @dev    Gets the amount of shares that can be redeemed.
     *  @param  owner_   The address to check the redemption for.
     *  @param  shares_  The amount of requested shares to redeem.
     *  @return assets_  The amount of assets that will be returned for `shares_`.
     */
    function previewRedeem(address owner_, uint256 shares_) external view returns (uint256 assets_);

    /**
     *  @dev    Gets the amount of assets that can be redeemed.
     *  @param  owner_   The address to check the redemption for.
     *  @param  assets_  The amount of requested shares to redeem.
     *  @return shares_  The amount of assets that will be returned for `assets_`.
     */
    function previewWithdraw(address owner_, uint256 assets_) external view returns (uint256 shares_);

    /**************************************************************************************************************************************/
    /*** View Functions                                                                                                                 ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Checks if a scheduled call can be executed.
     *  @param  functionId_   The function to check.
     *  @param  caller_       The address of the caller.
     *  @param  data_         The data of the call.
     *  @return canCall_      True if the call can be executed, false otherwise.
     *  @return errorMessage_ The error message if the call cannot be executed.
     */
    function canCall(bytes32 functionId_, address caller_, bytes memory data_)
        external view
        returns (bool canCall_, string memory errorMessage_);

    /**
     *  @dev    Gets the address of the globals.
     *  @return globals_ The address of the globals.
     */
    function globals() external view returns (address globals_);

    /**
     *  @dev    Gets the address of the governor.
     *  @return governor_ The address of the governor.
     */
    function governor() external view returns (address governor_);

    /**
     *  @dev    Returns if pool has sufficient cover.
     *  @return hasSufficientCover_ True if pool has sufficient cover.
     */
    function hasSufficientCover() external view returns (bool hasSufficientCover_);

    /**
     *  @dev    Returns the length of the `loanManagerList`.
     *  @return loanManagerListLength_ The length of the `loanManagerList`.
     */
    function loanManagerListLength() external view returns (uint256 loanManagerListLength_);

    /**
     *  @dev    Returns the amount of total assets.
     *  @return totalAssets_ Amount of of total assets.
     */
    function totalAssets() external view returns (uint256 totalAssets_);

    /**
     *  @dev    Returns the amount unrealized losses.
     *  @return unrealizedLosses_ Amount of unrealized losses.
     */
    function unrealizedLosses() external view returns (uint256 unrealizedLosses_);

}
MaplePoolManagerStorage.sol 35 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

import { IMaplePoolManagerStorage } from "../interfaces/IMaplePoolManagerStorage.sol";

abstract contract MaplePoolManagerStorage is IMaplePoolManagerStorage {

    uint256 internal _locked;  // Used when checking for reentrancy.

    address public override poolDelegate;
    address public override pendingPoolDelegate;

    address public override asset;
    address public override pool;

    address public override poolDelegateCover;
    address public override withdrawalManager;

    bool public override active;
    bool public override configured;
    
    bool __deprecated_openToPublic;

    uint256 public override liquidityCap;
    uint256 public override delegateManagementFeeRate;

    mapping(address => bool) public override isLoanManager;

    mapping(address => bool) __deprecated_isValidLender;

    address[] public override loanManagerList;

    address public override poolPermissionManager;

}
IMaplePoolManagerStorage.sol 86 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

interface IMaplePoolManagerStorage {

    /**
     *  @dev    Returns whether or not a pool is active.
     *  @return active_ True if the pool is active.
     */
    function active() external view returns (bool active_);

    /**
     *  @dev    Gets the address of the funds asset.
     *  @return asset_ The address of the funds asset.
     */
    function asset() external view returns (address asset_);

    /**
     *  @dev    Returns whether or not a pool is configured.
     *  @return configured_ True if the pool is configured.
     */
    function configured() external view returns (bool configured_);

    /**
     *  @dev    Gets the delegate management fee rate.
     *  @return delegateManagementFeeRate_ The value for the delegate management fee rate.
     */
    function delegateManagementFeeRate() external view returns (uint256 delegateManagementFeeRate_);

    /**
     *  @dev    Returns whether or not the given address is a loan manager.
     *  @param  loan_          The address of the loan.
     *  @return isLoanManager_ True if the address is a loan manager.
     */
    function isLoanManager(address loan_) external view returns (bool isLoanManager_);

    /**
     *  @dev    Gets the liquidity cap for the pool.
     *  @return liquidityCap_ The liquidity cap for the pool.
     */
    function liquidityCap() external view returns (uint256 liquidityCap_);

    /**
     *  @dev    Gets the address of the loan manager in the list.
     *  @param  index_       The index to get the address of.
     *  @return loanManager_ The address in the list.
     */
    function loanManagerList(uint256 index_) external view returns (address loanManager_);

    /**
     *  @dev    Gets the address of the pending pool delegate.
     *  @return pendingPoolDelegate_ The address of the pending pool delegate.
     */
    function pendingPoolDelegate() external view returns (address pendingPoolDelegate_);

    /**
     *  @dev    Gets the address of the pool.
     *  @return pool_ The address of the pool.
     */
    function pool() external view returns (address pool_);

    /**
     *  @dev    Gets the address of the pool delegate.
     *  @return poolDelegate_ The address of the pool delegate.
     */
    function poolDelegate() external view returns (address poolDelegate_);

    /**
     *  @dev    Gets the address of the pool delegate cover.
     *  @return poolDelegateCover_ The address of the pool delegate cover.
     */
    function poolDelegateCover() external view returns (address poolDelegateCover_);

    /**
     *  @dev    Gets the address of the pool delegate cover.
     *  @return poolPermissionManager_ The address of the pool permission manager.
     */
    function poolPermissionManager() external view returns (address poolPermissionManager_);

    /**
     *  @dev    Gets the address of the withdrawal manager.
     *  @return withdrawalManager_ The address of the withdrawal manager.
     */
    function withdrawalManager() external view returns (address withdrawalManager_);

}
IERC20Like.sol 13 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

/// @title Interface of the ERC20 standard as needed by ERC20Helper.
interface IERC20Like {

    function approve(address spender_, uint256 amount_) external returns (bool success_);

    function transfer(address recipient_, uint256 amount_) external returns (bool success_);

    function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_);

}
MapleProxiedInternals.sol 7 lines
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.7;

import { ProxiedInternals } from "../modules/proxy-factory/contracts/ProxiedInternals.sol";

/// @title A Maple implementation that is to be proxied, will need MapleProxiedInternals.
abstract contract MapleProxiedInternals is ProxiedInternals { }
IMapleProxied.sol 24 lines
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.7;

import { IProxied } from "../../modules/proxy-factory/contracts/interfaces/IProxied.sol";

/// @title A Maple implementation that is to be proxied, must implement IMapleProxied.
interface IMapleProxied is IProxied {

    /**
     *  @dev   The instance was upgraded.
     *  @param toVersion_ The new version of the loan.
     *  @param arguments_ The upgrade arguments, if any.
     */
    event Upgraded(uint256 toVersion_, bytes arguments_);

    /**
     *  @dev   Upgrades a contract implementation to a specific version.
     *         Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled.
     *  @param toVersion_ The version to upgrade to.
     *  @param arguments_ Some encoded arguments to use for the upgrade.
     */
    function upgrade(uint256 toVersion_, bytes calldata arguments_) external;

}
IMapleProxyFactory.sol 189 lines
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.7;

import { IDefaultImplementationBeacon } from "../../modules/proxy-factory/contracts/interfaces/IDefaultImplementationBeacon.sol";

/// @title A Maple factory for Proxy contracts that proxy MapleProxied implementations.
interface IMapleProxyFactory is IDefaultImplementationBeacon {

    /**************************************************************************************************************************************/
    /*** Events                                                                                                                         ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev   A default version was set.
     *  @param version_ The default version.
     */
    event DefaultVersionSet(uint256 indexed version_);

    /**
     *  @dev   A version of an implementation, at some address, was registered, with an optional initializer.
     *  @param version_               The version registered.
     *  @param implementationAddress_ The address of the implementation.
     *  @param initializer_           The address of the initializer, if any.
     */
    event ImplementationRegistered(uint256 indexed version_, address indexed implementationAddress_, address indexed initializer_);

    /**
     *  @dev   A proxy contract was deployed with some initialization arguments.
     *  @param version_                 The version of the implementation being proxied by the deployed proxy contract.
     *  @param instance_                The address of the proxy contract deployed.
     *  @param initializationArguments_ The arguments used to initialize the proxy contract, if any.
     */
    event InstanceDeployed(uint256 indexed version_, address indexed instance_, bytes initializationArguments_);

    /**
     *  @dev   A instance has upgraded by proxying to a new implementation, with some migration arguments.
     *  @param instance_           The address of the proxy contract.
     *  @param fromVersion_        The initial implementation version being proxied.
     *  @param toVersion_          The new implementation version being proxied.
     *  @param migrationArguments_ The arguments used to migrate, if any.
     */
    event InstanceUpgraded(address indexed instance_, uint256 indexed fromVersion_, uint256 indexed toVersion_, bytes migrationArguments_);

    /**
     *  @dev   The MapleGlobals was set.
     *  @param mapleGlobals_ The address of a Maple Globals contract.
     */
    event MapleGlobalsSet(address indexed mapleGlobals_);

    /**
     *  @dev   An upgrade path was disabled, with an optional migrator contract.
     *  @param fromVersion_ The starting version of the upgrade path.
     *  @param toVersion_   The destination version of the upgrade path.
     */
    event UpgradePathDisabled(uint256 indexed fromVersion_, uint256 indexed toVersion_);

    /**
     *  @dev   An upgrade path was enabled, with an optional migrator contract.
     *  @param fromVersion_ The starting version of the upgrade path.
     *  @param toVersion_   The destination version of the upgrade path.
     *  @param migrator_    The address of the migrator, if any.
     */
    event UpgradePathEnabled(uint256 indexed fromVersion_, uint256 indexed toVersion_, address indexed migrator_);

    /**************************************************************************************************************************************/
    /*** State Variables                                                                                                                ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev The default version.
     */
    function defaultVersion() external view returns (uint256 defaultVersion_);

    /**
     *  @dev The address of the MapleGlobals contract.
     */
    function mapleGlobals() external view returns (address mapleGlobals_);

    /**
     *  @dev    Whether the upgrade is enabled for a path from a version to another version.
     *  @param  toVersion_   The initial version.
     *  @param  fromVersion_ The destination version.
     *  @return allowed_     Whether the upgrade is enabled.
     */
    function upgradeEnabledForPath(uint256 toVersion_, uint256 fromVersion_) external view returns (bool allowed_);

    /**************************************************************************************************************************************/
    /*** State Changing Functions                                                                                                       ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Deploys a new instance proxying the default implementation version, with some initialization arguments.
     *          Uses a nonce and `msg.sender` as a salt for the CREATE2 opcode during instantiation to produce deterministic addresses.
     *  @param  arguments_ The initialization arguments to use for the instance deployment, if any.
     *  @param  salt_      The salt to use in the contract creation process.
     *  @return instance_  The address of the deployed proxy contract.
     */
    function createInstance(bytes calldata arguments_, bytes32 salt_) external returns (address instance_);

    /**
     *  @dev   Enables upgrading from a version to a version of an implementation, with an optional migrator.
     *         Only the Governor can call this function.
     *  @param fromVersion_ The starting version of the upgrade path.
     *  @param toVersion_   The destination version of the upgrade path.
     *  @param migrator_    The address of the migrator, if any.
     */
    function enableUpgradePath(uint256 fromVersion_, uint256 toVersion_, address migrator_) external;

    /**
     *  @dev   Disables upgrading from a version to a version of a implementation.
     *         Only the Governor can call this function.
     *  @param fromVersion_ The starting version of the upgrade path.
     *  @param toVersion_   The destination version of the upgrade path.
     */
    function disableUpgradePath(uint256 fromVersion_, uint256 toVersion_) external;

    /**
     *  @dev   Registers the address of an implementation contract as a version, with an optional initializer.
     *         Only the Governor can call this function.
     *  @param version_               The version to register.
     *  @param implementationAddress_ The address of the implementation.
     *  @param initializer_           The address of the initializer, if any.
     */
    function registerImplementation(uint256 version_, address implementationAddress_, address initializer_) external;

    /**
     *  @dev   Sets the default version.
     *         Only the Governor can call this function.
     *  @param version_ The implementation version to set as the default.
     */
    function setDefaultVersion(uint256 version_) external;

    /**
     *  @dev   Sets the Maple Globals contract.
     *         Only the Governor can call this function.
     *  @param mapleGlobals_ The address of a Maple Globals contract.
     */
    function setGlobals(address mapleGlobals_) external;

    /**
     *  @dev   Upgrades the calling proxy contract's implementation, with some migration arguments.
     *  @param toVersion_ The implementation version to upgrade the proxy contract to.
     *  @param arguments_ The migration arguments, if any.
     */
    function upgradeInstance(uint256 toVersion_, bytes calldata arguments_) external;

    /**************************************************************************************************************************************/
    /*** View Functions                                                                                                                 ***/
    /**************************************************************************************************************************************/

    /**
     *  @dev    Returns the deterministic address of a potential proxy, given some arguments and salt.
     *  @param  arguments_       The initialization arguments to be used when deploying the proxy.
     *  @param  salt_            The salt to be used when deploying the proxy.
     *  @return instanceAddress_ The deterministic address of a potential proxy.
     */
    function getInstanceAddress(bytes calldata arguments_, bytes32 salt_) external view returns (address instanceAddress_);

    /**
     *  @dev    Returns the address of an implementation version.
     *  @param  version_        The implementation version.
     *  @return implementation_ The address of the implementation.
     */
    function implementationOf(uint256 version_) external view returns (address implementation_);

    /**
     *  @dev    Returns if a given address has been deployed by this factory/
     *  @param  instance_   The address to check.
     *  @return isInstance_ A boolean indication if the address has been deployed by this factory.
     */
    function isInstance(address instance_) external view returns (bool isInstance_);

    /**
     *  @dev    Returns the address of a migrator contract for a migration path (from version, to version).
     *          If oldVersion_ == newVersion_, the migrator is an initializer.
     *  @param  oldVersion_ The old version.
     *  @param  newVersion_ The new version.
     *  @return migrator_   The address of a migrator contract.
     */
    function migratorForPath(uint256 oldVersion_, uint256 newVersion_) external view returns (address migrator_);

    /**
     *  @dev    Returns the version of an implementation contract.
     *  @param  implementation_ The address of an implementation contract.
     *  @return version_        The version of the implementation contract.
     */
    function versionOf(address implementation_) external view returns (uint256 version_);

}
ProxiedInternals.sol 50 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

import { SlotManipulatable } from "./SlotManipulatable.sol";

/// @title An implementation that is to be proxied, will need ProxiedInternals.
abstract contract ProxiedInternals is SlotManipulatable {

    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.factory') - 1`.
    bytes32 private constant FACTORY_SLOT = bytes32(0x7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af1);

    /// @dev Storage slot with the address of the current factory. `keccak256('eip1967.proxy.implementation') - 1`.
    bytes32 private constant IMPLEMENTATION_SLOT = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);

    /// @dev Delegatecalls to a migrator contract to manipulate storage during an initialization or migration.
    function _migrate(address migrator_, bytes calldata arguments_) internal virtual returns (bool success_) {
        uint256 size;

        assembly {
            size := extcodesize(migrator_)
        }

        if (size == uint256(0)) return false;

        ( success_, ) = migrator_.delegatecall(arguments_);
    }

    /// @dev Sets the factory address in storage.
    function _setFactory(address factory_) internal virtual returns (bool success_) {
        _setSlotValue(FACTORY_SLOT, bytes32(uint256(uint160(factory_))));
        return true;
    }

    /// @dev Sets the implementation address in storage.
    function _setImplementation(address implementation_) internal virtual returns (bool success_) {
        _setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(implementation_))));
        return true;
    }

    /// @dev Returns the factory address.
    function _factory() internal view virtual returns (address factory_) {
        return address(uint160(uint256(_getSlotValue(FACTORY_SLOT))));
    }

    /// @dev Returns the implementation address.
    function _implementation() internal view virtual returns (address implementation_) {
        return address(uint160(uint256(_getSlotValue(IMPLEMENTATION_SLOT))));
    }

}
SlotManipulatable.sol 22 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

abstract contract SlotManipulatable {

    function _getReferenceTypeSlot(bytes32 slot_, bytes32 key_) internal pure returns (bytes32 value_) {
        return keccak256(abi.encodePacked(key_, slot_));
    }

    function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) {
        assembly {
            value_ := sload(slot_)
        }
    }

    function _setSlotValue(bytes32 slot_, bytes32 value_) internal {
        assembly {
            sstore(slot_, value_)
        }
    }

}
IProxied.sol 31 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

/// @title An implementation that is to be proxied, must implement IProxied.
interface IProxied {

    /**
     *  @dev The address of the proxy factory.
     */
    function factory() external view returns (address factory_);

    /**
     *  @dev The address of the implementation contract being proxied.
     */
    function implementation() external view returns (address implementation_);

    /**
     *  @dev   Modifies the proxy's implementation address.
     *  @param newImplementation_ The address of an implementation contract.
     */
    function setImplementation(address newImplementation_) external;

    /**
     *  @dev   Modifies the proxy's storage by delegate-calling a migrator contract with some arguments.
     *         Access control logic critical since caller can force a selfdestruct via a malicious `migrator_` which is delegatecalled.
     *  @param migrator_  The address of a migrator contract.
     *  @param arguments_ Some encoded arguments to use for the migration.
     */
    function migrate(address migrator_, bytes calldata arguments_) external;

}
IDefaultImplementationBeacon.sol 10 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.7;

/// @title An beacon that provides a default implementation for proxies, must implement IDefaultImplementationBeacon.
interface IDefaultImplementationBeacon {

    /// @dev The address of an implementation for proxies.
    function defaultImplementation() external view returns (address defaultImplementation_);

}

Read Contract

HUNDRED_PERCENT 0x6ed93dd0 → uint256
active 0x02fb0c5e → bool
asset 0x38d52e0f → address
canCall 0x7bd243de → bool, string
configured 0x8772a23a → bool
convertToExitShares 0xa58c3eff → uint256
delegateManagementFeeRate 0x5dd28449 → uint256
factory 0xc45a0155 → address
getEscrowParams 0x5cf2ed57 → uint256, address
globals 0xc3124525 → address
governor 0x0c340a24 → address
hasSufficientCover 0xcaf901dd → bool
implementation 0x5c60da1b → address
isLoanManager 0xf4070e2d → bool
liquidityCap 0x76687d3d → uint256
loanManagerList 0xfae8ed3d → address
loanManagerListLength 0xba321f9f → uint256
maxDeposit 0x402d267d → uint256
maxMint 0xc63d75b6 → uint256
maxRedeem 0xd905777e → uint256
maxWithdraw 0xce96cb77 → uint256
pendingPoolDelegate 0x02db6cd3 → address
pool 0x16f0115b → address
poolDelegate 0x4046af2b → address
poolDelegateCover 0xab42685c → address
poolPermissionManager 0xe15e990a → address
previewRedeem 0xcbe52ae3 → uint256
previewWithdraw 0xbbc6f1dc → uint256
totalAssets 0x01e1d114 → uint256
unrealizedLosses 0x67e2ba23 → uint256
withdrawalManager 0x82fe535a → address

Write Contract 23 functions

These functions modify contract state and require a wallet transaction to execute.

acceptPoolDelegate 0x19e9cd7b
No parameters
addLoanManager 0x3b35e804
address loanManagerFactory_
returns: address
completeConfiguration 0x3291f012
No parameters
depositCover 0x8b1c4990
uint256 amount_
finishCollateralLiquidation 0x9e5df6c2
address loan_
migrate 0xc3fbb6fd
address migrator_
bytes arguments_
processRedeem 0x60af6ad3
uint256 shares_
address owner_
address sender_
returns: uint256, uint256
processWithdraw 0xe345f4b6
uint256 assets_
address owner_
address sender_
returns: uint256, uint256
removeShares 0x1b8f1830
uint256 shares_
address owner_
returns: uint256
requestFunds 0x494666b6
address destination_
uint256 principal_
requestRedeem 0x7d41c86e
uint256 shares_
address owner_
address sender_
requestWithdraw 0xd4dd0438
uint256 shares_
uint256 assets_
address owner_
address sender_
setActive 0xacec338a
bool active_
setDelegateManagementFeeRate 0x87c2f4ae
uint256 delegateManagementFeeRate_
setImplementation 0xd784d426
address implementation_
setIsLoanManager 0x4148c5e5
address loanManager_
bool isLoanManager_
setLiquidityCap 0x7b99adb1
uint256 liquidityCap_
setPendingPoolDelegate 0xd7c0ca48
address pendingPoolDelegate_
setPoolPermissionManager 0x2ebada04
address poolPermissionManager_
setWithdrawalManager 0xfc72ed5b
address withdrawalManager_
triggerDefault 0x40504ba0
address loan_
address liquidatorFactory_
upgrade 0x3b99bcee
uint256 version_
bytes arguments_
withdrawCover 0x26af24b7
uint256 amount_
address recipient_

Recent Transactions

No transactions found for this address