Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x08e820Fb5ba163a4174ED401b6b7F1Fe29987242
Balance 0 ETH
Nonce 1
Code Size 21887 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

21887 bytes
0x608060405234801561001057600080fd5b50600436106103db5760003560e01c806375d264131161020a578063b187bd2611610125578063dbf110a7116100b8578063e4ae9af711610087578063e4ae9af7146108ed578063e655dbd814610900578063f6fc84d214610913578063fc147d4a14610926578063ff85a2ba1461093957600080fd5b8063dbf110a714610892578063dd62ed3e146108a5578063dde43cba146108de578063e3161ddd146108e557600080fd5b8063c964a2f2116100f4578063c964a2f214610851578063d299398314610864578063d505accf1461086c578063d7020d0a1461087f57600080fd5b8063b187bd2614610804578063b1bf962d14610816578063b6fe2e9c1461081e578063b9844d8d1461083157600080fd5b806395d89b411161019d578063a8346a8c1161016c578063a8346a8c1461078f578063a9059cbb146107cd578063a9dd7702146107e0578063b16a19de146107f357600080fd5b806395d89b41146107645780639c7697871461076c5780639cfa776814610774578063a457c2d71461077c57600080fd5b80637ecebe00116101d95780637ecebe00146106e35780637fcea80e1461070c5780638abc37d31461071f57806392efda791461075357600080fd5b806375d2641314610697578063781603761461069d5780637c6ad541146106bd5780637df5bd3b146106d057600080fd5b80633644e515116102fa5780634efecaa51161028d578063679aefce1161025c578063679aefce146106585780636ea9ba541461066057806370a08231146106735780637535d2461461068657600080fd5b80634efecaa51461061757806355f4f1971461062a578063568ed0ed1461063257806359e67e921461064557600080fd5b80633b19e84a116102c95780633b19e84a146105ab5780634794c1d1146105d05780634800df8c146105e35780634d25c4f1146105f657600080fd5b80633644e5151461056757806337a926261461057057806339509351146105835780633a7d40891461059657600080fd5b80631dd0f483116103725780632f8dc4ea116103415780632f8dc4ea146105055780633079fac21461051857806330adf81f1461052b578063313ce5671461055257600080fd5b80631dd0f483146104b957806320531b17146104cc57806323b872dd146104df578063296637ce146104f257600080fd5b80630ca2103d116103ae5780630ca2103d1461045f57806316c38b3c1461048957806318160ddd1461049e5780631da24f3e146104a657600080fd5b806306fdde03146103e05780630746363d146103fe578063095ea7b3146104145780630afbcdc914610437575b600080fd5b6103e861096e565b6040516103f59190615262565b60405180910390f35b610406610a00565b6040519081526020016103f5565b610427610422366004614dfd565b610a15565b60405190151581526020016103f5565b61044a610445366004614b91565b610a2c565b604080519283526020830191909152016103f5565b61047261046d3660046150e9565b610a49565b6040805192151583526020830191909152016103f5565b61049c610497366004614f23565b610a9d565b005b610406610b17565b6104066104b4366004614b91565b610b49565b61049c6104c7366004614b91565b610bb1565b6104066104da366004614c9b565b610bbc565b6104276104ed366004614c01565b610d00565b61049c610500366004614b91565b610d2a565b61049c610513366004614b91565b610d71565b61049c610526366004614b91565b610d9e565b6104067f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460405160ff90911681526020016103f5565b61040660105481565b61049c61057e366004614f5b565b610dba565b610427610591366004614dfd565b610ea8565b61059e610ee4565b6040516103f591906152a2565b6013546001600160a01b03165b6040516001600160a01b0390911681526020016103f5565b6104066105de366004614c41565b610f6d565b61049c6105f13660046150cf565b6111c5565b600a54600160a01b900461ffff1660405161ffff90911681526020016103f5565b610406610625366004614dfd565b6111d6565b6104066111fd565b61049c610640366004614c01565b61120c565b610427610653366004614d32565b611349565b6104066114e8565b61049c61066e366004614dfd565b6114f2565b610406610681366004614b91565b611571565b6003546001600160a01b03166105b8565b306105b8565b6103e8604051806040016040528060018152602001603160f81b81525081565b61049c6106cb366004614e28565b6115a7565b61049c6106de366004615119565b6116a9565b6104066106f1366004614b91565b6001600160a01b031660009081526011602052604090205490565b61042761071a366004614dfd565b61174e565b61073261072d366004614eee565b611774565b60408051938452602084019290925263ffffffff16908201526060016103f5565b600a546001600160a01b03166105b8565b6103e86117ad565b61049c6117bc565b6104066118ae565b61042761078a366004614dfd565b611932565b6107a261079d366004614ea7565b611958565b6040805194855263ffffffff90931660208501529015159183019190915260608201526080016103f5565b6104276107db366004614dfd565b611984565b6104066107ee366004614b91565b611994565b6004546001600160a01b03166105b8565b600a54600160b01b900460ff16610427565b6104066119aa565b61049c61082c366004614bc9565b6119c1565b61040661083f366004614b91565b60116020526000908152604090205481565b61040661085f366004614b91565b6119d1565b6103e8611a75565b61049c61087a366004614d90565b611a7f565b61049c61088d366004614ced565b611cb1565b6104276108a0366004614e69565b611dd6565b6104066108b3366004614bc9565b6001600160a01b03918216600090815260126020908152604080832093909416825291909152205490565b6001610406565b61049c611ebb565b61049c6108fb366004614f93565b611fb1565b61049c61090e366004614b91565b6121ca565b61049c6109213660046150cf565b61220e565b61049c610934366004614c01565b61221f565b61094c610947366004614b91565b6122ec565b6040805193845263ffffffff90921660208401521515908201526060016103f5565b60606000805461097d90615458565b80601f01602080910402602001604051908101604052809291908181526020018280546109a990615458565b80156109f65780601f106109cb576101008083540402835291602001916109f6565b820191906000526020600020905b8154815290600101906020018083116109d957829003601f168201915b5050505050905090565b6000610a0a61231a565b50600090565b905090565b6000610a22338484612361565b5060015b92915050565b600080610a3883610b49565b610a406119aa565b91509150915091565b600080610a5461231a565b600a54600160a01b900461ffff16610a70576000610a40612485565b600a54610a89908490600160a01b900461ffff16612499565b9050610a948161258e565b60019150915091565b610aa56125d6565b600a5460ff600160b01b90910416151581151514610add57600a805460ff60b01b1916600160b01b83151502179055610add81612610565b604051811515815233907facaf4ee8e6a4949ca96787d73dfff5165ff2c555b2304b8517dc5396053add859060200160405180910390a250565b600080610b226119aa565b905080610b3157600091505090565b610b43610b3c6118ae565b8290612681565b91505090565b6000806000610b5784612728565b915091508160001415610b6e575060009392505050565b60018116610b7d575092915050565b6001600160a01b0384166000908152600c6020526040902054610ba9906001600160801b0316836153f0565b949350505050565b610bb9612753565b50565b6000610bc86001612795565b506040805180820190915260028152610c8d60f21b60208201526001600160a01b038516610c125760405162461bcd60e51b8152600401610c099190615262565b60405180910390fd5b50610c1e8585856127df565b6000610c2b858585612880565b9050610c36856129fa565b6000610c406118ae565b9050610c4e87868484612a4f565b508115610ca6576001600160a01b038087169088167f8fa239a1e4aab173da7c904daf25554507cccda331d369776d5b993d09856913610c8e8585612681565b60408051918252602082018690520160405180910390a35b6001600160a01b038087169088167ff27157c1edda26e69405c87bb533c005675f37b9dbc744fe439508d6082a681a610cdf8885612681565b60408051918252602082018690520160405180910390a35095945050505050565b6000610d15848484610d106118ae565b612aee565b610d1f8483612bc3565b5060015b9392505050565b60408051808201909152600280825261333360f01b602083015254610d66916101009091046001600160a01b0316903390630102002290612be7565b610bb9816006612c11565b610d79612c90565b610bb9816001600160a01b03166000908152600b60205260409020805460ff19169055565b610da6612c90565b610bb9816001612c11565b60025460ff1690565b60408051808201909152600280825261383160f01b602083015254610df5916101009091046001600160a01b03169033906280000890612be7565b6000610e046020830183614b91565b6001600160a01b03161415610e1857600080fd5b6000610e2c600a546001600160a01b031690565b6001600160a01b031614610e3f57600080fd5b610bb9610e4f6020830183614b91565b6000610e6160608501604086016150cf565b610e6e60208601866152ea565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ccb92505050565b3360008181526012602090815260408083206001600160a01b03871684529091528120549091610a22918590610edf90869061535a565b612361565b610f15604051806060016040528060006001600160a01b0316815260200160608152602001600061ffff1681525090565b6040518060600160405280610f32600a546001600160a01b031690565b6001600160a01b03168152602001610f48611a75565b8152602001610f62600a5461ffff600160a01b9091041690565b61ffff169052919050565b6000610f796001612795565b506040805180820190915260028152610c8d60f21b60208201526001600160a01b038616610fba5760405162461bcd60e51b8152600401610c099190615262565b50610fc68686866127df565b826001600160a01b0316866001600160a01b031614610ff957610fea8386846127df565b610ff48383612d08565b611009565b81841415611009575060006111bc565b60008060008487111561103b57848703915061102788836001612880565b92508282111561103657508181035b611052565b848710156110525786850391506110528883612d1b565b600061105c6118ae565b90506001600160a01b03808a16908b167ff27157c1edda26e69405c87bb533c005675f37b9dbc744fe439508d6082a681a6110978b85612681565b60408051918252602082018690520160405180910390a36000876001600160a01b03168b6001600160a01b0316146110dc576110d58b8a8785612a4f565b90506110fa565b868911156110f0576110d58b858785612a4f565b6110fa8885612d08565b8415611151576001600160a01b03808b16908c167f8fa239a1e4aab173da7c904daf25554507cccda331d369776d5b993d098569136111398886612681565b60408051918252602082018790520160405180910390a35b6001600160a01b03808b169089167f0e67a82cb7e9046df2eee608616b86ba3edb690a51a7b7f319f063487009e04b61118a8a86612681565b60408051918252602082018790520160405180910390a382156111b4576111b48b8b858486612e05565b509293505050505b95945050505050565b6111cd61231a565b610bb981612ec2565b60006111e0612f78565b6004546111f7906001600160a01b03168484612fbd565b50919050565b600061120761231a565b610a0a565b6112166003612795565b506001600160a01b03831615158061123657506001600160a01b03821615155b604051806040016040528060028152602001610c8d60f21b8152509061126f5760405162461bcd60e51b8152600401610c099190615262565b508061127a57505050565b60006112846118ae565b905060006112928383612681565b90506112a18584600085612a4f565b5060408051828152602081018490526001600160a01b038716917fbc4d0c2bf768c62cfe8d78ea0cf813ceeb7618df3b84168ea28734d8018d9ab1910160405180910390a26112f4858585600086612e05565b6112fe848461300f565b60408051828152602081018490526001600160a01b038616917f3bdc716e946aad9ffa957102a90584d57dd1cf714d0aa06a36e571795fc0349e910160405180910390a25050505050565b6000611353612f78565b600061135f8585613103565b9050806113705760009150506111bc565b60008061138089898589896131d9565b91509150841561143e5761139689848389613388565b6004546113ad906001600160a01b03168989612fbd565b6040518781526000906001600160a01b038b16906000805160206155058339815191529060200160405180910390a3876001600160a01b0316896001600160a01b03167f5d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2898960405161142a929190918252602082015260400190565b60405180910390a3600093505050506111bc565b61144b898985848a61340f565b876001600160a01b0316896001600160a01b03166000805160206155058339815191528960405161147e91815260200190565b60405180910390a3876001600160a01b0316896001600160a01b03167f4beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda866689896040516114d4929190918252602082015260400190565b60405180910390a350979650505050505050565b6000610a10612485565b6114fc6002612795565b50611509826000836127df565b6115138282612d08565b600061151d6118ae565b90506001600160a01b0383167f3bdc716e946aad9ffa957102a90584d57dd1cf714d0aa06a36e571795fc0349e6115548484612681565b6040805191825260208201859052015b60405180910390a2505050565b60008061157d83610b49565b90508061158d5750600092915050565b610d236115986118ae565b6115a185610b49565b90612681565b60006115b36002612795565b90506115c1846000856127df565b60006115cb6118ae565b905060006115dc8686600085612a4f565b90506001600160a01b0386167fbc4d0c2bf768c62cfe8d78ea0cf813ceeb7618df3b84168ea28734d8018d9ab16116138785612681565b60408051918252602082018690520160405180910390a26001600160a01b038416158015906116545750856001600160a01b0316846001600160a01b031614155b156116a157604080518082019091526002815261033360f41b6020820152600484166116935760405162461bcd60e51b8152600401610c099190615262565b506116a18685878486612e05565b505050505050565b6116b1612f78565b816116ba575050565b6013546001600160a01b03166116da816116d48585613103565b84613505565b6040518381526001600160a01b038216906000906000805160206155058339815191529060200160405180910390a360408051848152602081018490526001600160a01b038316917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9101611564565b5050565b6000610a228333846040518060600160405280602581526020016155256025913961357c565b60008060004263ffffffff168463ffffffff16101561179257600080fd5b61179c85856135d2565b9093506000925090505b9250925092565b60606001805461097d90615458565b6117c4612c90565b600254604051635c9fcd8560e11b815262080000600482015260009161010090046001600160a01b03169063b93f9b0a9060240160206040518083038186803b15801561181057600080fd5b505afa158015611824573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118489190614bad565b6040805180820190915260028152610dcd60f21b60208201529091506001600160a01b03821661188b5760405162461bcd60e51b8152600401610c099190615262565b50601380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546004805460405163d15e005360e01b81526001600160a01b0391821692810192909252600092169063d15e00539060240160206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a109190615101565b6000610a223384846040518060600160405280602581526020016155256025913961357c565b60008060008061196661231a565b611972888888886135eb565b929b919a509850909650945050505050565b6000610a22338484610d106118ae565b6000610a266119a16118ae565b6115a18461363c565b6000600e546119b7613657565b610a1091906153f0565b6119c9612753565b61174a613661565b60008060006119df84612728565b90925090506001811615611a1c576001600160a01b0384166000908152600c6020526040902054611a19906001600160801b0316836153f0565b91505b6004811615611a54576001600160a01b0384166000908152600d6020526040902054611a51906001600160801b03168361535a565b91505b81611a63575060009392505050565b610ba9611a6e6118ae565b8390612681565b6060610a106117ad565b6001600160a01b038716611ac55760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b6044820152606401610c09565b83421115611b0a5760405162461bcd60e51b815260206004820152601260248201527124a72b20a624a22fa2ac2824a920aa24a7a760711b6044820152606401610c09565b6001600160a01b0387811660008181526011602090815260408083205460105482517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958c166060860152608085018b905260a0850181905260c08086018b90528251808703909101815260e086019092528151919092012061190160f01b610100850152610102840194909452610122830193909352906101420160408051601f1981840301815282825280516020918201206000845290830180835281905260ff8816918301919091526060820186905260808201859052915060019060a0016020604051602081039080840390855afa158015611c19573d6000803e3d6000fd5b505050602060405103516001600160a01b0316896001600160a01b031614611c775760405162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b6044820152606401610c09565b611c8282600161535a565b6001600160a01b038a16600090815260116020526040902055611ca6898989613697565b505050505050505050565b611cb9612f78565b6000611cc58383613103565b60408051808201909152600281526106a760f31b602082015290915081611cff5760405162461bcd60e51b8152600401610c099190615262565b50611d338582611d2d886001600160a01b03166000908152600c60205260409020546001600160801b031690565b85613388565b600454611d4a906001600160a01b03168585612fbd565b6040518381526000906001600160a01b038716906000805160206155058339815191529060200160405180910390a3836001600160a01b0316856001600160a01b03167f5d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa28585604051611dc7929190918252602082015260400190565b60405180910390a35050505050565b6000611de0612f78565b6000611dec8585613103565b6040805180820190915260028152611a9b60f11b602082015290915081611e265760405162461bcd60e51b8152600401610c099190615262565b50611e328682856136a2565b9150611e3f868286613505565b6040518581526001600160a01b038716906000906000805160206155058339815191529060200160405180910390a360408051868152602081018690526001600160a01b038816917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250949350505050565b611ec3612c90565b6000600260019054906101000a90046001600160a01b03166001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f1357600080fd5b505afa158015611f27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4b9190614bad565b604080518082019091526002815261064760f31b60208201529091506001600160a01b038216611f8e5760405162461bcd60e51b8152600401610c099190615262565b50600380546001600160a01b0319166001600160a01b0392909216919091179055565b60016000806000611fc1846137f7565b92509250925080611fd25760158490555b611fdf6001601454101590565b15612065576120608a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525061205b9250610db1915050565b613a6d565b61210d565b6120f48a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600081840152601f19601f820116905080830192505050505050508d606001602081019061205b919061513a565b61210d612106368d90038d018d615041565b8787613aad565b61211a60208c018c614b91565b6001600160a01b031661213360608d0160408e01614b91565b6001600160a01b03167f2bb6ce244a49e83b442fa9c0617811f0929cb9961fd5ce013ebf708dc4d8bf028d60200160208101906121709190614b91565b61217861096e565b6121806117ad565b60025460ff168c8c60405161219a9695949392919061519c565b60405180910390a3806121ad5760148490555b816121bd57601483905560006015555b5050505050505050505050565b60408051808201909152600280825261383160f01b602083015254612205916101009091046001600160a01b03169033906280000890612be7565b610bb981613b67565b612216612c90565b610bb981613b6f565b6122296001612795565b506040805180820190915260028152610c8d60f21b60208201526001600160a01b03831661226a5760405162461bcd60e51b8152600401610c099190615262565b506122768383836127df565b6122808382612d08565b61228a8282612d1b565b60006122946118ae565b90506001600160a01b038084169085167f0e67a82cb7e9046df2eee608616b86ba3edb690a51a7b7f319f063487009e04b6122cf8585612681565b60408051918252602082018690520160405180910390a350505050565b60008060006122f961231a565b61230284613bb2565b9250925092505b9193909250565b610bb98142613bc0565b600a546001600160a01b0316331460405180604001604052806002815260200161039360f41b81525090610bb95760405162461bcd60e51b8152600401610c099190615262565b6001600160a01b0383166123c35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c09565b6001600160a01b0382166124245760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c09565b6001600160a01b0383811660008181526012602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610a106007546001600160e01b031690565b60008215806124a6575081155b156124b357506000610a26565b8160026124c2600160646153a7565b6124cd9060646153a7565b6124d79190615372565b6124e79061ffff166000196153f0565b6124f19190615393565b83111560405180604001604052806002815260200161068760f31b8152509061252d5760405162461bcd60e51b8152600401610c099190615262565b5061253a600160646153a7565b6125459060646153a7565b61ffff166002612557600160646153a7565b6125629060646153a7565b61256c9190615372565b61ffff1661257a84866153d1565b612584919061535a565b610d239190615393565b612596613c48565b61259f81613c99565b6040518181527fe65c987b2e4668e09ba867026921588005b2b2063607a1e7e7d91683c8f91b7b906020015b60405180910390a150565b60025461260e9061010090046001600160a01b0316336001604051806040016040528060028152602001611b9b60f11b815250612be7565b565b60035460048054604051631be090a560e01b81526001600160a01b0391821692810192909252831515602483015290911690631be090a5906044015b600060405180830381600087803b15801561266657600080fd5b505af115801561267a573d6000803e3d6000fd5b5050505050565b600082158061268e575081155b1561269b57506000610a26565b816126b360026b033b2e3c9fd0803ce8000000615393565b6126bf906000196153f0565b6126c99190615393565b83111560405180604001604052806002815260200161068760f31b815250906127055760405162461bcd60e51b8152600401610c099190615262565b506b033b2e3c9fd0803ce800000061271e600282615393565b61257a84866153d1565b600080600061273684613ca2565b80516020909101516001600160c01b039091169590945092505050565b61275c33613d0e565b60405180604001604052806002815260200161383160f01b81525090610bb95760405162461bcd60e51b8152600401610c099190615262565b60006127a033613da3565b604080518082019091526002815261033360f41b602082015290915060ff838316166111f75760405162461bcd60e51b8152600401610c099190615262565b6040805180820190915260028152610c8d60f21b6020820152816128165760405162461bcd60e51b8152600401610c099190615262565b506001600160a01b038316158015906128415750816001600160a01b0316836001600160a01b031614155b604051806040016040528060028152602001610c8d60f21b8152509061287a5760405162461bcd60e51b8152600401610c099190615262565b50505050565b6001600160a01b0383166000908152600d602090815260408083208151808301909252546001600160801b038082168352600160801b909104169181018290529015801590612908575080516001600160801b031684118061290857508280156129085750600f546128f790859061ffff16612499565b81602001516001600160801b031610155b15612971578381602001516001600160801b03161115612942576020810180518590036001600160801b0390811690915284169150612959565b60208101805160009091526001600160801b031691505b81600e600082825461296b91906153f0565b90915550505b61297b82856153f0565b815161299091906001600160801b03166153f0565b6001600160801b0390811682526001600160a01b0386166000908152600d602090815260409091208351918401518316600160801b02919092169081179091556129f25760006129df86612728565b9150506129f0866004198316613de6565b505b509392505050565b60035460048054604051631cf0066360e01b81526001600160a01b0391821692810192909252838116602483018190526044830152600060648301819052608483015290911690631cf006639060a40161264c565b6001600160a01b0384166000908152600c60205260408120548190612a7e9086906001600160801b03166153f0565b90508315612a9257612a9286858386613388565b6001600160a01b0386166000908152600c6020526040902080546001600160801b0319166001600160801b038316179055806111bc576000612ad387612728565b915050612ae4876001198316613de6565b5095945050505050565b6000612afa8383613103565b9050600080612b0887612728565b63ffffffff1691509150612b29878785612b228b86613e1e565b8887613e62565b856001600160a01b0316876001600160a01b031660008051602061550583398151915287604051612b5c91815260200190565b60405180910390a3856001600160a01b0316876001600160a01b03167f4beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda86668787604051612bb2929190918252602082015260400190565b60405180910390a350505050505050565b61174a8233836040518060600160405280602881526020016154dd6028913961357c565b612bf2848484613f28565b819061267a5760405162461bcd60e51b8152600401610c099190615262565b6001600160a01b038216612c5d5760405162461bcd60e51b81526020600482015260136024820152721859191c995cdcc81a5cc81c995c5d5a5c9959606a1b6044820152606401610c09565b6001600160a01b03919091166000908152600b60205260409020805460ff19811660ff9182169190931617919091179055565b60408051808201909152600280825261333360f01b60208301525461260e916101009091046001600160a01b03169033906202000290612be7565b600a80546001600160a01b0319166001600160a01b03861617905561ffff821615612cf957612cf982612ec2565b821561287a5761287a8361258e565b612d12828261300f565b61174a826129fa565b6000612d2683612728565b60408051808201909152600280825261323360f01b602083015291935091508216612d645760405162461bcd60e51b8152600401610c099190615262565b506001600160a01b0383166000908152600d6020526040902054612d91906001600160801b03168361535a565b91506001600160801b03821115612dba5760405162461bcd60e51b8152600401610c0990615275565b6001600160a01b0383166000908152600d6020526040902080546001600160801b0319166001600160801b03841617905560048116612e0057612e008360048317613de6565b505050565b612e1b8585858585612e168b61363c565b613e62565b6000612e278483612681565b9050846001600160a01b0316866001600160a01b031660008051602061550583398151915283604051612e5c91815260200190565b60405180910390a3846001600160a01b0316866001600160a01b03167f4beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda86668385604051612eb2929190918252602082015260400190565b60405180910390a3505050505050565b612eca613c48565b612ed6600160646153a7565b612ee19060646153a7565b61ffff168161ffff161115612f285760405162461bcd60e51b815260206004820152600d60248201526c696c6c6567616c2076616c756560981b6044820152606401610c09565b600a805461ffff60a01b1916600160a01b61ffff8416908102919091179091556040519081527fa4a0021d5a3e887ed39092287593218ba56daabb698755739666df81df918409906020016125cb565b600354604080518082019091526002815261323960f01b6020820152906001600160a01b03163314610bb95760405162461bcd60e51b8152600401610c099190615262565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612e00908490613f43565b60008061301b84612728565b6001600160a01b0386166000908152600c60205260408120549294509092509061304e906001600160801b03168561535a565b905082811115604051806040016040528060018152602001603560f81b8152509061308c5760405162461bcd60e51b8152600401610c099190615262565b506001600160801b038111156130b45760405162461bcd60e51b8152600401610c0990615275565b6001600160a01b0385166000908152600c6020526040902080546001600160801b0319166001600160801b038316179055600182166130fa576130fa8560018417613de6565b61267a856129fa565b604080518082019091526002815261035360f41b60208201526000908261313d5760405162461bcd60e51b8152600401610c099190615262565b50600061314b600284615393565b90506b033b2e3c9fd0803ce8000000613166826000196153f0565b6131709190615393565b84111560405180604001604052806002815260200161068760f31b815250906131ac5760405162461bcd60e51b8152600401610c099190615262565b5082816131c56b033b2e3c9fd0803ce8000000876153d1565b6131cf919061535a565b610ba99190615393565b6000806131e58661363c565b1591506000806131f489612728565b90925090506001811615613227576001600160a01b0389166000908152600c60205260409020546001600160801b031692505b600481161580159061324157508161323f848961535a565b115b1561337c576001600160a01b0389166000908152600d60209081526040918290208251808401909352546001600160801b03808216808552600160801b909204169183019190915288850184900391908210156132cd5780518290036001600160801b031681526020810180518391906132bc90839061532f565b6001600160801b03169052506132f9565b80516020820180516132e090839061532f565b6001600160801b03908116909152825160008452169250505b613303828a6153f0565b985086613379576133158a838a613505565b81600e6000828254613327919061535a565b90915550506001600160a01b038b167f1d725625046467975a2203d85e8286374668c126fa7cf471841bee1db7604192613361848b612681565b60408051918252602082018c90520160405180910390a25b50505b50509550959350505050565b6001600160a01b0384166133e85760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c09565b613403836133f46140c3565b6133fe91906153f0565b6140ce565b61287a848484846140d7565b6001600160a01b0385166134735760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c09565b6001600160a01b0384166134d55760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c09565b836001600160a01b0316856001600160a01b03161461267a576134fa858484846140d7565b61267a848483614102565b6001600160a01b03831661355b5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c09565b613571826135676140c3565b6133fe919061535a565b612e00838383614102565b6001600160a01b0380851660009081526012602090815260408083209387168352929052205481838210156135c45760405162461bcd60e51b8152600401610c099190615262565b5061267a8585858403612361565b6000806135df8484614123565b915091505b9250929050565b6000806000806135fa88613bb2565b9195509350915061360b878561535a565b935061ffff85161561363257613625848661ffff16612499565b61362f908761535a565b95505b5094509450949050565b600061364782613ca2565b516001600160c01b031692915050565b6000610a106140c3565b60405162461bcd60e51b815260206004820152600b60248201526a155394d5541413d495115160aa1b6044820152606401610c09565b612e00838383612361565b6040805180820190915260028152611a9b60f11b6020820152600090836136dc5760405162461bcd60e51b8152600401610c099190615262565b506000806136e986612728565b915091508380156136fc57506004811615155b156137ed576001600160a01b0386166000908152600d60209081526040918290208251808401909352546001600160801b038082168452600160801b90910416908201819052156137eb578581602001516001600160801b0316106137a557602080820180516001600160801b0390899003811682526001600160a01b038a166000908152600d9093526040909220925190518216600160801b02911617905550159050610d23565b6020808201805160008083526001600160a01b038b168152600d9093526040909220835191516001600160801b03908116600160801b0292811692909217905516909503945b505b5015949350505050565b6001600080613808836000196153f0565b83106138565760405162461bcd60e51b815260206004820152601960248201527f696e76616c696420636f6e7472616374207265766973696f6e000000000000006044820152606401610c09565b600084116138a65760405162461bcd60e51b815260206004820152601e60248201527f696e636f727265637420696e697469616c697a6572207265766973696f6e00006044820152606401610c09565b828411156138f65760405162461bcd60e51b815260206004820152601e60248201527f696e636f6e73697374656e7420636f6e7472616374207265766973696f6e00006044820152606401610c09565b61390360016000196153f0565b601454101561397f57600060155411801561391f575082601454105b9150818061392c5750303b155b80613938575060145483115b61397a5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610c09565b6139ef565b61398c60016000196153f0565b60145414801561399b5750303b155b6139dd5760405162461bcd60e51b81526020600482015260136024820152721a5b9a5d1a585b1a5e995c88189b1bd8dad959606a1b6044820152606401610c09565b60006014556015546000199350151591505b8115613a46578360155411613a465760405162461bcd60e51b815260206004820152601f60248201527f696e636f7272656374206f72646572206f6620696e697469616c697a657273006044820152606401610c09565b6014548411613a63578115613a5b5760016015555b506001612309565b5060009193909250565b8251613a80906000906020860190614a90565b508151613a94906001906020850190614a90565b506002805460ff191660ff929092169190911790555050565b60006001600160a01b031683602001516001600160a01b03161415604051806040016040528060028152602001610dcd60f21b81525090613b015760405162461bcd60e51b8152600401610c099190615262565b50613b0a6141ce565b613b1583838361427a565b613b406002613b26600160646153a7565b613b319060646153a7565b613b3b9190615372565b613b6f565b505060200151601380546001600160a01b0319166001600160a01b03909216919091179055565b610bb9613661565b613b7b600160646153a7565b613b869060646153a7565b61ffff168161ffff161115613b9a57600080fd5b600f805461ffff191661ffff92909216919091179055565b600080600061230284614346565b6007546001600160e01b0316821415613bd7575050565b6001600160e01b03821115613beb57600080fd5b60075463ffffffff600160e01b90910481169082168114612e00576007546001600160e01b0316613c1b83614354565b600780546001600160e01b0319166001600160e01b038681169190911790915561287a90821683856143d1565b600a546001600160a01b031661260e5760405162461bcd60e51b815260206004820152601660248201527518dbdb9d1c9bdb1b195c881a5cc81c995c5d5a5c995960521b6044820152606401610c09565b610bb981612310565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03949094168452600582529282902082519384018352546001600160c01b038116845263ffffffff600160c01b8204811692850192909252600160e01b9004169082015290565b600a546000906001600160a01b031615801590610a265750600a5460405163ce91a05960e01b81526001600160a01b0384811660048301529091169063ce91a0599060240160206040518083038186803b158015613d6b57600080fd5b505afa158015613d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a269190614f3f565b6003546000906001600160a01b0383811691161415613dc55750600019919050565b6001600160a01b0382166000908152600b602052604090205460ff16610a26565b6001600160a01b0382166000908152600560205260409020805463ffffffff60c01b1916600160c01b63ffffffff8416021790555050565b600060018216613e2f576000613e52565b6001600160a01b0383166000908152600c60205260409020546001600160801b03165b6001600160801b03169392505050565b6000613e6d8661363c565b9050613e7c878787878761340f565b6003546004546001600160a01b0391821691631cf00663911689898915801590613ea557508987145b60008b118015613eb3575086155b6040516001600160e01b031960e088901b1681526001600160a01b039586166004820152938516602485015293909116604483015215156064820152901515608482015260a401600060405180830381600087803b158015613f1457600080fd5b505af11580156121bd573d6000803e3d6000fd5b600080613f3685858561444d565b9092161515949350505050565b6001600160a01b0382163b613f9a5760405162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e7472616374006044820152606401610c09565b600080836001600160a01b031683604051613fb59190615180565b6000604051808303816000865af19150503d8060008114613ff2576040519150601f19603f3d011682016040523d82523d6000602084013e613ff7565b606091505b5091509150816140495760405162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646044820152606401610c09565b80511561287a57808060200190518101906140649190614f3f565b61287a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c09565b6000610a1060095490565b61174a816144d1565b60008060006140e78787876144ef565b9250925092506140f9878484846145cf565b50505050505050565b60008060006141118686614632565b9250925092506116a1868484846145cf565b6001600160a01b03821660009081526005602052604081205481906001600160c01b0316614156575060009050806135e4565b6001600160a01b0384166000818152600560209081526040808320815160608101835290546001600160c01b038116825263ffffffff600160c01b8204811683860152600160e01b90910416818301529383526006909152812054909182916141c09190876146dc565b909890975095505050505050565b467f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6141f86147c3565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018290523060a082015260c00160408051601f19818403018152919052805160209091012060105550565b8251600380546001600160a01b03199081166001600160a01b039384169081179092556040808701516004805490931694169390931781558251630b6b5afb60e11b8152925191926316d6b5f69281830192602092829003018186803b1580156142e357600080fd5b505afa1580156142f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061431b9190614bad565b600260016101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6000808061230284426147cd565b60075463ffffffff600160e01b909104811690821610156143ac5760405162461bcd60e51b8152602060048201526012602482015271726574726f6163746976652075706461746560701b6044820152606401610c09565b6007805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b6009546143dd57505050565b8163ffffffff168163ffffffff1614612e005760095461440c906ec097ce7bc90715b34b9f1000000000615393565b61441690846153d1565b92506144228282615407565b6144329063ffffffff16846153d1565b60086000828254614443919061535a565b9091555050505050565b60405163cc8b29c160e01b81526001600160a01b038381166004830152602482018390526000919085169063cc8b29c19060440160206040518083038186803b15801561449957600080fd5b505afa1580156144ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba99190615101565b60006009548214156144e557506000919050565b610a2682426148c0565b6001600160a01b0383166000908152600560209081526040808320815160608101835290546001600160c01b038116825263ffffffff600160c01b8204811694830194909452600160e01b90049092169082015281908190614551868661535a565b81516001600160c01b031610156145a35760405162461bcd60e51b8152602060048201526016602482015275616d6f756e7420657863656564732062616c616e636560501b6044820152606401610c09565b80516001600160c01b031695909503946145be87828861490a565b935093509350505b93509350939050565b826146265760008160028111156145f657634e487b7160e01b600052602160045260246000fd5b148061461c57506000614611600a546001600160a01b031690565b6001600160a01b0316145b156146265761287a565b61287a84848484614a03565b6001600160a01b0382166000908152600560209081526040808320815160608101835290546001600160c01b03811680835263ffffffff600160c01b8304811695840195909552600160e01b90910490931691810191909152829182919061469a908661535a565b94506001600160c01b038511156146c35760405162461bcd60e51b8152600401610c0990615275565b6146ce86828761490a565b935093509350509250925092565b60085460095460009081901561474d576000806146f7614a71565b915091506009546ec097ce7bc90715b34b9f10000000006147189190615393565b61472290836153d1565b915061472e8187615407565b61473e9063ffffffff16836153d1565b614748908661535a565b945050505b84831480614763575085516001600160c01b0316155b1561477757505060408401516000906145c6565b6ec097ce7bc90715b34b9f100000000061479186856153f0565b87516147a691906001600160c01b03166153d1565b6147b09190615393565b6040870151909250905093509350939050565b6060610a1061096e565b6001600160a01b0382166000908152600560209081526040808320815160608101835290546001600160c01b03811680835263ffffffff600160c01b8304811695840195909552600160e01b909104909316918101919091528291829190614840576000806000935093509350506117a6565b6001600160a01b038616600090815260066020526040812054819081906148699085908a6146dc565b6001600160a01b038c166000908152600660209081526040808320959095556005905292909220805463ffffffff8c16600160e01b026001600160e01b039091161790559750955060019450505050509250925092565b60008060006148cd614a71565b915091506148da84614354565b81156148fe576148eb8282866143d1565b8363ffffffff168163ffffffff16141592505b50506009929092555090565b6000806000846040015163ffffffff166000141561492a5750600161492e565b5060005b6001600160a01b0386166000908152600660205260408120544291908190819061495a908a90866146dc565b6001600160a01b03909c1660008181526006602090815260408083209590955584516060810186526001600160c01b039d8e1681529d81015163ffffffff9081168f83019081529981168f870190815293835260059091529390209b518c54975191518416600160e01b026001600160e01b0392909416600160c01b026001600160e01b03199098169b169a909a17959095179890981697909717909755509690945092505050565b600a546040516316050d6360e31b81526001600160a01b039091169063b0286b1890614a39908790879087908790600401615212565b600060405180830381600087803b158015614a5357600080fd5b505af1158015614a67573d6000803e3d6000fd5b5050505050505050565b6007546001600160e01b03811691600160e01b90910463ffffffff1690565b828054614a9c90615458565b90600052602060002090601f016020900481019282614abe5760008555614b04565b82601f10614ad757805160ff1916838001178555614b04565b82800160010185558215614b04579182015b82811115614b04578251825591602001919060010190614ae9565b50614b10929150614b14565b5090565b5b80821115614b105760008155600101614b15565b60008083601f840112614b3a578182fd5b50813567ffffffffffffffff811115614b51578182fd5b6020830191508360208285010111156135e457600080fd5b803561ffff81168114614b7b57600080fd5b919050565b803560ff81168114614b7b57600080fd5b600060208284031215614ba2578081fd5b8135610d23816154b9565b600060208284031215614bbe578081fd5b8151610d23816154b9565b60008060408385031215614bdb578081fd5b8235614be6816154b9565b91506020830135614bf6816154b9565b809150509250929050565b600080600060608486031215614c15578081fd5b8335614c20816154b9565b92506020840135614c30816154b9565b929592945050506040919091013590565b600080600080600060a08688031215614c58578081fd5b8535614c63816154b9565b94506020860135614c73816154b9565b9350604086013592506060860135614c8a816154b9565b949793965091946080013592915050565b60008060008060808587031215614cb0578384fd5b8435614cbb816154b9565b93506020850135614ccb816154b9565b9250604085013591506060850135614ce2816154ce565b939692955090935050565b60008060008060808587031215614d02578384fd5b8435614d0d816154b9565b93506020850135614d1d816154b9565b93969395505050506040820135916060013590565b600080600080600060a08688031215614d49578283fd5b8535614d54816154b9565b94506020860135614d64816154b9565b935060408601359250606086013591506080860135614d82816154ce565b809150509295509295909350565b600080600080600080600060e0888a031215614daa578485fd5b8735614db5816154b9565b96506020880135614dc5816154b9565b95506040880135945060608801359350614de160808901614b80565b925060a0880135915060c0880135905092959891949750929550565b60008060408385031215614e0f578182fd5b8235614e1a816154b9565b946020939093013593505050565b600080600060608486031215614e3c578081fd5b8335614e47816154b9565b9250602084013591506040840135614e5e816154b9565b809150509250925092565b60008060008060808587031215614e7e578182fd5b8435614e89816154b9565b935060208501359250604085013591506060850135614ce2816154ce565b60008060008060808587031215614ebc578182fd5b8435614ec7816154b9565b93506020850135925060408501359150614ee360608601614b69565b905092959194509250565b60008060408385031215614f00578182fd5b8235614f0b816154b9565b9150602083013563ffffffff81168114614bf6578182fd5b600060208284031215614f34578081fd5b8135610d23816154ce565b600060208284031215614f50578081fd5b8151610d23816154ce565b600060208284031215614f6c578081fd5b813567ffffffffffffffff811115614f82578182fd5b820160608185031215610d23578182fd5b600080600080600080600087890360e0811215614fae578182fd5b6080811215614fbb578182fd5b50879650608088013567ffffffffffffffff80821115614fd9578283fd5b614fe58b838c01614b29565b909850965060a08a0135915080821115614ffd578283fd5b6150098b838c01614b29565b909650945060c08a0135915080821115615021578283fd5b5061502e8a828b01614b29565b989b979a50959850939692959293505050565b600060808284031215615052578081fd5b6040516080810181811067ffffffffffffffff8211171561508157634e487b7160e01b83526041600452602483fd5b604052823561508f816154b9565b8152602083013561509f816154b9565b602082015260408301356150b2816154b9565b60408201526150c360608401614b80565b60608201529392505050565b6000602082840312156150e0578081fd5b610d2382614b69565b6000602082840312156150fa578081fd5b5035919050565b600060208284031215615112578081fd5b5051919050565b6000806040838503121561512b578182fd5b50508035926020909101359150565b60006020828403121561514b578081fd5b610d2382614b80565b6000815180845261516c81602086016020860161542c565b601f01601f19169290920160200192915050565b6000825161519281846020870161542c565b9190910192915050565b6001600160a01b038716815260a0602082018190526000906151c090830188615154565b82810360408401526151d28188615154565b905060ff8616606084015282810360808401528381528385602083013781602085830101526020601f19601f860116820101915050979650505050505050565b6001600160a01b03851681526020810184905263ffffffff83166040820152608081016003831061525357634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b602081526000610d236020830184615154565b6020808252601390820152720c4c2d8c2dcc6ca40d2e640e8dede40d0d2ced606b1b604082015260600190565b602080825282516001600160a01b031682820152820151606060408301526000906152d06080840182615154565b905061ffff60408501511660608401528091505092915050565b6000808335601e19843603018112615300578283fd5b83018035915067ffffffffffffffff82111561531a578283fd5b6020019150368190038213156135e457600080fd5b60006001600160801b038083168185168083038211156153515761535161548d565b01949350505050565b6000821982111561536d5761536d61548d565b500190565b600061ffff80841680615387576153876154a3565b92169190910492915050565b6000826153a2576153a26154a3565b500490565b600061ffff808316818516818304811182151516156153c8576153c861548d565b02949350505050565b60008160001904831182151516156153eb576153eb61548d565b500290565b6000828210156154025761540261548d565b500390565b600063ffffffff838116908316818110156154245761542461548d565b039392505050565b60005b8381101561544757818101518382015260200161542f565b8381111561287a5750506000910152565b600181811c9082168061546c57607f821691505b602082108114156111f757634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b0381168114610bb957600080fd5b8015158114610bb957600080fdfe45524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220279b2798ec4f082e100906fb3149d7a3f81c68449f340b774d8c105181c1f09764736f6c63430008040033

Verified Source Code Full Match

Compiler: v0.8.4+commit.c7e474f2 EVM: istanbul Optimization: Yes (200 runs)
Errors.sol 121 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

/**
 * @title Errors library
 * @notice Defines the error messages emitted by the different contracts
 * @dev Error messages prefix glossary:
 *  - VL = ValidationLogic
 *  - MATH = Math libraries
 *  - CT = Common errors between tokens (DepositToken, VariableDebtToken and StableDebtToken)
 *  - AT = DepositToken
 *  - SDT = StableDebtToken
 *  - VDT = VariableDebtToken
 *  - LP = LendingPool
 *  - LPAPR = AddressesProviderRegistry
 *  - LPC = LendingPoolConfiguration
 *  - RL = ReserveLogic
 *  - LPCM = LendingPoolExtension
 *  - ST = Stake
 */
library Errors {
  //contract specific errors
  string public constant VL_INVALID_AMOUNT = '1'; // Amount must be greater than 0
  string public constant VL_NO_ACTIVE_RESERVE = '2'; // Action requires an active reserve
  string public constant VL_RESERVE_FROZEN = '3'; // Action cannot be performed because the reserve is frozen
  string public constant VL_UNKNOWN_RESERVE = '4'; // Action requires an active reserve
  string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5'; // User cannot withdraw more than the available balance (above min limit)
  string public constant VL_TRANSFER_NOT_ALLOWED = '6'; // Transfer cannot be allowed.
  string public constant VL_BORROWING_NOT_ENABLED = '7'; // Borrowing is not enabled
  string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = '8'; // Invalid interest rate mode selected
  string public constant VL_COLLATERAL_BALANCE_IS_0 = '9'; // The collateral balance is 0
  string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10'; // Health factor is lesser than the liquidation threshold
  string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11'; // There is not enough collateral to cover a new borrow
  string public constant VL_STABLE_BORROWING_NOT_ENABLED = '12'; // stable borrowing not enabled
  string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13'; // collateral is (mostly) the same currency that is being borrowed
  string public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '14'; // The requested amount is exceeds max size of a stable loan
  string public constant VL_NO_DEBT_OF_SELECTED_TYPE = '15'; // to repay a debt, user needs to specify a correct debt type (variable or stable)
  string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16'; // To repay on behalf of an user an explicit amount to repay is needed
  string public constant VL_NO_STABLE_RATE_LOAN_IN_RESERVE = '17'; // User does not have a stable rate loan in progress on this reserve
  string public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = '18'; // User does not have a variable rate loan in progress on this reserve
  string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = '19'; // The collateral balance needs to be greater than 0
  string public constant VL_DEPOSIT_ALREADY_IN_USE = '20'; // User deposit is already being used as collateral
  string public constant VL_RESERVE_MUST_BE_COLLATERAL = '21'; // This reserve must be enabled as collateral
  string public constant LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '22'; // Interest rate rebalance conditions were not met
  string public constant AT_OVERDRAFT_DISABLED = '23'; // User doesn't accept allocation of overdraft
  string public constant VL_INVALID_SUB_BALANCE_ARGS = '24';
  string public constant AT_INVALID_SLASH_DESTINATION = '25';

  string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // The caller of the function is not the lending pool configurator

  string public constant LENDING_POOL_REQUIRED = '28'; // The caller of this function must be a lending pool
  string public constant CALLER_NOT_LENDING_POOL = '29'; // The caller of this function must be a lending pool
  string public constant AT_SUB_BALANCE_RESTIRCTED_FUNCTION = '30'; // The caller of this function must be a lending pool or a sub-balance operator

  string public constant RL_RESERVE_ALREADY_INITIALIZED = '32'; // Reserve has already been initialized
  string public constant CALLER_NOT_POOL_ADMIN = '33'; // The caller must be the pool admin
  string public constant LPC_RESERVE_LIQUIDITY_NOT_0 = '34'; // The liquidity of the reserve needs to be 0

  string public constant LPAPR_PROVIDER_NOT_REGISTERED = '41'; // Provider is not registered
  string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42'; // Health factor is not below the threshold
  string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43'; // The collateral chosen cannot be liquidated
  string public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '44'; // User did not borrow the specified currency
  string public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = '45'; // There isn't enough liquidity available to liquidate

  string public constant MATH_MULTIPLICATION_OVERFLOW = '48';
  string public constant MATH_ADDITION_OVERFLOW = '49';
  string public constant MATH_DIVISION_BY_ZERO = '50';
  string public constant RL_LIQUIDITY_INDEX_OVERFLOW = '51'; //  Liquidity index overflows uint128
  string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = '52'; //  Variable borrow index overflows uint128
  string public constant RL_LIQUIDITY_RATE_OVERFLOW = '53'; //  Liquidity rate overflows uint128
  string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = '54'; //  Variable borrow rate overflows uint128
  string public constant RL_STABLE_BORROW_RATE_OVERFLOW = '55'; //  Stable borrow rate overflows uint128
  string public constant CT_INVALID_MINT_AMOUNT = '56'; //invalid amount to mint
  string public constant CALLER_NOT_STAKE_ADMIN = '57';
  string public constant CT_INVALID_BURN_AMOUNT = '58'; //invalid amount to burn
  string public constant BORROW_ALLOWANCE_NOT_ENOUGH = '59'; // User borrows on behalf, but allowance are too small
  string public constant CALLER_NOT_LIQUIDITY_CONTROLLER = '60';
  string public constant CALLER_NOT_REF_ADMIN = '61';
  string public constant VL_INSUFFICIENT_REWARD_AVAILABLE = '62';
  string public constant LP_CALLER_MUST_BE_DEPOSIT_TOKEN = '63';
  string public constant LP_IS_PAUSED = '64'; // Pool is paused
  string public constant LP_NO_MORE_RESERVES_ALLOWED = '65';
  string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66';
  string public constant RC_INVALID_LTV = '67';
  string public constant RC_INVALID_LIQ_THRESHOLD = '68';
  string public constant RC_INVALID_LIQ_BONUS = '69';
  string public constant RC_INVALID_DECIMALS = '70';
  string public constant RC_INVALID_RESERVE_FACTOR = '71';
  string public constant LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72';
  string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = '73';
  string public constant VL_TREASURY_REQUIRED = '74';
  string public constant LPC_INVALID_CONFIGURATION = '75'; // Invalid risk parameters for the reserve
  string public constant CALLER_NOT_EMERGENCY_ADMIN = '76'; // The caller must be the emergency admin
  string public constant UL_INVALID_INDEX = '77';
  string public constant VL_CONTRACT_REQUIRED = '78';
  string public constant SDT_STABLE_DEBT_OVERFLOW = '79';
  string public constant SDT_BURN_EXCEEDS_BALANCE = '80';
  string public constant CALLER_NOT_REWARD_CONFIG_ADMIN = '81'; // The caller of this function must be a reward admin
  string public constant LP_INVALID_PERCENTAGE = '82'; // Percentage can't be more than 100%
  string public constant LP_IS_NOT_TRUSTED_FLASHLOAN = '83';
  string public constant CALLER_NOT_SWEEP_ADMIN = '84';
  string public constant LP_TOO_MANY_NESTED_CALLS = '85';
  string public constant LP_RESTRICTED_FEATURE = '86';
  string public constant LP_TOO_MANY_FLASHLOAN_CALLS = '87';
  string public constant RW_BASELINE_EXCEEDED = '88';
  string public constant CALLER_NOT_REWARD_RATE_ADMIN = '89';
  string public constant CALLER_NOT_REWARD_CONTROLLER = '90';
  string public constant RW_REWARD_PAUSED = '91';
  string public constant CALLER_NOT_TEAM_MANAGER = '92';
  string public constant STK_REDEEM_PAUSED = '93';
  string public constant STK_INSUFFICIENT_COOLDOWN = '94';
  string public constant STK_UNSTAKE_WINDOW_FINISHED = '95';
  string public constant STK_INVALID_BALANCE_ON_COOLDOWN = '96';
  string public constant STK_EXCESSIVE_SLASH_PCT = '97';
  string public constant STK_WRONG_COOLDOWN_OR_UNSTAKE = '98';
  string public constant STK_PAUSED = '99';

  string public constant TXT_OWNABLE_CALLER_NOT_OWNER = 'Ownable: caller is not the owner';
  string public constant TXT_CALLER_NOT_PROXY_OWNER = 'ProxyOwner: caller is not the owner';
  string public constant TXT_ACCESS_RESTRICTED = 'RESTRICTED';
}
AccessFlags.sol 46 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

library AccessFlags {
  // roles that can be assigned to multiple addresses - use range [0..15]
  uint256 public constant EMERGENCY_ADMIN = 1 << 0;
  uint256 public constant POOL_ADMIN = 1 << 1;
  uint256 public constant TREASURY_ADMIN = 1 << 2;
  uint256 public constant REWARD_CONFIG_ADMIN = 1 << 3;
  uint256 public constant REWARD_RATE_ADMIN = 1 << 4;
  uint256 public constant STAKE_ADMIN = 1 << 5;
  uint256 public constant REFERRAL_ADMIN = 1 << 6;
  uint256 public constant LENDING_RATE_ADMIN = 1 << 7;
  uint256 public constant SWEEP_ADMIN = 1 << 8;
  uint256 public constant ORACLE_ADMIN = 1 << 9;

  uint256 public constant ROLES = (uint256(1) << 16) - 1;

  // singletons - use range [16..64] - can ONLY be assigned to a single address
  uint256 public constant SINGLETONS = ((uint256(1) << 64) - 1) & ~ROLES;

  // proxied singletons
  uint256 public constant LENDING_POOL = 1 << 16;
  uint256 public constant LENDING_POOL_CONFIGURATOR = 1 << 17;
  uint256 public constant LIQUIDITY_CONTROLLER = 1 << 18;
  uint256 public constant TREASURY = 1 << 19;
  uint256 public constant REWARD_TOKEN = 1 << 20;
  uint256 public constant REWARD_STAKE_TOKEN = 1 << 21;
  uint256 public constant REWARD_CONTROLLER = 1 << 22;
  uint256 public constant REWARD_CONFIGURATOR = 1 << 23;
  uint256 public constant STAKE_CONFIGURATOR = 1 << 24;
  uint256 public constant REFERRAL_REGISTRY = 1 << 25;

  uint256 public constant PROXIES = ((uint256(1) << 26) - 1) & ~ROLES;

  // non-proxied singletons, numbered down from 31 (as JS has problems with bitmasks over 31 bits)
  uint256 public constant WETH_GATEWAY = 1 << 27;
  uint256 public constant DATA_HELPER = 1 << 28;
  uint256 public constant PRICE_ORACLE = 1 << 29;
  uint256 public constant LENDING_RATE_ORACLE = 1 << 30;

  // any other roles - use range [64..]
  // these roles can be assigned to multiple addresses

  uint256 public constant TRUSTED_FLASHLOAN = 1 << 66;
}
AccessHelper.sol 45 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './interfaces/IRemoteAccessBitmask.sol';

/// @dev Helper/wrapper around IRemoteAccessBitmask
library AccessHelper {
  function getAcl(IRemoteAccessBitmask remote, address subject) internal view returns (uint256) {
    return remote.queryAccessControlMask(subject, ~uint256(0));
  }

  function queryAcl(
    IRemoteAccessBitmask remote,
    address subject,
    uint256 filterMask
  ) internal view returns (uint256) {
    return remote.queryAccessControlMask(subject, filterMask);
  }

  function hasAnyOf(
    IRemoteAccessBitmask remote,
    address subject,
    uint256 flags
  ) internal view returns (bool) {
    uint256 found = queryAcl(remote, subject, flags);
    return found & flags != 0;
  }

  function hasAny(IRemoteAccessBitmask remote, address subject) internal view returns (bool) {
    return remote.queryAccessControlMask(subject, 0) != 0;
  }

  function hasNone(IRemoteAccessBitmask remote, address subject) internal view returns (bool) {
    return remote.queryAccessControlMask(subject, 0) == 0;
  }

  function requireAnyOf(
    IRemoteAccessBitmask remote,
    address subject,
    uint256 flags,
    string memory text
  ) internal view {
    require(hasAnyOf(remote, subject, flags), text);
  }
}
IPoolToken.sol 11 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IDerivedToken.sol';

// solhint-disable func-name-mixedcase
interface IPoolToken is IDerivedToken {
  function POOL() external view returns (address);

  function updatePool() external;
}
WadRayMath.sol 95 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../Errors.sol';

/// @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)
library WadRayMath {
  uint256 internal constant WAD = 1e18;
  uint256 internal constant halfWAD = WAD / 2;

  uint256 internal constant RAY = 1e27;
  uint256 internal constant halfRAY = RAY / 2;

  uint256 internal constant WAD_RAY_RATIO = 1e9;

  /// @return One ray, 1e27
  function ray() internal pure returns (uint256) {
    return RAY;
  }

  /// @return One wad, 1e18
  function wad() internal pure returns (uint256) {
    return WAD;
  }

  /// @return Half ray, 1e27/2
  function halfRay() internal pure returns (uint256) {
    return halfRAY;
  }

  /// @return Half ray, 1e18/2
  function halfWad() internal pure returns (uint256) {
    return halfWAD;
  }

  /// @dev Multiplies two wad, rounding half up to the nearest wad
  function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0 || b == 0) {
      return 0;
    }
    require(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (a * b + halfWAD) / WAD;
  }

  /// @dev Divides two wad, rounding half up to the nearest wad
  function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0, Errors.MATH_DIVISION_BY_ZERO);
    uint256 halfB = b / 2;

    require(a <= (type(uint256).max - halfB) / WAD, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (a * WAD + halfB) / b;
  }

  /// @dev Multiplies two ray, rounding half up to the nearest ray
  function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0 || b == 0) {
      return 0;
    }

    require(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (a * b + halfRAY) / RAY;
  }

  /// @dev Divides two ray, rounding half up to the nearest ray
  function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0, Errors.MATH_DIVISION_BY_ZERO);
    uint256 halfB = b / 2;

    require(a <= (type(uint256).max - halfB) / RAY, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (a * RAY + halfB) / b;
  }

  /// @dev Casts ray down to wad
  function rayToWad(uint256 a) internal pure returns (uint256) {
    uint256 halfRatio = WAD_RAY_RATIO / 2;
    uint256 result = halfRatio + a;

    require(result >= halfRatio, Errors.MATH_ADDITION_OVERFLOW);

    return result / WAD_RAY_RATIO;
  }

  /// @dev Converts wad up to ray
  function wadToRay(uint256 a) internal pure returns (uint256) {
    uint256 result = a * WAD_RAY_RATIO;

    require(result / WAD_RAY_RATIO == a, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return result;
  }
}
IDepositToken.sol 163 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../dependencies/openzeppelin/contracts/IERC20.sol';
import './IScaledBalanceToken.sol';
import './IPoolToken.sol';

interface IDepositToken is IERC20, IPoolToken, IScaledBalanceToken {
  /**
   * @dev Emitted on mint
   * @param account The receiver of minted tokens
   * @param value The amount minted
   * @param index The new liquidity index of the reserve
   **/
  event Mint(address indexed account, uint256 value, uint256 index);

  /**
   * @dev Mints `amount` depositTokens to `user`
   * @param user The address receiving the minted tokens
   * @param amount The amount of tokens getting minted
   * @param index The new liquidity index of the reserve
   * @param repayOverdraft Enables to use this amount cover an overdraft
   * @return `true` if the the previous balance of the user was 0
   */
  function mint(
    address user,
    uint256 amount,
    uint256 index,
    bool repayOverdraft
  ) external returns (bool);

  /**
   * @dev Emitted on burn
   * @param account The owner of tokens burned
   * @param target The receiver of the underlying
   * @param value The amount burned
   * @param index The new liquidity index of the reserve
   **/
  event Burn(address indexed account, address indexed target, uint256 value, uint256 index);

  /**
   * @dev Emitted on transfer
   * @param from The sender
   * @param to The recipient
   * @param value The amount transferred
   * @param index The new liquidity index of the reserve
   **/
  event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);

  /**
   * @dev Burns depositTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
   * @param user The owner of the depositTokens, getting them burned
   * @param receiverOfUnderlying The address that will receive the underlying
   * @param amount The amount being burned
   * @param index The new liquidity index of the reserve
   **/
  function burn(
    address user,
    address receiverOfUnderlying,
    uint256 amount,
    uint256 index
  ) external;

  /**
   * @dev Mints depositTokens to the reserve treasury
   * @param amount The amount of tokens getting minted
   * @param index The new liquidity index of the reserve
   */
  function mintToTreasury(uint256 amount, uint256 index) external;

  /**
   * @dev Transfers depositTokens in the event of a borrow being liquidated, in case the liquidators reclaims the depositToken
   * @param from The address getting liquidated, current owner of the depositTokens
   * @param to The recipient
   * @param value The amount of tokens getting transferred
   * @param index The liquidity index of the reserve
   * @param transferUnderlying is true when the underlying should be, otherwise the depositToken
   * @return true when transferUnderlying is false and the recipient had zero balance
   **/
  function transferOnLiquidation(
    address from,
    address to,
    uint256 value,
    uint256 index,
    bool transferUnderlying
  ) external returns (bool);

  /**
   * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer
   * assets in borrow(), withdraw() and flashLoan()
   * @param user The recipient of the underlying
   * @param amount The amount getting transferred
   * @return The amount transferred
   **/
  function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);

  function collateralBalanceOf(address) external view returns (uint256);

  /**
   * @dev Emitted on use of overdraft (by liquidation)
   * @param account The receiver of overdraft (user with shortage)
   * @param value The amount received
   * @param index The liquidity index of the reserve
   **/
  event OverdraftApplied(address indexed account, uint256 value, uint256 index);

  /**
   * @dev Emitted on return of overdraft allowance when it was fully or partially used
   * @param provider The provider of overdraft
   * @param recipient The receiver of overdraft
   * @param overdraft The amount overdraft that was covered by the provider
   * @param index The liquidity index of the reserve
   **/
  event OverdraftCovered(address indexed provider, address indexed recipient, uint256 overdraft, uint256 index);

  event SubBalanceProvided(address indexed provider, address indexed recipient, uint256 amount, uint256 index);
  event SubBalanceReturned(address indexed provider, address indexed recipient, uint256 amount, uint256 index);
  event SubBalanceLocked(address indexed provider, uint256 amount, uint256 index);
  event SubBalanceUnlocked(address indexed provider, uint256 amount, uint256 index);

  function updateTreasury() external;

  function addSubBalanceOperator(address addr) external;

  function addStakeOperator(address addr) external;

  function removeSubBalanceOperator(address addr) external;

  function provideSubBalance(
    address provider,
    address recipient,
    uint256 scaledAmount
  ) external;

  function returnSubBalance(
    address provider,
    address recipient,
    uint256 scaledAmount,
    bool preferOverdraft
  ) external returns (uint256 coveredOverdraft);

  function lockSubBalance(address provider, uint256 scaledAmount) external;

  function unlockSubBalance(
    address provider,
    uint256 scaledAmount,
    address transferTo
  ) external;

  function replaceSubBalance(
    address prevProvider,
    address recipient,
    uint256 prevScaledAmount,
    address newProvider,
    uint256 newScaledAmount
  ) external returns (uint256 coveredOverdraftByPrevProvider);

  function transferLockedBalance(
    address from,
    address to,
    uint256 scaledAmount
  ) external;
}
IDerivedToken.sol 10 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

// solhint-disable func-name-mixedcase
interface IDerivedToken {
  /**
   * @dev Returns the address of the underlying asset of this token (E.g. WETH for agWETH)
   **/
  function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}
ERC20Events.sol 21 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface ERC20Events {
  /**
   * @dev Emitted when `value` tokens are moved from one account (`from`) to
   * another (`to`).
   *
   * Note that `value` may be zero.
   */
  event Transfer(address indexed from, address indexed to, uint256 value);

  /**
   * @dev Emitted when the allowance of a `spender` for an `owner` is set by
   * a call to {approve}. `value` is the new allowance.
   */
  event Approval(address indexed owner, address indexed spender, uint256 value);
}
IRewardedToken.sol 10 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IRewardedToken {
  function setIncentivesController(address) external;

  function getIncentivesController() external view returns (address);

  function rewardedBalanceOf(address) external view returns (uint256);
}
PercentageMath.sol 56 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../Errors.sol';

/// @dev Percentages are defined in basis points. The precision is indicated by ONE. Operations are rounded half up.
library PercentageMath {
  uint16 public constant BP = 1; // basis point
  uint16 public constant PCT = 100 * BP; // basis points per percentage point
  uint16 public constant ONE = 100 * PCT; // basis points per 1 (100%)
  uint16 public constant HALF_ONE = ONE / 2;
  // deprecated
  uint256 public constant PERCENTAGE_FACTOR = ONE; //percentage plus two decimals

  /**
   * @dev Executes a percentage multiplication
   * @param value The value of which the percentage needs to be calculated
   * @param factor Basis points of the value to be calculated
   * @return The percentage of value
   **/
  function percentMul(uint256 value, uint256 factor) internal pure returns (uint256) {
    if (value == 0 || factor == 0) {
      return 0;
    }

    require(value <= (type(uint256).max - HALF_ONE) / factor, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (value * factor + HALF_ONE) / ONE;
  }

  /**
   * @dev Executes a percentage division
   * @param value The value of which the percentage needs to be calculated
   * @param factor Basis points of the value to be calculated
   * @return The value divided the percentage
   **/
  function percentDiv(uint256 value, uint256 factor) internal pure returns (uint256) {
    require(factor != 0, Errors.MATH_DIVISION_BY_ZERO);
    uint256 halfFactor = factor >> 1;

    require(value <= (type(uint256).max - halfFactor) / ONE, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (value * ONE + halfFactor) / factor;
  }

  function percentOf(uint256 value, uint256 base) internal pure returns (uint256) {
    require(base != 0, Errors.MATH_DIVISION_BY_ZERO);
    if (value == 0) {
      return 0;
    }

    require(value <= (type(uint256).max - HALF_ONE) / ONE, Errors.MATH_MULTIPLICATION_OVERFLOW);

    return (value * ONE + (base >> 1)) / base;
  }
}
MarketAccessBitmask.sol 78 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../tools/Errors.sol';
import './interfaces/IMarketAccessController.sol';
import './AccessHelper.sol';
import './AccessFlags.sol';

// solhint-disable func-name-mixedcase
abstract contract MarketAccessBitmaskMin {
  using AccessHelper for IMarketAccessController;
  IMarketAccessController internal _remoteAcl;

  constructor(IMarketAccessController remoteAcl) {
    _remoteAcl = remoteAcl;
  }

  function _getRemoteAcl(address addr) internal view returns (uint256) {
    return _remoteAcl.getAcl(addr);
  }

  function hasRemoteAcl() internal view returns (bool) {
    return _remoteAcl != IMarketAccessController(address(0));
  }

  function acl_hasAnyOf(address subject, uint256 flags) internal view returns (bool) {
    return _remoteAcl.hasAnyOf(subject, flags);
  }

  modifier aclHas(uint256 flags) virtual {
    _remoteAcl.requireAnyOf(msg.sender, flags, Errors.TXT_ACCESS_RESTRICTED);
    _;
  }

  modifier aclAnyOf(uint256 flags) {
    _remoteAcl.requireAnyOf(msg.sender, flags, Errors.TXT_ACCESS_RESTRICTED);
    _;
  }

  modifier onlyPoolAdmin() {
    _remoteAcl.requireAnyOf(msg.sender, AccessFlags.POOL_ADMIN, Errors.CALLER_NOT_POOL_ADMIN);
    _;
  }

  modifier onlyRewardAdmin() {
    _remoteAcl.requireAnyOf(msg.sender, AccessFlags.REWARD_CONFIG_ADMIN, Errors.CALLER_NOT_REWARD_CONFIG_ADMIN);
    _;
  }

  modifier onlyRewardConfiguratorOrAdmin() {
    _remoteAcl.requireAnyOf(
      msg.sender,
      AccessFlags.REWARD_CONFIG_ADMIN | AccessFlags.REWARD_CONFIGURATOR,
      Errors.CALLER_NOT_REWARD_CONFIG_ADMIN
    );
    _;
  }
}

abstract contract MarketAccessBitmask is MarketAccessBitmaskMin {
  using AccessHelper for IMarketAccessController;

  constructor(IMarketAccessController remoteAcl) MarketAccessBitmaskMin(remoteAcl) {}

  modifier onlyEmergencyAdmin() {
    _remoteAcl.requireAnyOf(msg.sender, AccessFlags.EMERGENCY_ADMIN, Errors.CALLER_NOT_EMERGENCY_ADMIN);
    _;
  }

  function _onlySweepAdmin() internal view virtual {
    _remoteAcl.requireAnyOf(msg.sender, AccessFlags.SWEEP_ADMIN, Errors.CALLER_NOT_SWEEP_ADMIN);
  }

  modifier onlySweepAdmin() {
    _onlySweepAdmin();
    _;
  }
}
IERC20Details.sol 10 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IERC20Details {
  function name() external view returns (string memory);

  function symbol() external view returns (string memory);

  function decimals() external view returns (uint8);
}
IEmergencyAccess.sol 10 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IEmergencyAccess {
  function setPaused(bool paused) external;

  function isPaused() external view returns (bool);

  event EmergencyPaused(address indexed by, bool paused);
}
IProxy.sol 6 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IProxy {
  function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;
}
ERC20PermitBase.sol 84 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IERC20WithPermit.sol';

abstract contract ERC20PermitBase is IERC20WithPermit {
  // solhint-disable-next-line var-name-mixedcase
  bytes32 public DOMAIN_SEPARATOR;
  bytes public constant EIP712_REVISION = bytes('1');
  bytes32 internal constant EIP712_DOMAIN =
    keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
  bytes32 public constant PERMIT_TYPEHASH =
    keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');

  /// @dev owner => next valid nonce to submit with permit()
  /// keep public for backward compatibility
  mapping(address => uint256) public _nonces;

  constructor() {
    _initializeDomainSeparator();
  }

  /// @dev returns nonce, to comply with eip-2612
  function nonces(address addr) external view returns (uint256) {
    return _nonces[addr];
  }

  function _initializeDomainSeparator() internal {
    uint256 chainId;

    // solhint-disable-next-line no-inline-assembly
    assembly {
      chainId := chainid()
    }

    DOMAIN_SEPARATOR = keccak256(
      abi.encode(EIP712_DOMAIN, keccak256(_getPermitDomainName()), keccak256(EIP712_REVISION), chainId, address(this))
    );
  }

  /**
   * @dev implements the permit function as for https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
   * @param owner the owner of the funds
   * @param spender the spender
   * @param value the amount
   * @param deadline the deadline timestamp, type(uint256).max for no deadline
   * @param v signature param
   * @param s signature param
   * @param r signature param
   */

  function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external override {
    require(owner != address(0), 'INVALID_OWNER');
    require(block.timestamp <= deadline, 'INVALID_EXPIRATION');
    uint256 currentValidNonce = _nonces[owner];
    bytes32 digest = keccak256(
      abi.encodePacked(
        '\x19\x01',
        DOMAIN_SEPARATOR,
        keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
      )
    );

    require(owner == ecrecover(digest, v, r, s), 'INVALID_SIGNATURE');
    _nonces[owner] = currentValidNonce + 1;
    _approveByPermit(owner, spender, value);
  }

  function _approveByPermit(
    address owner,
    address spender,
    uint256 value
  ) internal virtual;

  function _getPermitDomainName() internal view virtual returns (bytes memory);
}
ERC20DetailsBase.sol 42 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IERC20Details.sol';

abstract contract ERC20DetailsBase is IERC20Details {
  string private _name;
  string private _symbol;
  uint8 private _decimals;

  constructor(
    string memory name_,
    string memory symbol_,
    uint8 decimals_
  ) {
    _name = name_;
    _symbol = symbol_;
    _decimals = decimals_;
  }

  function _initializeERC20(
    string memory name_,
    string memory symbol_,
    uint8 decimals_
  ) internal {
    _name = name_;
    _symbol = symbol_;
    _decimals = decimals_;
  }

  function name() public view override returns (string memory) {
    return _name;
  }

  function symbol() public view override returns (string memory) {
    return _symbol;
  }

  function decimals() public view override returns (uint8) {
    return _decimals;
  }
}
IERC20WithPermit.sol 16 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../dependencies/openzeppelin/contracts/IERC20.sol';

interface IERC20WithPermit is IERC20 {
  function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;
}
IScaledBalanceToken.sol 28 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IScaledBalanceToken {
  /**
   * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the
   * updated stored balance divided by the reserve's liquidity index at the moment of the update
   * @param user The user whose balance is calculated
   * @return The scaled balance of the user
   **/
  function scaledBalanceOf(address user) external view returns (uint256);

  /**
   * @dev Returns the scaled balance of the user and the scaled total supply.
   * @param user The address of the user
   * @return The scaled balance of the user
   * @return The scaled balance and the scaled total supply
   **/
  function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);

  /**
   * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
   * @return The scaled total supply
   **/
  function scaledTotalSupply() external view returns (uint256);

  function getScaleIndex() external view returns (uint256);
}
ERC20AllowanceBase.sol 76 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../dependencies/openzeppelin/contracts/IERC20.sol';

abstract contract ERC20AllowanceBase is IERC20 {
  mapping(address => mapping(address => uint256)) private _allowances;

  function allowance(address owner, address spender) public view virtual override returns (uint256) {
    return _allowances[owner][spender];
  }

  function approve(address spender, uint256 amount) public virtual override returns (bool) {
    _approve(msg.sender, spender, amount);
    return true;
  }

  function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
    _approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue);
    return true;
  }

  function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
    _decAllowance(msg.sender, spender, subtractedValue, 'ERC20: decreased allowance below zero');
    return true;
  }

  function useAllowance(address owner, uint256 subtractedValue) public virtual returns (bool) {
    _decAllowance(owner, msg.sender, subtractedValue, 'ERC20: decreased allowance below zero');
    return true;
  }

  function _decAllowance(
    address owner,
    address spender,
    uint256 subtractedValue,
    string memory errMsg
  ) private {
    uint256 limit = _allowances[owner][spender];
    require(limit >= subtractedValue, errMsg);
    unchecked {
      _approve(owner, spender, limit - subtractedValue);
    }
  }

  /**
   * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
   *
   * This is internal function is equivalent to `approve`, and can be used to
   * e.g. set automatic allowances for certain subsystems, etc.
   *
   * Emits an {Approval} event.
   *
   * Requirements:
   *
   * - `owner` cannot be the zero address.
   * - `spender` cannot be the zero address.
   */
  function _approve(
    address owner,
    address spender,
    uint256 amount
  ) internal {
    require(owner != address(0), 'ERC20: approve from the zero address');
    require(spender != address(0), 'ERC20: approve to the zero address');

    _allowances[owner][spender] = amount;
    emit Approval(owner, spender, amount);
  }

  event Approval(address indexed owner, address indexed spender, uint256 value);

  function _approveTransferFrom(address owner, uint256 amount) internal virtual {
    _decAllowance(owner, msg.sender, amount, 'ERC20: transfer amount exceeds allowance');
  }
}
ILendingPoolForTokens.sol 38 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../access/interfaces/IMarketAccessController.sol';
import '../protocol/libraries/types/DataTypes.sol';

interface ILendingPoolForTokens {
  /**
   * @dev Validates and finalizes an depositToken transfer
   * - Only callable by the overlying depositToken of the `asset`
   * @param asset The address of the underlying asset of the depositToken
   * @param from The user from which the depositToken are transferred
   * @param to The user receiving the depositToken
   * @param lastBalanceFrom True when from's balance was non-zero and became zero
   * @param firstBalanceTo True when to's balance was zero and became non-zero
   */
  function finalizeTransfer(
    address asset,
    address from,
    address to,
    bool lastBalanceFrom,
    bool firstBalanceTo
  ) external;

  function getAccessController() external view returns (IMarketAccessController);

  function getReserveNormalizedIncome(address asset) external view returns (uint256);

  function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

  function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);

  function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);

  function getReservesList() external view returns (address[] memory);

  function setReservePaused(address asset, bool paused) external;
}
ControlledRewardPool.sol 291 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../tools/math/PercentageMath.sol';
import '../interfaces/IRewardController.sol';
import '../interfaces/IManagedRewardPool.sol';
import '../../access/AccessFlags.sol';
import '../../access/AccessHelper.sol';
import '../../tools/Errors.sol';

abstract contract ControlledRewardPool is IManagedRewardPool {
  using PercentageMath for uint256;

  IRewardController private _controller;

  uint16 private _baselinePercentage;
  bool private _paused;

  constructor(
    IRewardController controller,
    uint256 initialRate,
    uint16 baselinePercentage
  ) {
    _initialize(controller, initialRate, baselinePercentage, '');
  }

  function _initialize(
    IRewardController controller,
    uint256 initialRate,
    uint16 baselinePercentage,
    string memory poolName
  ) internal virtual {
    poolName;
    _controller = controller;

    if (baselinePercentage > 0) {
      _setBaselinePercentage(baselinePercentage);
    }

    if (initialRate > 0) {
      _setRate(initialRate);
    }
  }

  function getPoolName() public view virtual override returns (string memory) {
    return '';
  }

  function updateBaseline(uint256 baseline)
    external
    virtual
    override
    onlyController
    returns (bool hasBaseline, uint256 appliedRate)
  {
    if (_baselinePercentage == 0) {
      return (false, internalGetRate());
    }
    appliedRate = baseline.percentMul(_baselinePercentage);
    _setRate(appliedRate);
    return (true, appliedRate);
  }

  function setBaselinePercentage(uint16 factor) external override onlyController {
    _setBaselinePercentage(factor);
  }

  function getBaselinePercentage() public view override returns (uint16) {
    return _baselinePercentage;
  }

  function _mustHaveController() private view {
    require(address(_controller) != address(0), 'controller is required');
  }

  function _setBaselinePercentage(uint16 factor) internal virtual {
    _mustHaveController();
    require(factor <= PercentageMath.ONE, 'illegal value');
    _baselinePercentage = factor;
    emit BaselinePercentageUpdated(factor);
  }

  function _setRate(uint256 rate) internal {
    _mustHaveController();
    internalSetRate(rate);
    emit RateUpdated(rate);
  }

  function getRate() external view override returns (uint256) {
    return internalGetRate();
  }

  function internalGetRate() internal view virtual returns (uint256);

  function internalSetRate(uint256 rate) internal virtual;

  function setPaused(bool paused) public override onlyEmergencyAdmin {
    if (_paused != paused) {
      _paused = paused;
      internalPause(paused);
    }
    emit EmergencyPaused(msg.sender, paused);
  }

  function isPaused() public view override returns (bool) {
    return _paused;
  }

  function internalPause(bool paused) internal virtual {}

  function getRewardController() public view override returns (address) {
    return address(_controller);
  }

  function claimRewardFor(address holder)
    external
    override
    onlyController
    returns (
      uint256,
      uint32,
      bool
    )
  {
    return internalGetReward(holder);
  }

  function claimRewardWithLimitFor(
    address holder,
    uint256 baseAmount,
    uint256 limit,
    uint16 minPct
  )
    external
    override
    onlyController
    returns (
      uint256 amount,
      uint32 since,
      bool keepPull,
      uint256 newLimit
    )
  {
    return internalGetRewardWithLimit(holder, baseAmount, limit, minPct);
  }

  function calcRewardFor(address holder, uint32 at)
    external
    view
    virtual
    override
    returns (
      uint256 amount,
      uint256,
      uint32 since
    )
  {
    require(at >= uint32(block.timestamp));
    (amount, since) = internalCalcReward(holder, at);
    return (amount, 0, since);
  }

  function internalAllocateReward(
    address holder,
    uint256 allocated,
    uint32 since,
    AllocationMode mode
  ) internal {
    _controller.allocatedByPool(holder, allocated, since, mode);
  }

  function internalGetRewardWithLimit(
    address holder,
    uint256 baseAmount,
    uint256 limit,
    uint16 minBoostPct
  )
    internal
    virtual
    returns (
      uint256 amount,
      uint32 since,
      bool keepPull,
      uint256
    )
  {
    (amount, since, keepPull) = internalGetReward(holder);
    amount += baseAmount;
    if (minBoostPct > 0) {
      limit += PercentageMath.percentMul(amount, minBoostPct);
    }
    return (amount, since, keepPull, limit);
  }

  function internalGetReward(address holder)
    internal
    virtual
    returns (
      uint256,
      uint32,
      bool
    );

  function internalCalcReward(address holder, uint32 at) internal view virtual returns (uint256, uint32);

  function attachedToRewardController() external override onlyController returns (uint256) {
    internalAttachedToRewardController();
    return internalGetPreAllocatedLimit();
  }

  function detachedFromRewardController() external override onlyController returns (uint256) {
    return internalGetPreAllocatedLimit();
  }

  function internalGetPreAllocatedLimit() internal virtual returns (uint256) {
    return 0;
  }

  function internalAttachedToRewardController() internal virtual {}

  function _isController(address addr) internal view virtual returns (bool) {
    return address(_controller) == addr;
  }

  function getAccessController() internal view virtual returns (IMarketAccessController) {
    return _controller.getAccessController();
  }

  function _onlyController() private view {
    require(_isController(msg.sender), Errors.CALLER_NOT_REWARD_CONTROLLER);
  }

  modifier onlyController() {
    _onlyController();
    _;
  }

  function _isConfigAdmin(address addr) internal view returns (bool) {
    return address(_controller) != address(0) && _controller.isConfigAdmin(addr);
  }

  function _onlyConfigAdmin() private view {
    require(_isConfigAdmin(msg.sender), Errors.CALLER_NOT_REWARD_CONFIG_ADMIN);
  }

  modifier onlyConfigAdmin() {
    _onlyConfigAdmin();
    _;
  }

  function _isRateAdmin(address addr) internal view returns (bool) {
    return address(_controller) != address(0) && _controller.isRateAdmin(addr);
  }

  function _onlyRateAdmin() private view {
    require(_isRateAdmin(msg.sender), Errors.CALLER_NOT_REWARD_RATE_ADMIN);
  }

  modifier onlyRateAdmin() {
    _onlyRateAdmin();
    _;
  }

  function _onlyEmergencyAdmin() private view {
    AccessHelper.requireAnyOf(
      getAccessController(),
      msg.sender,
      AccessFlags.EMERGENCY_ADMIN,
      Errors.CALLER_NOT_EMERGENCY_ADMIN
    );
  }

  modifier onlyEmergencyAdmin() {
    _onlyEmergencyAdmin();
    _;
  }

  function _notPaused() private view {
    require(!_paused, Errors.RW_REWARD_PAUSED);
  }

  modifier notPaused() {
    _notPaused();
    _;
  }

  modifier notPausedCustom(string memory err) {
    require(!_paused, err);
    _;
  }
}
DataTypes.sol 58 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

library DataTypes {
  struct ReserveData {
    //stores the reserve configuration
    ReserveConfigurationMap configuration;
    //the liquidity index. Expressed in ray
    uint128 liquidityIndex;
    //variable borrow index. Expressed in ray
    uint128 variableBorrowIndex;
    //the current supply rate. Expressed in ray
    uint128 currentLiquidityRate;
    //the current variable borrow rate. Expressed in ray
    uint128 currentVariableBorrowRate;
    //the current stable borrow rate. Expressed in ray
    uint128 currentStableBorrowRate;
    uint40 lastUpdateTimestamp;
    //tokens addresses
    address depositTokenAddress;
    address stableDebtTokenAddress;
    address variableDebtTokenAddress;
    //address of the reserve strategy
    address strategy;
    //the id of the reserve. Represents the position in the list of the active reserves
    uint8 id;
  }

  struct ReserveConfigurationMap {
    //bit 0-15: LTV
    //bit 16-31: Liq. threshold
    //bit 32-47: Liq. bonus
    //bit 48-55: Decimals
    //bit 56: Reserve is active
    //bit 57: reserve is frozen
    //bit 58: borrowing is enabled
    //bit 59: stable rate borrowing enabled
    //bit 60-63: reserved
    //bit 64-79: reserve factor
    //bit 80: strategy is external
    uint256 data;
  }

  struct UserConfigurationMap {
    uint256 data;
  }

  enum InterestRateMode {NONE, STABLE, VARIABLE}

  struct InitReserveData {
    address asset;
    address depositTokenAddress;
    address stableDebtAddress;
    address variableDebtAddress;
    address strategy;
    bool externalStrategy;
  }
}
DepositToken.sol 42 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../tools/Errors.sol';
import '../../tools/upgradeability/VersionedInitializable.sol';
import './interfaces/PoolTokenConfig.sol';
import './base/DepositTokenBase.sol';

/// @dev Deposit token, an interest bearing token for the Augmented Finance protocol
contract DepositToken is DepositTokenBase, VersionedInitializable {
  uint256 private constant TOKEN_REVISION = 0x1;

  constructor() PoolTokenBase(address(0), address(0)) DepositTokenBase(address(0)) ERC20DetailsBase('', '', 0) {}

  function getRevision() internal pure virtual override returns (uint256) {
    return TOKEN_REVISION;
  }

  function initialize(
    PoolTokenConfig calldata config,
    string calldata name,
    string calldata symbol,
    bytes calldata params
  ) external override initializerRunAlways(TOKEN_REVISION) {
    if (isRevisionInitialized(TOKEN_REVISION)) {
      _initializeERC20(name, symbol, super.decimals());
    } else {
      _initializeERC20(name, symbol, config.underlyingDecimals);
      _initializePoolToken(config, params);
    }

    emit Initialized(
      config.underlyingAsset,
      address(config.pool),
      address(config.treasury),
      super.name(),
      super.symbol(),
      super.decimals(),
      params
    );
  }
}
IAccessController.sol 16 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IRemoteAccessBitmask.sol';
import '../../tools/upgradeability/IProxy.sol';

/// @dev Main registry of permissions and addresses
interface IAccessController is IRemoteAccessBitmask {
  function getAddress(uint256 id) external view returns (address);

  function createProxy(
    address admin,
    address impl,
    bytes calldata params
  ) external returns (IProxy);
}
IRewardController.sol 25 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../access/interfaces/IMarketAccessController.sol';

enum AllocationMode {
  Push,
  SetPull,
  SetPullSpecial
}

interface IRewardController {
  function allocatedByPool(
    address holder,
    uint256 allocated,
    uint32 since,
    AllocationMode mode
  ) external;

  function isRateAdmin(address) external view returns (bool);

  function isConfigAdmin(address) external view returns (bool);

  function getAccessController() external view returns (IMarketAccessController);
}
IManagedRewardPool.sol 62 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../interfaces/IEmergencyAccess.sol';

interface IManagedRewardPool is IEmergencyAccess {
  function updateBaseline(uint256) external returns (bool hasBaseline, uint256 appliedRate);

  function setBaselinePercentage(uint16) external;

  function getBaselinePercentage() external view returns (uint16);

  function getRate() external view returns (uint256);

  function getPoolName() external view returns (string memory);

  function claimRewardFor(address holder)
    external
    returns (
      uint256 amount,
      uint32 since,
      bool keepPull
    );

  function claimRewardWithLimitFor(
    address holder,
    uint256 baseAmount,
    uint256 limit,
    uint16 minPct
  )
    external
    returns (
      uint256 amount,
      uint32 since,
      bool keepPull,
      uint256 newLimit
    );

  function calcRewardFor(address holder, uint32 at)
    external
    view
    returns (
      uint256 amount,
      uint256 extra,
      uint32 since
    );

  function addRewardProvider(address provider, address token) external;

  function removeRewardProvider(address provider) external;

  function getRewardController() external view returns (address);

  function attachedToRewardController() external returns (uint256 allocateReward);

  function detachedFromRewardController() external returns (uint256 deallocateReward);

  event RateUpdated(uint256 rate);
  event BaselinePercentageUpdated(uint16);
  event ProviderAdded(address provider, address token);
  event ProviderRemoved(address provider);
}
CalcLinearRewardBalances.sol 224 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../interfaces/IRewardController.sol';

abstract contract CalcLinearRewardBalances {
  struct RewardBalance {
    uint192 rewardBase;
    uint32 custom;
    uint32 claimedAt;
  }
  mapping(address => RewardBalance) private _balances;
  mapping(address => uint256) private _accumRates;

  uint224 private _rate;
  uint32 private _rateUpdatedAt;

  function setLinearRate(uint256 rate) internal {
    setLinearRateAt(rate, getCurrentTick());
  }

  function setLinearRateAt(uint256 rate, uint32 at) internal {
    if (_rate == rate) {
      return;
    }
    require(rate <= type(uint224).max);

    uint32 prevTick = _rateUpdatedAt;
    if (at != prevTick) {
      uint224 prevRate = _rate;
      internalMarkRateUpdate(at);
      _rate = uint224(rate);
      internalRateUpdated(prevRate, prevTick, at);
    }
  }

  function doSyncRateAt(uint32 at) internal {
    uint32 prevTick = _rateUpdatedAt;
    if (at != prevTick) {
      internalMarkRateUpdate(at);
      internalRateUpdated(_rate, prevTick, at);
    }
  }

  function getCurrentTick() internal view virtual returns (uint32);

  function internalRateUpdated(
    uint256 lastRate,
    uint32 lastAt,
    uint32 at
  ) internal virtual;

  function internalMarkRateUpdate(uint32 currentTick) internal {
    require(currentTick >= _rateUpdatedAt, 'retroactive update');
    _rateUpdatedAt = currentTick;
  }

  function getLinearRate() internal view returns (uint256) {
    return _rate;
  }

  function getRateAndUpdatedAt() internal view returns (uint256, uint32) {
    return (_rate, _rateUpdatedAt);
  }

  function internalCalcRateAndReward(
    RewardBalance memory entry,
    uint256 lastAccumRate,
    uint32 currentTick
  )
    internal
    view
    virtual
    returns (
      uint256 rate,
      uint256 allocated,
      uint32 since
    );

  function getRewardEntry(address holder) internal view returns (RewardBalance memory) {
    return _balances[holder];
  }

  function internalSetRewardEntryCustom(address holder, uint32 custom) internal {
    _balances[holder].custom = custom;
  }

  function doIncrementRewardBalance(address holder, uint256 amount)
    internal
    returns (
      uint256,
      uint32,
      AllocationMode
    )
  {
    RewardBalance memory entry = _balances[holder];
    amount += entry.rewardBase;
    require(amount <= type(uint192).max, 'balance is too high');
    return _doUpdateRewardBalance(holder, entry, uint192(amount));
  }

  function doDecrementRewardBalance(
    address holder,
    uint256 amount,
    uint256 minBalance
  )
    internal
    returns (
      uint256,
      uint32,
      AllocationMode
    )
  {
    RewardBalance memory entry = _balances[holder];
    require(entry.rewardBase >= minBalance + amount, 'amount exceeds balance');
    unchecked {
      amount = entry.rewardBase - amount;
    }
    return _doUpdateRewardBalance(holder, entry, uint192(amount));
  }

  function doUpdateRewardBalance(address holder, uint256 newBalance)
    internal
    returns (
      uint256 allocated,
      uint32 since,
      AllocationMode mode
    )
  {
    require(newBalance <= type(uint192).max, 'balance is too high');
    return _doUpdateRewardBalance(holder, _balances[holder], uint192(newBalance));
  }

  function _doUpdateRewardBalance(
    address holder,
    RewardBalance memory entry,
    uint192 newBalance
  )
    private
    returns (
      uint256,
      uint32,
      AllocationMode mode
    )
  {
    if (entry.claimedAt == 0) {
      mode = AllocationMode.SetPull;
    } else {
      mode = AllocationMode.Push;
    }

    uint32 currentTick = getCurrentTick();
    (uint256 adjRate, uint256 allocated, uint32 since) = internalCalcRateAndReward(
      entry,
      _accumRates[holder],
      currentTick
    );

    _accumRates[holder] = adjRate;
    _balances[holder] = RewardBalance(newBalance, entry.custom, currentTick);
    return (allocated, since, mode);
  }

  function doRemoveRewardBalance(address holder) internal returns (uint256 rewardBase) {
    rewardBase = _balances[holder].rewardBase;
    if (rewardBase == 0 && _balances[holder].claimedAt == 0) {
      return 0;
    }
    delete (_balances[holder]);
    return rewardBase;
  }

  function doGetReward(address holder)
    internal
    returns (
      uint256,
      uint32,
      bool
    )
  {
    return doGetRewardAt(holder, getCurrentTick());
  }

  function doGetRewardAt(address holder, uint32 currentTick)
    internal
    returns (
      uint256,
      uint32,
      bool
    )
  {
    RewardBalance memory balance = _balances[holder];
    if (balance.rewardBase == 0) {
      return (0, 0, false);
    }

    (uint256 adjRate, uint256 allocated, uint32 since) = internalCalcRateAndReward(
      balance,
      _accumRates[holder],
      currentTick
    );

    _accumRates[holder] = adjRate;
    _balances[holder].claimedAt = currentTick;
    return (allocated, since, true);
  }

  function doCalcReward(address holder) internal view returns (uint256, uint32) {
    return doCalcRewardAt(holder, getCurrentTick());
  }

  function doCalcRewardAt(address holder, uint32 currentTick) internal view returns (uint256, uint32) {
    if (_balances[holder].rewardBase == 0) {
      return (0, 0);
    }

    (, uint256 allocated, uint32 since) = internalCalcRateAndReward(
      _balances[holder],
      _accumRates[holder],
      currentTick
    );
    return (allocated, since);
  }
}
CalcLinearWeightedReward.sol 95 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './CalcLinearRewardBalances.sol';

abstract contract CalcLinearWeightedReward is CalcLinearRewardBalances {
  uint256 private _accumRate;
  uint256 private _totalSupply;

  uint256 private constant _maxWeightBase = 1e36;

  function internalGetTotalSupply() internal view returns (uint256) {
    return _totalSupply;
  }

  function internalRateUpdated(
    uint256 lastRate,
    uint32 lastAt,
    uint32 at
  ) internal override {
    if (_totalSupply == 0) {
      return;
    }

    // the rate is weighted now vs _maxWeightBase
    if (at != lastAt) {
      lastRate *= _maxWeightBase / _totalSupply;
      _accumRate += lastRate * (at - lastAt);
    }
  }

  function doUpdateTotalSupply(uint256 newSupply) internal returns (bool) {
    if (newSupply == _totalSupply) {
      return false;
    }
    return internalSetTotalSupply(newSupply, getCurrentTick());
  }

  function doIncrementTotalSupply(uint256 amount) internal {
    doUpdateTotalSupply(_totalSupply + amount);
  }

  function doDecrementTotalSupply(uint256 amount) internal {
    doUpdateTotalSupply(_totalSupply - amount);
  }

  function internalSetTotalSupply(uint256 totalSupply, uint32 at) internal returns (bool rateUpdated) {
    (uint256 lastRate, uint32 lastAt) = getRateAndUpdatedAt();
    internalMarkRateUpdate(at);

    if (lastRate > 0) {
      internalRateUpdated(lastRate, lastAt, at);
      rateUpdated = lastAt != at;
    }

    _totalSupply = totalSupply;
    return rateUpdated;
  }

  function internalGetLastAccumRate() internal view returns (uint256) {
    return _accumRate;
  }

  function internalCalcRateAndReward(
    RewardBalance memory entry,
    uint256 lastAccumRate,
    uint32 at
  )
    internal
    view
    virtual
    override
    returns (
      uint256 adjRate,
      uint256 allocated,
      uint32 /* since */
    )
  {
    adjRate = _accumRate;

    if (_totalSupply > 0) {
      (uint256 rate, uint32 updatedAt) = getRateAndUpdatedAt();

      rate *= _maxWeightBase / _totalSupply;
      adjRate += rate * (at - updatedAt);
    }

    if (adjRate == lastAccumRate || entry.rewardBase == 0) {
      return (adjRate, 0, entry.claimedAt);
    }

    allocated = (uint256(entry.rewardBase) * (adjRate - lastAccumRate)) / _maxWeightBase;
    return (adjRate, allocated, entry.claimedAt);
  }
}
IRemoteAccessBitmask.sol 13 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

interface IRemoteAccessBitmask {
  /**
   * @dev Returns access flags granted to the given address and limited by the filterMask. filterMask == 0 has a special meaning.
   * @param addr an to get access perfmissions for
   * @param filterMask limits a subset of flags to be checked.
   * NB! When filterMask == 0 then zero is returned no flags granted, or an unspecified non-zero value otherwise.
   * @return Access flags currently granted
   */
  function queryAccessControlMask(address addr, uint256 filterMask) external view returns (uint256);
}
PoolTokenBase.sol 185 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../../tools/Errors.sol';
import '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import '../../../tools/tokens/ERC20DetailsBase.sol';
import '../../../interfaces/IPoolToken.sol';
import '../../../interfaces/ILendingPoolForTokens.sol';
import '../../../interfaces/IRewardedToken.sol';
import '../../../access/AccessHelper.sol';
import '../../../access/AccessFlags.sol';
import '../../../access/MarketAccessBitmask.sol';
import '../../../access/interfaces/IMarketAccessController.sol';
import '../interfaces/IInitializablePoolToken.sol';
import '../interfaces/PoolTokenConfig.sol';

abstract contract PoolTokenBase is
  IERC20,
  IPoolToken,
  IInitializablePoolToken,
  IRewardedToken,
  ERC20DetailsBase,
  MarketAccessBitmaskMin
{
  using AccessHelper for IMarketAccessController;

  event Transfer(address indexed from, address indexed to, uint256 value);

  ILendingPoolForTokens internal _pool;
  address internal _underlyingAsset;

  constructor(address pool_, address underlyingAsset_)
    MarketAccessBitmaskMin(
      pool_ != address(0) ? ILendingPoolForTokens(pool_).getAccessController() : IMarketAccessController(address(0))
    )
  {
    _pool = ILendingPoolForTokens(pool_);
    _underlyingAsset = underlyingAsset_;
  }

  function _initializePoolToken(PoolTokenConfig memory config, bytes calldata params) internal virtual {
    params;
    _pool = ILendingPoolForTokens(config.pool);
    _underlyingAsset = config.underlyingAsset;
    _remoteAcl = ILendingPoolForTokens(config.pool).getAccessController();
  }

  function _onlyLendingPool() private view {
    require(msg.sender == address(_pool), Errors.CALLER_NOT_LENDING_POOL);
  }

  modifier onlyLendingPool() {
    _onlyLendingPool();
    _;
  }

  function _onlyLendingPoolConfiguratorOrAdmin() private view {
    _remoteAcl.requireAnyOf(
      msg.sender,
      AccessFlags.POOL_ADMIN | AccessFlags.LENDING_POOL_CONFIGURATOR,
      Errors.CALLER_NOT_POOL_ADMIN
    );
  }

  modifier onlyLendingPoolConfiguratorOrAdmin() {
    _onlyLendingPoolConfiguratorOrAdmin();
    _;
  }

  function updatePool() external override onlyLendingPoolConfiguratorOrAdmin {
    address pool = _remoteAcl.getLendingPool();
    require(pool != address(0), Errors.LENDING_POOL_REQUIRED);
    _pool = ILendingPoolForTokens(pool);
  }

  // solhint-disable-next-line func-name-mixedcase
  function UNDERLYING_ASSET_ADDRESS() public view override returns (address) {
    return _underlyingAsset;
  }

  // solhint-disable-next-line func-name-mixedcase
  function POOL() public view override returns (address) {
    return address(_pool);
  }

  function setIncentivesController(address hook) external override onlyRewardConfiguratorOrAdmin {
    internalSetIncentivesController(hook);
  }

  function internalBalanceOf(address account) internal view virtual returns (uint256);

  function internalBalanceAndFlagsOf(address account) internal view virtual returns (uint256, uint32);

  function internalSetFlagsOf(address account, uint32 flags) internal virtual;

  function internalSetIncentivesController(address hook) internal virtual;

  function totalSupply() public view virtual override returns (uint256) {
    return internalTotalSupply();
  }

  function internalTotalSupply() internal view virtual returns (uint256);

  function _mintBalance(
    address account,
    uint256 amount,
    uint256 scale
  ) internal {
    require(account != address(0), 'ERC20: mint to the zero address');
    _beforeTokenTransfer(address(0), account, amount);
    internalUpdateTotalSupply(internalTotalSupply() + amount);
    internalIncrementBalance(account, amount, scale);
  }

  function _burnBalance(
    address account,
    uint256 amount,
    uint256 minLimit,
    uint256 scale
  ) internal {
    require(account != address(0), 'ERC20: burn from the zero address');
    _beforeTokenTransfer(account, address(0), amount);
    internalUpdateTotalSupply(internalTotalSupply() - amount);
    internalDecrementBalance(account, amount, minLimit, scale);
  }

  function _transferBalance(
    address sender,
    address recipient,
    uint256 amount,
    uint256 senderMinLimit,
    uint256 scale
  ) internal {
    require(sender != address(0), 'ERC20: transfer from the zero address');
    require(recipient != address(0), 'ERC20: transfer to the zero address');

    _beforeTokenTransfer(sender, recipient, amount);
    if (sender != recipient) {
      // require(oldSenderBalance >= amount, 'ERC20: transfer amount exceeds balance');
      internalDecrementBalance(sender, amount, senderMinLimit, scale);
      internalIncrementBalance(recipient, amount, scale);
    }
  }

  function _incrementBalanceWithTotal(
    address account,
    uint256 amount,
    uint256 scale,
    uint256 total
  ) internal {
    internalUpdateTotalSupply(total);
    internalIncrementBalance(account, amount, scale);
  }

  function _decrementBalanceWithTotal(
    address account,
    uint256 amount,
    uint256 scale,
    uint256 total
  ) internal {
    internalUpdateTotalSupply(total);
    internalDecrementBalance(account, amount, 0, scale);
  }

  function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
  ) internal virtual {}

  function internalIncrementBalance(
    address account,
    uint256 amount,
    uint256 scale
  ) internal virtual;

  function internalDecrementBalance(
    address account,
    uint256 amount,
    uint256 senderMinLimit,
    uint256 scale
  ) internal virtual;

  function internalUpdateTotalSupply(uint256 newTotal) internal virtual;
}
IMarketAccessController.sol 15 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IAccessController.sol';

/// @dev Main registry of addresses part of or connected to the protocol, including permissioned roles. Also acts a proxy factory.
interface IMarketAccessController is IAccessController {
  function getMarketId() external view returns (string memory);

  function getLendingPool() external view returns (address);

  function getPriceOracle() external view returns (address);

  function getLendingRateOracle() external view returns (address);
}
SubBalanceBase.sol 447 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import '../../../interfaces/IDepositToken.sol';
import '../../../tools/Errors.sol';
import '../../../tools/math/WadRayMath.sol';
import '../../../tools/math/PercentageMath.sol';
import '../../../tools/tokens/ERC20Events.sol';
import '../../../access/AccessFlags.sol';
import '../../../tools/tokens/ERC20PermitBase.sol';
import '../../../tools/tokens/ERC20AllowanceBase.sol';
import './RewardedTokenBase.sol';

abstract contract SubBalanceBase is IDepositToken, RewardedTokenBase {
  using WadRayMath for uint256;
  using PercentageMath for uint256;
  using SafeERC20 for IERC20;

  uint32 private constant FLAG_OUT_BALANCE = 1 << 0;
  uint32 private constant FLAG_ALLOW_OVERDRAFT = 1 << 1;
  uint32 private constant FLAG_IN_BALANCE = 1 << 2;

  struct InBalance {
    uint128 allowance;
    uint128 overdraft;
  }

  struct OutBalance {
    uint128 outBalance;
  }

  uint8 internal constant ACCESS_SUB_BALANCE = uint8(1) << 0;
  uint8 internal constant ACCESS_LOCK_BALANCE = uint8(1) << 1;
  uint8 internal constant ACCESS_TRANSFER = uint8(1) << 2;

  mapping(address => uint8) private _subBalanceOperators;
  mapping(address => OutBalance) private _outBalances;
  mapping(address => InBalance) private _inBalances;
  uint256 private _totalOverdraft;
  uint16 private _overdraftTolerancePct = PercentageMath.HALF_ONE;

  function internalSetOverdraftTolerancePct(uint16 overdraftTolerancePct) internal {
    require(overdraftTolerancePct <= PercentageMath.ONE);
    _overdraftTolerancePct = overdraftTolerancePct;
  }

  function _addSubBalanceOperator(address addr, uint8 accessMode) internal {
    require(addr != address(0), 'address is required');
    _subBalanceOperators[addr] |= accessMode;
  }

  function _removeSubBalanceOperator(address addr) internal {
    delete (_subBalanceOperators[addr]);
  }

  function getSubBalanceOperatorAccess(address addr) internal view virtual returns (uint8) {
    return _subBalanceOperators[addr];
  }

  function getScaleIndex() public view virtual override returns (uint256);

  function _onlySubBalanceOperator(uint8 requiredMode) private view returns (uint8 accessMode) {
    accessMode = getSubBalanceOperatorAccess(msg.sender);
    require(accessMode & requiredMode != 0, Errors.AT_SUB_BALANCE_RESTIRCTED_FUNCTION);
    return accessMode;
  }

  modifier onlySubBalanceOperator() {
    _onlySubBalanceOperator(ACCESS_SUB_BALANCE);
    _;
  }

  function provideSubBalance(
    address provider,
    address recipient,
    uint256 scaledAmount
  ) external override onlySubBalanceOperator {
    require(recipient != address(0), Errors.VL_INVALID_SUB_BALANCE_ARGS);
    _checkSubBalanceArgs(provider, recipient, scaledAmount);

    _incrementOutBalance(provider, scaledAmount);
    _incrementInBalance(recipient, scaledAmount);

    uint256 index = getScaleIndex();
    emit SubBalanceProvided(provider, recipient, scaledAmount.rayMul(index), index);
  }

  function lockSubBalance(address provider, uint256 scaledAmount) external override {
    _onlySubBalanceOperator(ACCESS_LOCK_BALANCE);
    _checkSubBalanceArgs(provider, address(0), scaledAmount);

    _incrementOutBalance(provider, scaledAmount);

    uint256 index = getScaleIndex();
    emit SubBalanceLocked(provider, scaledAmount.rayMul(index), index);
  }

  function _incrementOutBalance(address provider, uint256 scaledAmount) private {
    _incrementOutBalanceNoCheck(provider, scaledAmount);
    _ensureHealthFactor(provider);
  }

  function _incrementOutBalanceNoCheck(address provider, uint256 scaledAmount) private {
    (uint256 balance, uint32 flags) = internalBalanceAndFlagsOf(provider);
    uint256 outBalance = scaledAmount + _outBalances[provider].outBalance;

    require(outBalance <= balance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE);
    require(outBalance <= type(uint128).max, 'balance is too high');

    _outBalances[provider].outBalance = uint128(outBalance);

    if (flags & FLAG_OUT_BALANCE == 0) {
      internalSetFlagsOf(provider, flags | FLAG_OUT_BALANCE);
    }

    _ensureHealthFactor(provider);
  }

  function _ensureHealthFactor(address provider) internal virtual;

  function _decrementOutBalance(
    address provider,
    uint256 scaledAmount,
    uint256 coveredOverdraft,
    uint256 index
  ) private returns (uint256) {
    uint256 outBalance = uint256(_outBalances[provider].outBalance) - scaledAmount;

    if (coveredOverdraft > 0) {
      // A provider of overdraft is not know when overdraft is applied, so there is an excess of tokens minted at that time.
      // So this excess of tokens will be burned here.
      _burnBalance(provider, coveredOverdraft, outBalance, index);
    }
    _outBalances[provider].outBalance = uint128(outBalance);

    if (outBalance == 0) {
      (, uint32 flags) = internalBalanceAndFlagsOf(provider);
      internalSetFlagsOf(provider, flags & ~FLAG_OUT_BALANCE);
    }
    return outBalance;
  }

  function _incrementInBalance(address recipient, uint256 scaledAmount) private {
    (, uint32 flags) = internalBalanceAndFlagsOf(recipient);
    require(flags & FLAG_ALLOW_OVERDRAFT != 0, Errors.AT_OVERDRAFT_DISABLED);
    scaledAmount += _inBalances[recipient].allowance;

    require(scaledAmount <= type(uint128).max, 'balance is too high');
    _inBalances[recipient].allowance = uint128(scaledAmount);

    if (flags & FLAG_IN_BALANCE == 0) {
      internalSetFlagsOf(recipient, flags | FLAG_IN_BALANCE);
    }
  }

  function _decrementInBalance(
    address recipient,
    uint256 scaledAmount,
    bool preferOverdraft
  ) private returns (uint256 overdraft) {
    InBalance memory inBalance = _inBalances[recipient];

    if (
      inBalance.overdraft > 0 &&
      (scaledAmount > inBalance.allowance ||
        (preferOverdraft && inBalance.overdraft >= scaledAmount.percentMul(_overdraftTolerancePct)))
    ) {
      if (inBalance.overdraft > scaledAmount) {
        overdraft = uint128(scaledAmount);
        unchecked {
          inBalance.overdraft -= uint128(scaledAmount);
        }
      } else {
        overdraft = inBalance.overdraft;
        inBalance.overdraft = 0;
      }
      _totalOverdraft -= overdraft;
    }
    inBalance.allowance = uint128(uint256(inBalance.allowance) - (scaledAmount - overdraft));

    _inBalances[recipient] = inBalance;
    if (inBalance.allowance == 0) {
      (, uint32 flags) = internalBalanceAndFlagsOf(recipient);
      internalSetFlagsOf(recipient, flags & ~FLAG_IN_BALANCE);
    }
  }

  function _checkSubBalanceArgs(
    address provider,
    address recipient,
    uint256 scaledAmount
  ) private pure {
    require(scaledAmount > 0, Errors.VL_INVALID_SUB_BALANCE_ARGS);
    require(provider != address(0) && provider != recipient, Errors.VL_INVALID_SUB_BALANCE_ARGS);
  }

  function replaceSubBalance(
    address prevProvider,
    address recipient,
    uint256 prevScaledAmount,
    address newProvider,
    uint256 newScaledAmount
  ) external override onlySubBalanceOperator returns (uint256) {
    require(recipient != address(0), Errors.VL_INVALID_SUB_BALANCE_ARGS);
    _checkSubBalanceArgs(prevProvider, recipient, prevScaledAmount);

    if (prevProvider != newProvider) {
      _checkSubBalanceArgs(newProvider, recipient, newScaledAmount);
      _incrementOutBalance(newProvider, newScaledAmount);
    } else if (prevScaledAmount == newScaledAmount) {
      return 0;
    }

    uint256 overdraft;
    uint256 delta;
    uint256 compensation;
    if (prevScaledAmount > newScaledAmount) {
      unchecked {
        delta = prevScaledAmount - newScaledAmount;
      }
      overdraft = _decrementInBalance(recipient, delta, true);
      if (delta > overdraft) {
        unchecked {
          compensation = delta - overdraft;
        }
      }
    } else if (prevScaledAmount < newScaledAmount) {
      unchecked {
        delta = newScaledAmount - prevScaledAmount;
      }
      _incrementInBalance(recipient, delta);
    }

    uint256 index = getScaleIndex();
    emit SubBalanceReturned(prevProvider, recipient, prevScaledAmount.rayMul(index), index);

    uint256 outBalance;
    if (prevProvider != newProvider) {
      outBalance = _decrementOutBalance(prevProvider, prevScaledAmount, overdraft, index);
    } else if (prevScaledAmount > newScaledAmount) {
      outBalance = _decrementOutBalance(prevProvider, delta, overdraft, index);
    } else {
      _incrementOutBalance(newProvider, delta);
    }

    if (overdraft > 0) {
      emit OverdraftCovered(prevProvider, recipient, uint256(overdraft).rayMul(index), index);
    }
    emit SubBalanceProvided(newProvider, recipient, newScaledAmount.rayMul(index), index);

    if (compensation > 0) {
      _transferScaled(prevProvider, recipient, compensation, outBalance, index);
    }

    return overdraft;
  }

  function returnSubBalance(
    address provider,
    address recipient,
    uint256 scaledAmount,
    bool preferOverdraft
  ) external override onlySubBalanceOperator returns (uint256) {
    require(recipient != address(0), Errors.VL_INVALID_SUB_BALANCE_ARGS);
    _checkSubBalanceArgs(provider, recipient, scaledAmount);

    uint256 overdraft = _decrementInBalance(recipient, scaledAmount, preferOverdraft);
    _ensureHealthFactor(recipient);

    uint256 index = getScaleIndex();
    _decrementOutBalance(provider, scaledAmount, overdraft, index);
    if (overdraft > 0) {
      emit OverdraftCovered(provider, recipient, uint256(overdraft).rayMul(index), index);
    }

    emit SubBalanceReturned(provider, recipient, scaledAmount.rayMul(index), index);
    return overdraft;
  }

  function unlockSubBalance(
    address provider,
    uint256 scaledAmount,
    address transferTo
  ) external override {
    uint8 accessMode = _onlySubBalanceOperator(ACCESS_LOCK_BALANCE);

    _checkSubBalanceArgs(provider, address(0), scaledAmount);

    uint256 index = getScaleIndex();
    uint256 outBalance = _decrementOutBalance(provider, scaledAmount, 0, index);

    emit SubBalanceUnlocked(provider, scaledAmount.rayMul(index), index);

    if (transferTo != address(0) && transferTo != provider) {
      require(accessMode & ACCESS_TRANSFER != 0, Errors.AT_SUB_BALANCE_RESTIRCTED_FUNCTION);
      _transferScaled(provider, transferTo, scaledAmount, outBalance, index);
    }
  }

  function transferLockedBalance(
    address from,
    address to,
    uint256 scaledAmount
  ) external override {
    _onlySubBalanceOperator(ACCESS_LOCK_BALANCE | ACCESS_SUB_BALANCE);
    require(from != address(0) || to != address(0), Errors.VL_INVALID_SUB_BALANCE_ARGS);
    if (scaledAmount == 0) {
      return;
    }

    uint256 index = getScaleIndex();
    uint256 amount = scaledAmount.rayMul(index);

    _decrementOutBalance(from, scaledAmount, 0, index);
    emit SubBalanceUnlocked(from, amount, index);

    _transferScaled(from, to, scaledAmount, 0, index);

    _incrementOutBalanceNoCheck(to, scaledAmount);
    emit SubBalanceLocked(to, amount, index);
  }

  function _mintToSubBalance(
    address user,
    uint256 amountScaled,
    bool repayOverdraft
  ) internal returns (bool) {
    require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT);

    (uint256 firstBalance, uint32 flags) = internalBalanceAndFlagsOf(user);
    if (repayOverdraft && flags & FLAG_IN_BALANCE != 0) {
      InBalance memory inBalance = _inBalances[user];

      if (inBalance.overdraft > 0) {
        unchecked {
          if (inBalance.overdraft >= amountScaled) {
            inBalance.overdraft -= uint128(amountScaled);
            _inBalances[user] = inBalance;
            return firstBalance == 0;
          }
          amountScaled -= inBalance.overdraft;
        }
        inBalance.overdraft = 0;
        _inBalances[user] = inBalance;
      }
    }
    return firstBalance == 0;
  }

  function _liquidateWithSubBalance(
    address user,
    address receiver,
    uint256 scaledAmount,
    uint256 index,
    bool transferUnderlying
  ) internal returns (bool firstBalance, uint256 outBalance) {
    firstBalance = internalBalanceOf(receiver) == 0;
    (uint256 scaledBalanceFrom, uint32 flags) = internalBalanceAndFlagsOf(user);

    if (flags & FLAG_OUT_BALANCE != 0) {
      outBalance = _outBalances[user].outBalance;
    }

    if (flags & FLAG_IN_BALANCE != 0 && scaledAmount + outBalance > scaledBalanceFrom) {
      // lack of own funds - use overdraft

      uint256 requiredAmount;
      unchecked {
        requiredAmount = scaledAmount + outBalance - scaledBalanceFrom;
      }

      InBalance memory inBalance = _inBalances[user];
      if (inBalance.allowance > requiredAmount) {
        unchecked {
          inBalance.allowance -= uint128(requiredAmount);
        }
        inBalance.overdraft += uint128(requiredAmount);
      } else {
        inBalance.overdraft += inBalance.allowance;
        requiredAmount = inBalance.allowance;
        inBalance.allowance = 0;
      }

      scaledAmount -= requiredAmount;
      if (!transferUnderlying) {
        // A provider of overdraft is not known here and tokens cant be transferred from it.
        // So new tokens will be minted here for liquidator and existing tokens will
        // be burned when the provider will return its sub-balance.
        //
        // But the totalSupply will remain unchanged as it is reduced by _totalOverdraft.

        _mintBalance(receiver, requiredAmount, index);
        _totalOverdraft += requiredAmount;

        emit OverdraftApplied(user, requiredAmount.rayMul(index), index);
      }
    }
  }

  function getMinBalance(address user) internal view returns (uint256) {
    return _outBalances[user].outBalance;
  }

  function getMinBalance(address user, uint256 flags) internal view returns (uint256) {
    return flags & FLAG_OUT_BALANCE != 0 ? _outBalances[user].outBalance : 0;
  }

  function scaledBalanceOf(address user) public view override returns (uint256) {
    (uint256 userBalance, uint32 flags) = internalBalanceAndFlagsOf(user);
    if (userBalance == 0) {
      return 0;
    }
    if (flags & FLAG_OUT_BALANCE == 0) {
      return userBalance;
    }

    return userBalance - _outBalances[user].outBalance;
  }

  function scaledTotalSupply() public view override returns (uint256) {
    return super.totalSupply() - _totalOverdraft;
  }

  function collateralBalanceOf(address user) public view override returns (uint256) {
    (uint256 userBalance, uint32 flags) = internalBalanceAndFlagsOf(user);
    if (flags & FLAG_OUT_BALANCE != 0) {
      // the out-balance can only be with own finds, hence it is subtracted before adding the in-balance
      userBalance -= _outBalances[user].outBalance;
    }
    if (flags & FLAG_IN_BALANCE != 0) {
      userBalance += _inBalances[user].allowance;
    }
    if (userBalance == 0) {
      return 0;
    }
    return userBalance.rayMul(getScaleIndex());
  }

  function _transferScaled(
    address from,
    address to,
    uint256 scaledAmount,
    uint256 outBalance,
    uint256 index
  ) internal virtual;
}
IERC20.sol 60 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP excluding events to avoid linearization issues.
 */
interface IERC20 {
  /**
   * @dev Returns the amount of tokens in existence.
   */
  function totalSupply() external view returns (uint256);

  /**
   * @dev Returns the amount of tokens owned by `account`.
   */
  function balanceOf(address account) external view returns (uint256);

  /**
   * @dev Moves `amount` tokens from the caller's account to `recipient`.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   */
  function transfer(address recipient, uint256 amount) external returns (bool);

  /**
   * @dev Returns the remaining number of tokens that `spender` will be
   * allowed to spend on behalf of `owner` through {transferFrom}. This is
   * zero by default.
   *
   * This value changes when {approve} or {transferFrom} are called.
   */
  function allowance(address owner, address spender) external view returns (uint256);

  /**
   * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   *
   * IMPORTANT: Beware that changing an allowance with this method brings the risk
   * that someone may use both the old and the new allowance by unfortunate
   * transaction ordering. One possible solution to mitigate this race
   * condition is to first reduce the spender's allowance to 0 and set the
   * desired value afterwards:
   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
   */
  function approve(address spender, uint256 amount) external returns (bool);

  /**
   * @dev Moves `amount` tokens from `sender` to `recipient` using the
   * allowance mechanism. `amount` is then deducted from the caller's
   * allowance.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   */
  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) external returns (bool);
}
IInitializableRewardPool.sol 16 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './IRewardController.sol';

interface IInitializableRewardPool {
  struct InitRewardPoolData {
    IRewardController controller;
    string poolName;
    uint16 baselinePercentage;
  }

  function initializeRewardPool(InitRewardPoolData calldata) external;

  function initializedRewardPoolWith() external view returns (InitRewardPoolData memory);
}
Address.sol 230 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

// solhint-disable no-inline-assembly, avoid-low-level-calls

/**
 * @dev Collection of functions related to the address type
 */
library Address {
  /**
   * @dev Returns true if `account` is a contract.
   *
   * [IMPORTANT]
   * ====
   * It is unsafe to assume that an address for which this function returns
   * false is an externally-owned account (EOA) and not a contract.
   *
   * Among others, `isContract` will return false for the following
   * types of addresses:
   *
   *  - an externally-owned account
   *  - a contract in construction
   *  - an address where a contract will be created
   *  - an address where a contract lived, but was destroyed
   * ====
   */
  function isContract(address account) internal view returns (bool) {
    // This method relies on extcodesize, which returns 0 for contracts in
    // construction, since the code is only stored at the end of the
    // constructor execution.

    uint256 size;
    assembly {
      size := extcodesize(account)
    }
    return size > 0;
  }

  bytes32 private constant accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

  function isExternallyOwned(address account) internal view returns (bool) {
    // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
    // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
    // for accounts without code, i.e. `keccak256('')`
    bytes32 codehash;
    uint256 size;
    assembly {
      codehash := extcodehash(account)
      size := extcodesize(account)
    }
    return codehash == accountHash && size == 0;
  }

  /**
   * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
   * `recipient`, forwarding all available gas and reverting on errors.
   *
   * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
   * of certain opcodes, possibly making contracts go over the 2300 gas limit
   * imposed by `transfer`, making them unable to receive funds via
   * `transfer`. {sendValue} removes this limitation.
   *
   * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
   *
   * IMPORTANT: because control is transferred to `recipient`, care must be
   * taken to not create reentrancy vulnerabilities. Consider using {ReentrancyGuard}.
   */
  function sendValue(address payable recipient, uint256 amount) internal {
    require(address(this).balance >= amount, 'Address: insufficient balance');

    // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
    (bool success, ) = recipient.call{value: amount}('');
    require(success, 'Address: unable to send value, recipient may have reverted');
  }

  /**
   * @dev Performs a Solidity function call using a low level `call`. A
   * plain `call` is an unsafe replacement for a function call: use this
   * function instead.
   *
   * If `target` reverts with a revert reason, it is bubbled up by this
   * function (like regular Solidity function calls).
   *
   * Returns the raw returned data.
   *
   * Requirements:
   *
   * - `target` must be a contract.
   * - calling `target` with `data` must not revert.
   *
   * _Available since v3.1._
   */
  function functionCall(address target, bytes memory data) internal returns (bytes memory) {
    return functionCall(target, data, 'Address: low-level call failed');
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
   * `errorMessage` as a fallback revert reason when `target` reverts.
   *
   * _Available since v3.1._
   */
  function functionCall(
    address target,
    bytes memory data,
    string memory errorMessage
  ) internal returns (bytes memory) {
    return functionCallWithValue(target, data, 0, errorMessage);
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   * but also transferring `value` wei to `target`.
   *
   * Requirements:
   *
   * - the calling contract must have an ETH balance of at least `value`.
   * - the called Solidity function must be `payable`.
   *
   * _Available since v3.1._
   */
  function functionCallWithValue(
    address target,
    bytes memory data,
    uint256 value
  ) internal returns (bytes memory) {
    return functionCallWithValue(target, data, value, 'Address: low-level call with value failed');
  }

  /**
   * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
   * with `errorMessage` as a fallback revert reason when `target` reverts.
   *
   * _Available since v3.1._
   */
  function functionCallWithValue(
    address target,
    bytes memory data,
    uint256 value,
    string memory errorMessage
  ) internal returns (bytes memory) {
    require(address(this).balance >= value, 'Address: insufficient balance for call');
    require(isContract(target), 'Address: call to non-contract');

    (bool success, bytes memory returndata) = target.call{value: value}(data);
    return verifyCallResult(success, returndata, errorMessage);
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   * but performing a static call.
   *
   * _Available since v3.3._
   */
  function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
    return functionStaticCall(target, data, 'Address: low-level static call failed');
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   * but performing a static call.
   *
   * _Available since v3.3._
   */
  function functionStaticCall(
    address target,
    bytes memory data,
    string memory errorMessage
  ) internal view returns (bytes memory) {
    require(isContract(target), 'Address: static call to non-contract');

    (bool success, bytes memory returndata) = target.staticcall(data);
    return verifyCallResult(success, returndata, errorMessage);
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   * but performing a delegate call.
   *
   * _Available since v3.4._
   */
  function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
    return functionDelegateCall(target, data, 'Address: low-level delegate call failed');
  }

  /**
   * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   * but performing a delegate call.
   *
   * _Available since v3.4._
   */
  function functionDelegateCall(
    address target,
    bytes memory data,
    string memory errorMessage
  ) internal returns (bytes memory) {
    require(isContract(target), 'Address: delegate call to non-contract');

    (bool success, bytes memory returndata) = target.delegatecall(data);
    return verifyCallResult(success, returndata, errorMessage);
  }

  /**
   * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
   * revert reason using the provided one.
   *
   * _Available since v4.3._
   */
  function verifyCallResult(
    bool success,
    bytes memory returndata,
    string memory errorMessage
  ) internal pure returns (bytes memory) {
    if (success) {
      return returndata;
    } else {
      // Look for revert reason and bubble it up if present
      if (returndata.length > 0) {
        // The easiest way to bubble the revert reason is using memory via assembly

        assembly {
          let returndata_size := mload(returndata)
          revert(add(32, returndata), returndata_size)
        }
      } else {
        revert(errorMessage);
      }
    }
  }
}
DepositTokenBase.sol 288 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../../dependencies/openzeppelin/contracts/SafeERC20.sol';
import '../../../interfaces/IDepositToken.sol';
import '../../../tools/Errors.sol';
import '../../../tools/math/WadRayMath.sol';
import '../../../tools/math/PercentageMath.sol';
import '../../../tools/tokens/ERC20Events.sol';
import '../../../access/AccessFlags.sol';
import '../../../tools/tokens/ERC20PermitBase.sol';
import '../../../tools/tokens/ERC20AllowanceBase.sol';
import './SubBalanceBase.sol';

/// @dev Implementation of the interest bearing token for the Augmented Finance protocol
abstract contract DepositTokenBase is SubBalanceBase, ERC20PermitBase, ERC20AllowanceBase {
  using WadRayMath for uint256;
  using PercentageMath for uint256;
  using SafeERC20 for IERC20;
  using AccessHelper for IMarketAccessController;

  address internal _treasury;

  constructor(address treasury_) {
    _treasury = treasury_;
  }

  function _initializePoolToken(PoolTokenConfig memory config, bytes calldata params) internal virtual override {
    require(config.treasury != address(0), Errors.VL_TREASURY_REQUIRED);
    super._initializeDomainSeparator();
    super._initializePoolToken(config, params);
    internalSetOverdraftTolerancePct(PercentageMath.HALF_ONE);
    _treasury = config.treasury;
  }

  function getTreasury() external view returns (address) {
    return _treasury;
  }

  function updateTreasury() external override onlyLendingPoolConfiguratorOrAdmin {
    address treasury = _remoteAcl.getAddress(AccessFlags.TREASURY);
    require(treasury != address(0), Errors.VL_TREASURY_REQUIRED);
    _treasury = treasury;
  }

  function setOverdraftTolerancePct(uint16 overdraftTolerancePct) external onlyLendingPoolConfiguratorOrAdmin {
    internalSetOverdraftTolerancePct(overdraftTolerancePct);
  }

  function addSubBalanceOperator(address addr) external override onlyLendingPoolConfiguratorOrAdmin {
    _addSubBalanceOperator(addr, ACCESS_SUB_BALANCE);
  }

  function addStakeOperator(address addr) external override {
    _remoteAcl.requireAnyOf(
      msg.sender,
      AccessFlags.POOL_ADMIN |
        AccessFlags.LENDING_POOL_CONFIGURATOR |
        AccessFlags.STAKE_CONFIGURATOR |
        AccessFlags.STAKE_ADMIN,
      Errors.CALLER_NOT_POOL_ADMIN
    );

    _addSubBalanceOperator(addr, ACCESS_LOCK_BALANCE | ACCESS_TRANSFER);
  }

  function removeSubBalanceOperator(address addr) external override onlyLendingPoolConfiguratorOrAdmin {
    _removeSubBalanceOperator(addr);
  }

  function getSubBalanceOperatorAccess(address addr) internal view override returns (uint8) {
    if (addr == address(_pool)) {
      return ~uint8(0);
    }
    return super.getSubBalanceOperatorAccess(addr);
  }

  function getScaleIndex() public view override returns (uint256) {
    return _pool.getReserveNormalizedIncome(_underlyingAsset);
  }

  function mint(
    address user,
    uint256 amount,
    uint256 index,
    bool repayOverdraft
  ) external override onlyLendingPool returns (bool firstBalance) {
    uint256 amountScaled = amount.rayDiv(index);
    require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT);

    firstBalance = _mintToSubBalance(user, amountScaled, repayOverdraft);

    _mintBalance(user, amountScaled, index);
    emit Transfer(address(0), user, amount);
    emit Mint(user, amount, index);

    return firstBalance;
  }

  function mintToTreasury(uint256 amount, uint256 index) external override onlyLendingPool {
    if (amount == 0) {
      return;
    }

    address treasury = _treasury;

    // Compared to the normal mint, we don't check for rounding errors.
    // The treasury may experience a very small loss, but it wont revert a valid transactions.
    _mintBalance(treasury, amount.rayDiv(index), index);

    emit Transfer(address(0), treasury, amount);
    emit Mint(treasury, amount, index);
  }

  function burn(
    address user,
    address receiverOfUnderlying,
    uint256 amount,
    uint256 index
  ) external override onlyLendingPool {
    uint256 amountScaled = amount.rayDiv(index);
    require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT);
    _burnBalance(user, amountScaled, getMinBalance(user), index);

    IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount);

    emit Transfer(user, address(0), amount);
    emit Burn(user, receiverOfUnderlying, amount, index);
  }

  function transferOnLiquidation(
    address user,
    address receiver,
    uint256 amount,
    uint256 index,
    bool transferUnderlying
  ) external override onlyLendingPool returns (bool) {
    uint256 scaledAmount = amount.rayDiv(index);
    if (scaledAmount == 0) {
      return false;
    }

    (bool firstBalance, uint256 outBalance) = _liquidateWithSubBalance(
      user,
      receiver,
      scaledAmount,
      index,
      transferUnderlying
    );

    if (transferUnderlying) {
      // Burn the equivalent amount of tokens, sending the underlying to the liquidator
      _burnBalance(user, scaledAmount, outBalance, index);
      IERC20(_underlyingAsset).safeTransfer(receiver, amount);

      emit Transfer(user, address(0), amount);
      emit Burn(user, receiver, amount, index);
      return false;
    }

    super._transferBalance(user, receiver, scaledAmount, outBalance, index);

    emit Transfer(user, receiver, amount);
    emit BalanceTransfer(user, receiver, amount, index);
    return firstBalance;
  }

  /// @dev Calculates the balance of the user: principal balance + interest generated by the principal
  function balanceOf(address user) public view override returns (uint256) {
    uint256 scaledBalance = scaledBalanceOf(user);
    if (scaledBalance == 0) {
      return 0;
    }
    return scaledBalanceOf(user).rayMul(getScaleIndex());
  }

  function rewardedBalanceOf(address user) external view override returns (uint256) {
    return internalBalanceOf(user).rayMul(getScaleIndex());
  }

  function getScaledUserBalanceAndSupply(address user) external view override returns (uint256, uint256) {
    return (scaledBalanceOf(user), scaledTotalSupply());
  }

  function totalSupply() public view override returns (uint256) {
    uint256 currentSupplyScaled = scaledTotalSupply();
    if (currentSupplyScaled == 0) {
      return 0;
    }
    return currentSupplyScaled.rayMul(getScaleIndex());
  }

  function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
    _transfer(msg.sender, recipient, amount, getScaleIndex());
    return true;
  }

  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) public virtual override returns (bool) {
    _transfer(sender, recipient, amount, getScaleIndex());
    _approveTransferFrom(sender, amount);
    return true;
  }

  function transferUnderlyingTo(address target, uint256 amount) external override onlyLendingPool returns (uint256) {
    IERC20(_underlyingAsset).safeTransfer(target, amount);
    return amount;
  }

  /**
   * @dev Validates and executes a transfer.
   * @param from The source address
   * @param to The destination address
   * @param amount The amount getting transferred
   **/
  function _transfer(
    address from,
    address to,
    uint256 amount,
    uint256 index
  ) private {
    uint256 scaledAmount = amount.rayDiv(index);
    (uint256 scaledBalanceBeforeFrom, uint256 flags) = internalBalanceAndFlagsOf(from);

    _transferAndFinalize(from, to, scaledAmount, getMinBalance(from, flags), index, scaledBalanceBeforeFrom);

    emit Transfer(from, to, amount);
    emit BalanceTransfer(from, to, amount, index);
  }

  function _transferScaled(
    address from,
    address to,
    uint256 scaledAmount,
    uint256 minBalance,
    uint256 index
  ) internal override {
    _transferAndFinalize(from, to, scaledAmount, minBalance, index, internalBalanceOf(from));

    uint256 amount = scaledAmount.rayMul(index);
    emit Transfer(from, to, amount);
    emit BalanceTransfer(from, to, amount, index);
  }

  function _transferAndFinalize(
    address from,
    address to,
    uint256 scaledAmount,
    uint256 minBalance,
    uint256 index,
    uint256 scaledBalanceBeforeFrom
  ) private {
    uint256 scaledBalanceBeforeTo = internalBalanceOf(to);
    super._transferBalance(from, to, scaledAmount, minBalance, index);

    _pool.finalizeTransfer(
      _underlyingAsset,
      from,
      to,
      scaledAmount > 0 && scaledBalanceBeforeFrom == scaledAmount,
      scaledAmount > 0 && scaledBalanceBeforeTo == 0
    );
  }

  function _ensureHealthFactor(address holder) internal override {
    _pool.finalizeTransfer(_underlyingAsset, holder, holder, false, false);
  }

  function _approveByPermit(
    address owner,
    address spender,
    uint256 amount
  ) internal override {
    _approve(owner, spender, amount);
  }

  function _getPermitDomainName() internal view override returns (bytes memory) {
    return bytes(super.name());
  }

  function internalPause(bool paused) internal override {
    super.internalPause(paused);
    _pool.setReservePaused(_underlyingAsset, paused);
  }
}
VersionedInitializable.sol 158 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

/**
 * @title VersionedInitializable
 *
 * @dev Helper contract to implement versioned initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` or `initializerRunAlways` modifier.
 * The revision number should be defined as a private constant, returned by getRevision() and used by initializer() modifier.
 *
 * ATTN: There is a built-in protection from implementation self-destruct exploits. This protection
 * prevents initializers from being called on an implementation inself, but only on proxied contracts.
 * To override this protection, call _unsafeResetVersionedInitializers() from a constructor.
 *
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an initializable contract, as well
 * as extending an initializable contract via inheritance.
 *
 * ATTN: When used with inheritance, parent initializers with `initializer` modifier are prevented by calling twice,
 * but can only be called in child-to-parent sequence.
 *
 * WARNING: When used with inheritance, parent initializers with `initializerRunAlways` modifier
 * are NOT protected from multiple calls by another initializer.
 */
abstract contract VersionedInitializable {
  uint256 private constant BLOCK_REVISION = type(uint256).max;
  // This revision number is applied to implementations
  uint256 private constant IMPL_REVISION = BLOCK_REVISION - 1;

  /// @dev Indicates that the contract has been initialized. The default value blocks initializers from being called on an implementation.
  uint256 private lastInitializedRevision = IMPL_REVISION;

  /// @dev Indicates that the contract is in the process of being initialized.
  uint256 private lastInitializingRevision = 0;

  /**
   * @dev There is a built-in protection from self-destruct of implementation exploits. This protection
   * prevents initializers from being called on an implementation inself, but only on proxied contracts.
   * Function _unsafeResetVersionedInitializers() can be called from a constructor to disable this protection.
   * It must be called before any initializers, otherwise it will fail.
   */
  function _unsafeResetVersionedInitializers() internal {
    require(isConstructor(), 'only for constructor');

    if (lastInitializedRevision == IMPL_REVISION) {
      lastInitializedRevision = 0;
    } else {
      require(lastInitializedRevision == 0, 'can only be called before initializer(s)');
    }
  }

  /// @dev Modifier to use in the initializer function of a contract.
  modifier initializer(uint256 localRevision) {
    (uint256 topRevision, bool initializing, bool skip) = _preInitializer(localRevision);

    if (!skip) {
      lastInitializingRevision = localRevision;
      _;
      lastInitializedRevision = localRevision;
    }

    if (!initializing) {
      lastInitializedRevision = topRevision;
      lastInitializingRevision = 0;
    }
  }

  modifier initializerRunAlways(uint256 localRevision) {
    (uint256 topRevision, bool initializing, bool skip) = _preInitializer(localRevision);

    if (!skip) {
      lastInitializingRevision = localRevision;
    }
    _;
    if (!skip) {
      lastInitializedRevision = localRevision;
    }

    if (!initializing) {
      lastInitializedRevision = topRevision;
      lastInitializingRevision = 0;
    }
  }

  function _preInitializer(uint256 localRevision)
    private
    returns (
      uint256 topRevision,
      bool initializing,
      bool skip
    )
  {
    topRevision = getRevision();
    require(topRevision < IMPL_REVISION, 'invalid contract revision');

    require(localRevision > 0, 'incorrect initializer revision');
    require(localRevision <= topRevision, 'inconsistent contract revision');

    if (lastInitializedRevision < IMPL_REVISION) {
      // normal initialization
      initializing = lastInitializingRevision > 0 && lastInitializedRevision < topRevision;
      require(initializing || isConstructor() || topRevision > lastInitializedRevision, 'already initialized');
    } else {
      // by default, initialization of implementation is only allowed inside a constructor
      require(lastInitializedRevision == IMPL_REVISION && isConstructor(), 'initializer blocked');

      // enable normal use of initializers inside a constructor
      lastInitializedRevision = 0;
      // but make sure to block initializers afterwards
      topRevision = BLOCK_REVISION;

      initializing = lastInitializingRevision > 0;
    }

    if (initializing) {
      require(lastInitializingRevision > localRevision, 'incorrect order of initializers');
    }

    if (localRevision <= lastInitializedRevision) {
      // prevent calling of parent's initializer when it was called before
      if (initializing) {
        // Can't set zero yet, as it is not a top-level call, otherwise `initializing` will become false.
        // Further calls will fail with the `incorrect order` assertion above.
        lastInitializingRevision = 1;
      }
      return (topRevision, initializing, true);
    }
    return (topRevision, initializing, false);
  }

  function isRevisionInitialized(uint256 localRevision) internal view returns (bool) {
    return lastInitializedRevision >= localRevision;
  }

  // solhint-disable-next-line func-name-mixedcase
  function REVISION() public pure returns (uint256) {
    return getRevision();
  }

  /**
   * @dev returns the revision number (< type(uint256).max - 1) of the contract.
   * The number should be defined as a private constant.
   **/
  function getRevision() internal pure virtual returns (uint256);

  /// @dev Returns true if and only if the function is running in the constructor
  function isConstructor() private view returns (bool) {
    uint256 cs;
    // solhint-disable-next-line no-inline-assembly
    assembly {
      cs := extcodesize(address())
    }
    return cs == 0;
  }

  // Reserved storage space to allow for layout changes in the future.
  uint256[4] private ______gap;
}
RewardedTokenBase.sol 140 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import '../../../tools/Errors.sol';
import '../../../reward/calcs/CalcLinearWeightedReward.sol';
import '../../../reward/pools/ControlledRewardPool.sol';
import '../../../reward/interfaces/IRewardController.sol';
import '../../../reward/interfaces/IInitializableRewardPool.sol';
import './PoolTokenBase.sol';

abstract contract RewardedTokenBase is
  PoolTokenBase,
  CalcLinearWeightedReward,
  ControlledRewardPool,
  IInitializableRewardPool
{
  constructor() ControlledRewardPool(IRewardController(address(0)), 0, 0) {}

  function internalTotalSupply() internal view override returns (uint256) {
    return super.internalGetTotalSupply();
  }

  function internalBalanceOf(address account) internal view override returns (uint256) {
    return super.getRewardEntry(account).rewardBase;
  }

  function internalBalanceAndFlagsOf(address account) internal view override returns (uint256, uint32) {
    RewardBalance memory balance = super.getRewardEntry(account);
    return (balance.rewardBase, balance.custom);
  }

  function internalSetFlagsOf(address account, uint32 flags) internal override {
    super.internalSetRewardEntryCustom(account, flags);
  }

  function internalSetIncentivesController(address) internal override {
    _mutable();
    _notSupported();
  }

  function _notSupported() private pure {
    revert('UNSUPPORTED');
  }

  function _mutable() private {}

  function addRewardProvider(address, address) external view override onlyConfigAdmin {
    _notSupported();
  }

  function removeRewardProvider(address provider) external override onlyConfigAdmin {}

  function internalGetRate() internal view override returns (uint256) {
    return super.getLinearRate();
  }

  function internalSetRate(uint256 rate) internal override {
    super.setLinearRate(rate);
  }

  function getIncentivesController() public view override returns (address) {
    return address(this);
  }

  function getCurrentTick() internal view override returns (uint32) {
    return uint32(block.timestamp);
  }

  function internalGetReward(address holder)
    internal
    override
    returns (
      uint256,
      uint32,
      bool
    )
  {
    return doGetReward(holder);
  }

  function internalCalcReward(address holder, uint32 at) internal view override returns (uint256, uint32) {
    return doCalcRewardAt(holder, at);
  }

  function getAccessController() internal view override returns (IMarketAccessController) {
    return _remoteAcl;
  }

  function internalAllocatedReward(
    address account,
    uint256 allocated,
    uint32 since,
    AllocationMode mode
  ) internal {
    if (allocated == 0) {
      if (mode == AllocationMode.Push || getRewardController() == address(0)) {
        return;
      }
    }
    super.internalAllocateReward(account, allocated, since, mode);
  }

  function internalIncrementBalance(
    address account,
    uint256 amount,
    uint256
  ) internal override {
    (uint256 allocated, uint32 since, AllocationMode mode) = doIncrementRewardBalance(account, amount);
    internalAllocatedReward(account, allocated, since, mode);
  }

  function internalDecrementBalance(
    address account,
    uint256 amount,
    uint256 minBalance,
    uint256
  ) internal override {
    // require(oldAccountBalance >= amount, 'ERC20: burn amount exceeds balance');
    (uint256 allocated, uint32 since, AllocationMode mode) = doDecrementRewardBalance(account, amount, minBalance);
    internalAllocatedReward(account, allocated, since, mode);
  }

  function internalUpdateTotalSupply(uint256 newSupply) internal override {
    doUpdateTotalSupply(newSupply);
  }

  function getPoolName() public view virtual override returns (string memory) {
    return super.symbol();
  }

  function initializeRewardPool(InitRewardPoolData calldata config) external override onlyRewardConfiguratorOrAdmin {
    require(address(config.controller) != address(0));
    require(address(getRewardController()) == address(0));
    _initialize(IRewardController(config.controller), 0, config.baselinePercentage, config.poolName);
  }

  function initializedRewardPoolWith() external view override returns (InitRewardPoolData memory) {
    return InitRewardPoolData(IRewardController(getRewardController()), getPoolName(), getBaselinePercentage());
  }
}
SafeERC20.sol 61 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import './IERC20.sol';
import './Address.sol';

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  using Address for address;

  function safeTransfer(
    IERC20 token,
    address to,
    uint256 value
  ) internal {
    callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
  }

  function safeTransferFrom(
    IERC20 token,
    address from,
    address to,
    uint256 value
  ) internal {
    callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
  }

  function safeApprove(
    IERC20 token,
    address spender,
    uint256 value
  ) internal {
    require(
      (value == 0) || (token.allowance(address(this), spender) == 0),
      'SafeERC20: approve from non-zero to non-zero allowance'
    );
    callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
  }

  function callOptionalReturn(IERC20 token, bytes memory data) private {
    require(address(token).isContract(), 'SafeERC20: call to non-contract');

    // solhint-disable-next-line avoid-low-level-calls
    (bool success, bytes memory returndata) = address(token).call(data);
    require(success, 'SafeERC20: low-level call failed');

    if (returndata.length > 0) {
      // Return data is optional
      // solhint-disable-next-line max-line-length
      require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed');
    }
  }
}
PoolTokenConfig.sol 13 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

struct PoolTokenConfig {
  // Address of the associated lending pool
  address pool;
  // Address of the treasury
  address treasury;
  // Address of the underlying asset
  address underlyingAsset;
  // Decimals of the underlying asset
  uint8 underlyingDecimals;
}
IInitializablePoolToken.sol 25 lines
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.4;

import './PoolTokenConfig.sol';

/// @dev Interface for the initialize function on PoolToken or DebtToken
interface IInitializablePoolToken {
  event Initialized(
    address indexed underlyingAsset,
    address indexed pool,
    address treasury,
    string tokenName,
    string tokenSymbol,
    uint8 tokenDecimals,
    bytes params
  );

  /// @dev Initializes the depositToken
  function initialize(
    PoolTokenConfig calldata config,
    string calldata tokenName,
    string calldata tokenSymbol,
    bytes calldata params
  ) external;
}

Read Contract

DOMAIN_SEPARATOR 0x3644e515 → bytes32
EIP712_REVISION 0x78160376 → bytes
PERMIT_TYPEHASH 0x30adf81f → bytes32
POOL 0x7535d246 → address
REVISION 0xdde43cba → uint256
UNDERLYING_ASSET_ADDRESS 0xb16a19de → address
_nonces 0xb9844d8d → uint256
addRewardProvider 0xb6fe2e9c
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
calcRewardFor 0x8abc37d3 → uint256, uint256, uint32
collateralBalanceOf 0xc964a2f2 → uint256
decimals 0x313ce567 → uint8
getBaselinePercentage 0x4d25c4f1 → uint16
getIncentivesController 0x75d26413 → address
getPoolName 0xd2993983 → string
getRate 0x679aefce → uint256
getRewardController 0x92efda79 → address
getScaleIndex 0x9cfa7768 → uint256
getScaledUserBalanceAndSupply 0x0afbcdc9 → uint256, uint256
getTreasury 0x3b19e84a → address
initializedRewardPoolWith 0x3a7d4089 → tuple
isPaused 0xb187bd26 → bool
name 0x06fdde03 → string
nonces 0x7ecebe00 → uint256
rewardedBalanceOf 0xa9dd7702 → uint256
scaledBalanceOf 0x1da24f3e → uint256
scaledTotalSupply 0xb1bf962d → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256

Write Contract 35 functions

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

addStakeOperator 0x296637ce
address addr
addSubBalanceOperator 0x3079fac2
address addr
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
attachedToRewardController 0x55f4f197
No parameters
returns: uint256
burn 0xd7020d0a
address user
address receiverOfUnderlying
uint256 amount
uint256 index
claimRewardFor 0xff85a2ba
address holder
returns: uint256, uint32, bool
claimRewardWithLimitFor 0xa8346a8c
address holder
uint256 baseAmount
uint256 limit
uint16 minPct
returns: uint256, uint32, bool, uint256
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
detachedFromRewardController 0x0746363d
No parameters
returns: uint256
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
initialize 0x31e72661
tuple config
string name
string symbol
bytes params
initializeRewardPool 0xea4b810d
tuple config
lockSubBalance 0x6ea9ba54
address provider
uint256 scaledAmount
mint 0xdbf110a7
address user
uint256 amount
uint256 index
bool repayOverdraft
returns: bool
mintToTreasury 0x7df5bd3b
uint256 amount
uint256 index
permit 0xd505accf
address owner
address spender
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
provideSubBalance 0xfc147d4a
address provider
address recipient
uint256 scaledAmount
removeRewardProvider 0x1dd0f483
address provider
removeSubBalanceOperator 0x2f8dc4ea
address addr
replaceSubBalance 0x4794c1d1
address prevProvider
address recipient
uint256 prevScaledAmount
address newProvider
uint256 newScaledAmount
returns: uint256
returnSubBalance 0x20531b17
address provider
address recipient
uint256 scaledAmount
bool preferOverdraft
returns: uint256
setBaselinePercentage 0x4800df8c
uint16 factor
setIncentivesController 0xe655dbd8
address hook
setOverdraftTolerancePct 0xf6fc84d2
uint16 overdraftTolerancePct
setPaused 0x16c38b3c
bool paused
transfer 0xa9059cbb
address recipient
uint256 amount
returns: bool
transferFrom 0x23b872dd
address sender
address recipient
uint256 amount
returns: bool
transferLockedBalance 0x568ed0ed
address from
address to
uint256 scaledAmount
transferOnLiquidation 0x59e67e92
address user
address receiver
uint256 amount
uint256 index
bool transferUnderlying
returns: bool
transferUnderlyingTo 0x4efecaa5
address target
uint256 amount
returns: uint256
unlockSubBalance 0x7c6ad541
address provider
uint256 scaledAmount
address transferTo
updateBaseline 0x0ca2103d
uint256 baseline
returns: bool, uint256
updatePool 0xe3161ddd
No parameters
updateTreasury 0x9c769787
No parameters
useAllowance 0x7fcea80e
address owner
uint256 subtractedValue
returns: bool

Recent Transactions

No transactions found for this address