diff --git a/deploy/StrategyAaveFlashloan.ts b/deploy/StrategyAaveFlashloan.ts index 993ab7b..433f178 100644 --- a/deploy/StrategyAaveFlashloan.ts +++ b/deploy/StrategyAaveFlashloan.ts @@ -20,6 +20,8 @@ const func: DeployFunction = async ({ deployments, ethers }) => { from: deployer.address, }); + console.log('success: deployed flashminlib', flashMintLib.address); + const poolManager = new Contract( CONTRACTS_ADDRESSES[1].agEUR.collaterals!.USDC.PoolManager as string, Interfaces.PoolManager_Interface, @@ -51,6 +53,8 @@ const func: DeployFunction = async ({ deployments, ethers }) => { libraries: { FlashMintLib: flashMintLib.address }, }); + console.log('success: deployed strategy implementation', strategyImplementation.address); + const initializeData = AaveFlashloanStrategy__factory.createInterface().encodeFunctionData('initialize', [ poolManager.address, '0x8Cae0596bC1eD42dc3F04c4506cfe442b3E74e27', diff --git a/deployments/mainnet/.chainId b/deployments/mainnet/.chainId new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/deployments/mainnet/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/deployments/mainnet/AaveFlashloanStrategy.json b/deployments/mainnet/AaveFlashloanStrategy.json new file mode 100644 index 0000000..d92a64b --- /dev/null +++ b/deployments/mainnet/AaveFlashloanStrategy.json @@ -0,0 +1,438 @@ +{ + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "receipt": { + "to": null, + "from": "0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185", + "contractAddress": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "transactionIndex": 139, + "gasUsed": "1647056", + "logsBloom": "0x20000004000000000800000000000000480000000000000002200000000000000000000008000000000000001000000000000400000000000000800000200000000020100000000008000008000003000000000000000004000000000001001010000000020000400000000000000880000000800000400000010000000000000200030000001200000001000000010100100002010000000100000000a04200020000000000200000000020000000000800020000000000001000000000081001000020020000000800000000000000004902000c00000100000000000020000010040001402000000000000000002000000000002000000000000000040000", + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89", + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "logs": [ + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000cda39b74054effb230156f21b334e50295ca8df4" + ], + "data": "0x", + "logIndex": 223, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041", + "0x0000000000000000000000000c2553e4b9dfa9f83b1a6d3eab96c4baab42d430", + "0x000000000000000000000000fda462548ce04282f4b6d6619823a7c64fdc0185" + ], + "data": "0x", + "logIndex": 224, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041", + "0x000000000000000000000000dc4e6dfe07efca50a197df15d9200883ef4eb1c8", + "0x000000000000000000000000fda462548ce04282f4b6d6619823a7c64fdc0185" + ], + "data": "0x", + "logIndex": 225, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562", + "0x000000000000000000000000e9f183fc656656f1f17af1f2b0df79b8ff9ad8ed", + "0x000000000000000000000000fda462548ce04282f4b6d6619823a7c64fdc0185" + ], + "data": "0x", + "logIndex": 226, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0x5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562" + ], + "data": "0x", + "logIndex": 227, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562" + ], + "data": "0x", + "logIndex": 228, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0xfc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab", + "0x000000000000000000000000cc617c6f9725eacc993ac626c7efc6b96476916e", + "0x000000000000000000000000fda462548ce04282f4b6d6619823a7c64fdc0185" + ], + "data": "0x", + "logIndex": 229, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff", + "0xfc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041" + ], + "data": "0x", + "logIndex": 230, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x000000000000000000000000e9f183fc656656f1f17af1f2b0df79b8ff9ad8ed" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 231, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000007d2768de32b0b80b7a3454c06bdac94a69ddc7a9" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 232, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0xBcca60bB61934080951369a648Fb03DF4F96263C", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000007d2768de32b0b80b7a3454c06bdac94a69ddc7a9" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 233, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000001eb4cf3a948e7d72a198fe073ccb8c7a948cd853" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 234, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x4da27a545c0c5B758a6BA100e3a049001de870f5", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000001111111254fb6c44bac0bed2854e76f90643097d" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 235, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000001111111254fb6c44bac0bed2854e76f90643097d" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 236, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x0000000000000000000000001f847fd5e08fb559a69280a14e7e904e6dbff81f", + "0x0000000000000000000000007d2768de32b0b80b7a3454c06bdac94a69ddc7a9" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 237, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + }, + { + "transactionIndex": 139, + "blockNumber": 14538316, + "transactionHash": "0x2f7864b8b665f314dbf3c2532c82b33ff16c0dd08bfdf2facf2dd16726341bd3", + "address": "0x1F847FD5E08Fb559A69280A14e7E904e6DBfF81f", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d941ef0d3bba4ad67dbfbcee5262f4cee53a32b", + "logIndex": 238, + "blockHash": "0x318846893c5e6c31f16009b7f1f98cd3823ace4582161e19019d7354e4e30f89" + } + ], + "blockNumber": 14538316, + "cumulativeGasUsed": "12175788", + "status": 1, + "byzantium": true + }, + "args": [ + "0xcDA39B74054EFFB230156f21b334E50295Ca8df4", + "0x1D941EF0D3Bba4ad67DBfBCeE5262F4CEE53A32b", + "0xf8453e7c000000000000000000000000e9f183fc656656f1f17af1f2b0df79b8ff9ad8ed0000000000000000000000008cae0596bc1ed42dc3f04c4506cfe442b3e74e27000000000000000000000000dc4e6dfe07efca50a197df15d9200883ef4eb1c80000000000000000000000000c2553e4b9dfa9f83b1a6d3eab96c4baab42d43000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cc617c6f9725eacc993ac626c7efc6b96476916e" + ], + "numDeployments": 1, + "solcInputHash": "cca16ad1f0f505ca7a8330fb58e463cc", + "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. It is fully forked from OpenZeppelin `TransparentUpgradeableProxy` To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/external/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":3500},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n Address.isContract(IBeacon(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xabf3f59bc0e5423eae45e459dbe92e7052c6983628d39008590edc852a62f94a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0x0edeb16b9821ae2b16e9d69c383b38d3ad2fbb3e0c06cf809a0786d96e602551\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"},\"contracts/external/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin. It is fully forked from OpenZeppelin\\n * `TransparentUpgradeableProxy`\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x541c923cc8e95e2f62a63280449729ed9ed7b0c33e9191c5ee25ee27df4a3d52\",\"license\":\"GPL-3.0\"}},\"version\":1}", + "bytecode": "0x608060405260405162001005380380620010058339810160408190526200002691620004d4565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd62000607565b60008051602062000fbe833981519152146200007557620000756200065c565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610462000607565b60008051602062000f9e83398151915214620000d357620000d36200065c565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002701760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e9838360405180606001604052806027815260200162000fde6027913962000381565b9392505050565b60006200021a60008051602062000f9e83398151915260001b6200046760201b620002181760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd60008051602062000f9e83398151915260001b6200046760201b620002181760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200029c1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd60008051602062000fbe83398151915260001b6200046760201b620002181760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b031685604051620004089190620005b4565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b9190620005d2565b80516001600160a01b0381168114620004cf57600080fd5b919050565b600080600060608486031215620004ea57600080fd5b620004f584620004b7565b92506200050560208501620004b7565b60408501519092506001600160401b03808211156200052357600080fd5b818601915086601f8301126200053857600080fd5b8151818111156200054d576200054d62000672565b604051601f8201601f19908116603f0116810190838211818310171562000578576200057862000672565b816040528281528960208487010111156200059257600080fd5b620005a58360208301602088016200062d565b80955050505050509250925092565b60008251620005c88184602087016200062d565b9190910192915050565b6020815260008251806020840152620005f38160408501602087016200062d565b601f01601f19169190910160400192915050565b6000828210156200062857634e487b7160e01b600052601160045260246000fd5b500390565b60005b838110156200064a57818101518382015260200162000630565b838111156200011d5750506000910152565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61090680620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100d9578063f851a440146100f95761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61010e565b005b61006b61010e565b34801561008157600080fd5b5061006b610090366004610772565b610128565b61006b6100a336600461078d565b61016f565b3480156100b457600080fd5b506100bd6101e0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100e557600080fd5b5061006b6100f4366004610772565b61021b565b34801561010557600080fd5b506100bd610245565b6101166102ab565b610126610121610365565b61036f565b565b610130610393565b6001600160a01b0316336001600160a01b0316141561016757610164816040518060200160405280600081525060006103c6565b50565b61016461010e565b610177610393565b6001600160a01b0316336001600160a01b031614156101d8576101d38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506103c6915050565b505050565b6101d361010e565b60006101ea610393565b6001600160a01b0316336001600160a01b031614156102105761020b610365565b905090565b61021861010e565b90565b610223610393565b6001600160a01b0316336001600160a01b0316141561016757610164816103f1565b600061024f610393565b6001600160a01b0316336001600160a01b031614156102105761020b610393565b606061029583836040518060600160405280602781526020016108aa60279139610445565b9392505050565b6001600160a01b03163b151590565b6102b3610393565b6001600160a01b0316336001600160a01b031614156101265760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061020b610539565b3660008037600080366000845af43d6000803e80801561038e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103cf83610561565b6000825111806103dc5750805b156101d3576103eb8383610270565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a610393565b604080516001600160a01b03928316815291841660208301520160405180910390a1610164816105a1565b60606001600160a01b0384163b6104c45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161035c565b600080856001600160a01b0316856040516104df9190610810565b600060405180830381855af49150503d806000811461051a576040519150601f19603f3d011682016040523d82523d6000602084013e61051f565b606091505b509150915061052f828286610679565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103b7565b61056a816106b2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661061d5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161035c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905550565b60608315610688575081610295565b8251156106985782518084602001fd5b8160405162461bcd60e51b815260040161035c919061082c565b6001600160a01b0381163b61072f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161035c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610640565b80356001600160a01b038116811461076d57600080fd5b919050565b60006020828403121561078457600080fd5b61029582610756565b6000806000604084860312156107a257600080fd5b6107ab84610756565b9250602084013567ffffffffffffffff808211156107c857600080fd5b818601915086601f8301126107dc57600080fd5b8135818111156107eb57600080fd5b8760208285010111156107fd57600080fd5b6020830194508093505050509250925092565b6000825161082281846020870161087d565b9190910192915050565b602081526000825180602084015261084b81604085016020870161087d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60005b83811015610898578181015183820152602001610880565b838111156103eb575050600091015256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122096753dd4a00f6d80e827dbf43c817069a35ee05d2f7b9dc4471b2957262b602064736f6c63430008070033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100d9578063f851a440146100f95761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61010e565b005b61006b61010e565b34801561008157600080fd5b5061006b610090366004610772565b610128565b61006b6100a336600461078d565b61016f565b3480156100b457600080fd5b506100bd6101e0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100e557600080fd5b5061006b6100f4366004610772565b61021b565b34801561010557600080fd5b506100bd610245565b6101166102ab565b610126610121610365565b61036f565b565b610130610393565b6001600160a01b0316336001600160a01b0316141561016757610164816040518060200160405280600081525060006103c6565b50565b61016461010e565b610177610393565b6001600160a01b0316336001600160a01b031614156101d8576101d38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506103c6915050565b505050565b6101d361010e565b60006101ea610393565b6001600160a01b0316336001600160a01b031614156102105761020b610365565b905090565b61021861010e565b90565b610223610393565b6001600160a01b0316336001600160a01b0316141561016757610164816103f1565b600061024f610393565b6001600160a01b0316336001600160a01b031614156102105761020b610393565b606061029583836040518060600160405280602781526020016108aa60279139610445565b9392505050565b6001600160a01b03163b151590565b6102b3610393565b6001600160a01b0316336001600160a01b031614156101265760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061020b610539565b3660008037600080366000845af43d6000803e80801561038e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103cf83610561565b6000825111806103dc5750805b156101d3576103eb8383610270565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a610393565b604080516001600160a01b03928316815291841660208301520160405180910390a1610164816105a1565b60606001600160a01b0384163b6104c45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161035c565b600080856001600160a01b0316856040516104df9190610810565b600060405180830381855af49150503d806000811461051a576040519150601f19603f3d011682016040523d82523d6000602084013e61051f565b606091505b509150915061052f828286610679565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103b7565b61056a816106b2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661061d5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161035c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905550565b60608315610688575081610295565b8251156106985782518084602001fd5b8160405162461bcd60e51b815260040161035c919061082c565b6001600160a01b0381163b61072f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161035c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610640565b80356001600160a01b038116811461076d57600080fd5b919050565b60006020828403121561078457600080fd5b61029582610756565b6000806000604084860312156107a257600080fd5b6107ab84610756565b9250602084013567ffffffffffffffff808211156107c857600080fd5b818601915086601f8301126107dc57600080fd5b8135818111156107eb57600080fd5b8760208285010111156107fd57600080fd5b6020830194508093505050509250925092565b6000825161082281846020870161087d565b9190910192915050565b602081526000825180602084015261084b81604085016020870161087d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60005b83811015610898578181015183820152602001610880565b838111156103eb575050600091015256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122096753dd4a00f6d80e827dbf43c817069a35ee05d2f7b9dc4471b2957262b602064736f6c63430008070033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. It is fully forked from OpenZeppelin `TransparentUpgradeableProxy` To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/mainnet/AaveFlashloanStrategyImplementation.json b/deployments/mainnet/AaveFlashloanStrategyImplementation.json new file mode 100644 index 0000000..531609c --- /dev/null +++ b/deployments/mainnet/AaveFlashloanStrategyImplementation.json @@ -0,0 +1,1678 @@ +{ + "address": "0xcDA39B74054EFFB230156f21b334E50295Ca8df4", + "abi": [ + { + "anonymous": false, + "inputs": [], + "name": "EmergencyExitActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "profit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "loss", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "debtPayment", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "debtOutstanding", + "type": "uint256" + } + ], + "name": "Harvested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "debtThreshold", + "type": "uint256" + } + ], + "name": "UpdatedDebtThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "activated", + "type": "bool" + } + ], + "name": "UpdatedIsRewardActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "UpdatedMaxReportDelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "UpdatedMinReportDelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_rewardAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_minimumAmountMoved", + "type": "uint256" + } + ], + "name": "UpdatedRewardAmountAndMinimumAmountMoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "rewards", + "type": "address" + } + ], + "name": "UpdatedRewards", + "type": "event" + }, + { + "inputs": [], + "name": "BASE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GUARDIAN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEEPER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "POOLMANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SECONDSPERYEAR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_guardian", + "type": "address" + } + ], + "name": "addGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "boolParams", + "outputs": [ + { + "internalType": "bool", + "name": "automaticallyComputeCollatRatio", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isFlashMintActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "withdrawCheck", + "type": "bool" + }, + { + "internalType": "bool", + "name": "cooldownStkAave", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cooldownSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "daiBorrowCollatRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "debtThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "discountFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyExit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "estimatedAPR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "estimatedTotalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "deposits", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrows", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "harvest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "borrowInit", + "type": "uint256" + } + ], + "name": "harvest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_poolManager", + "type": "address" + }, + { + "internalType": "contract IReserveInterestRateStrategy", + "name": "interestRateStrategyAddress_", + "type": "address" + }, + { + "internalType": "address", + "name": "governor", + "type": "address" + }, + { + "internalType": "address", + "name": "guardian", + "type": "address" + }, + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "manualDeleverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "manualReleaseWant", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxBorrowCollatRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxCollatRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxIterations", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minWant", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onFlashLoan", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "poolManager", + "outputs": [ + { + "internalType": "contract IPoolManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "r0", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactor", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "revokeGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minAmountOut", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "sellRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setAavePoolVariables", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "automaticallyComputeCollatRatio", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isFlashMintActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "withdrawCheck", + "type": "bool" + }, + { + "internalType": "bool", + "name": "cooldownStkAave", + "type": "bool" + } + ], + "internalType": "struct AaveFlashloanStrategy.BoolParams", + "name": "_boolParams", + "type": "tuple" + } + ], + "name": "setBoolParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_targetCollatRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxCollatRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxBorrowCollatRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_daiBorrowCollatRatio", + "type": "uint256" + } + ], + "name": "setCollateralTargets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_debtThreshold", + "type": "uint256" + } + ], + "name": "setDebtThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_discountFactor", + "type": "uint256" + } + ], + "name": "setDiscountFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setEmergencyExit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minWant", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minRatio", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "_maxIterations", + "type": "uint8" + } + ], + "name": "setMinsAndMaxs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "slope1", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "slope2", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "sweep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "targetCollatRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "uOptimal", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unstakeWindow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "want", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wantBase", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amountNeeded", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "amountFreed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_loss", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x4db154e22a28ecb1be5de61d8f3b5efcaeb3e32b13c5ba84a02a40ab5cb9c9e6", + "receipt": { + "to": null, + "from": "0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185", + "contractAddress": "0xcDA39B74054EFFB230156f21b334E50295Ca8df4", + "transactionIndex": 180, + "gasUsed": "5362061", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x27ea6659cee4cbb4d25a0b2cb03b70c446994f58130b855a6477cde4a91bad05", + "transactionHash": "0x4db154e22a28ecb1be5de61d8f3b5efcaeb3e32b13c5ba84a02a40ab5cb9c9e6", + "logs": [], + "blockNumber": 14538315, + "cumulativeGasUsed": "21647110", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "cca16ad1f0f505ca7a8330fb58e463cc", + "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[],\"name\":\"EmergencyExitActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"profit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"loss\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"debtPayment\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"debtOutstanding\",\"type\":\"uint256\"}],\"name\":\"Harvested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"debtThreshold\",\"type\":\"uint256\"}],\"name\":\"UpdatedDebtThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"activated\",\"type\":\"bool\"}],\"name\":\"UpdatedIsRewardActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"UpdatedMaxReportDelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delay\",\"type\":\"uint256\"}],\"name\":\"UpdatedMinReportDelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_rewardAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_minimumAmountMoved\",\"type\":\"uint256\"}],\"name\":\"UpdatedRewardAmountAndMinimumAmountMoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rewards\",\"type\":\"address\"}],\"name\":\"UpdatedRewards\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GUARDIAN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEEPER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"POOLMANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SECONDSPERYEAR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"}],\"name\":\"addGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"boolParams\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"automaticallyComputeCollatRatio\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFlashMintActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"withdrawCheck\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"cooldownStkAave\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cooldownSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"daiBorrowCollatRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"debtThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"discountFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyExit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"estimatedAPR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"estimatedTotalAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"deposits\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"harvest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"borrowInit\",\"type\":\"uint256\"}],\"name\":\"harvest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_poolManager\",\"type\":\"address\"},{\"internalType\":\"contract IReserveInterestRateStrategy\",\"name\":\"interestRateStrategyAddress_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"governor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"keepers\",\"type\":\"address[]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isActive\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"manualDeleverage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"manualReleaseWant\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxBorrowCollatRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxCollatRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxIterations\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minWant\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initiator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onFlashLoan\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"poolManager\",\"outputs\":[{\"internalType\":\"contract IPoolManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"r0\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reserveFactor\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guardian\",\"type\":\"address\"}],\"name\":\"revokeGuardian\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountOut\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"sellRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"setAavePoolVariables\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"automaticallyComputeCollatRatio\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isFlashMintActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"withdrawCheck\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"cooldownStkAave\",\"type\":\"bool\"}],\"internalType\":\"struct AaveFlashloanStrategy.BoolParams\",\"name\":\"_boolParams\",\"type\":\"tuple\"}],\"name\":\"setBoolParams\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_targetCollatRatio\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxCollatRatio\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_maxBorrowCollatRatio\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_daiBorrowCollatRatio\",\"type\":\"uint256\"}],\"name\":\"setCollateralTargets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_debtThreshold\",\"type\":\"uint256\"}],\"name\":\"setDebtThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_discountFactor\",\"type\":\"uint256\"}],\"name\":\"setDiscountFactor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"setEmergencyExit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minWant\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minRatio\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"_maxIterations\",\"type\":\"uint8\"}],\"name\":\"setMinsAndMaxs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slope1\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slope2\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"sweep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"targetCollatRatio\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"uOptimal\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unstakeWindow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"want\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wantBase\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amountNeeded\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountFreed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_loss\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Yearn Finance (https://etherscan.io/address/0xd4E94061183b2DBF24473F28A3559cf4dE4459Db#code) but heavily reviewed and modified by Angle Core Team\",\"details\":\"Angle strategies computes the optimal collateral ratio based on AAVE rewards for deposits and borrows\",\"kind\":\"dev\",\"methods\":{\"addGuardian(address)\":{\"params\":{\"_guardian\":\"New guardian address\"}},\"estimatedTotalAssets()\":{\"details\":\"It sums the effective deposit amount to the rewards accumulated\"},\"getCurrentPosition()\":{\"details\":\"The actual amount brought is `deposits - borrows`\"},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.\"},\"harvest(uint256)\":{\"params\":{\"borrowInit\":\"Approximate optimal borrows to have faster convergence on the NR method\"}},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"initialize(address,address,address,address,address[])\":{\"params\":{\"_poolManager\":\"Address of the `PoolManager` lending to this strategy\",\"governor\":\"Governor address of the protocol\",\"guardian\":\"Address of the guardian\",\"interestRateStrategyAddress_\":\"Address of the `InterestRateStrategy` defining borrow rates for the collateral\",\"keepers\":\"List of the addresses with keeper privilege\"}},\"isActive()\":{\"returns\":{\"_0\":\"True if the strategy is actively managing a position.\"}},\"manualDeleverage(uint256)\":{\"params\":{\"amount\":\"Amount of `want` to withdraw/repay\"}},\"manualReleaseWant(uint256)\":{\"params\":{\"amount\":\"Amount of `want` to withdraw\"}},\"onFlashLoan(address,address,uint256,uint256,bytes)\":{\"details\":\"If everything went smoothly, will return `keccak256(\\\"ERC3156FlashBorrower.onFlashLoan\\\")`\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.\"},\"revokeGuardian(address)\":{\"params\":{\"guardian\":\"Old guardian address to revoke\"}},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.\"},\"sellRewards(uint256,bytes)\":{\"params\":{\"minAmountOut\":\"Minimum amount of `want` to receive for the swap to happen\",\"payload\":\"Bytes needed for 1Inch API. Tokens swapped should be: stkAave -> `want` or Aave -> `want`\"}},\"setAavePoolVariables()\":{\"details\":\"No access control needed because they fetch the values from Aave directly. If it changes there, it will need to be updated here tooWe expect the values concerned not to be often modified\"},\"setDebtThreshold(uint256)\":{\"details\":\"By default this is 0, meaning any losses would cause a harvest which will subsequently report the loss to the Manager for tracking.\",\"params\":{\"_debtThreshold\":\"How big of a loss this Strategy may carry without\"}},\"setEmergencyExit()\":{\"details\":\"This may only be called by the `PoolManager`, because when calling this the `PoolManager` should at the same time update the debt ratioThis function can only be called once by the `PoolManager` contractSee `poolManager.setEmergencyExit()` and `harvest()` for further details.\"},\"sweep(address,address)\":{\"details\":\"Implement `_protectedTokens()` to specify any additional tokens that should be protected from sweeping in addition to `want`.\",\"params\":{\"_token\":\"The token to transfer out of this `PoolManager`.\",\"to\":\"Address to send the tokens to.\"}},\"withdraw(uint256)\":{\"details\":\"This may only be called by the `PoolManager`\",\"params\":{\"_amountNeeded\":\"How much `want` to withdraw.\"},\"returns\":{\"_loss\":\"Any realized losses\",\"amountFreed\":\"How much `want` withdrawn.\"}}},\"title\":\"AaveFlashloanStrategy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN_ROLE()\":{\"notice\":\"Role for guardians and governors\"},\"KEEPER_ROLE()\":{\"notice\":\"Role for keepers\"},\"POOLMANAGER_ROLE()\":{\"notice\":\"Role for `PoolManager` only\"},\"addGuardian(address)\":{\"notice\":\"Adds a new guardian address\"},\"boolParams()\":{\"notice\":\"Struct with some boolean parameters of the contract These parameters are packed in a struct for efficiency of SLOAD operations\"},\"daiBorrowCollatRatio()\":{\"notice\":\"Parameter used for flash mints\"},\"debtThreshold()\":{\"notice\":\"Use this to adjust the threshold at which running a debt causes a harvest trigger. See `setDebtThreshold()` for more details\"},\"discountFactor()\":{\"notice\":\"Discount factor applied to the StkAAVE price\"},\"emergencyExit()\":{\"notice\":\"See note on `setEmergencyExit()`\"},\"estimatedTotalAssets()\":{\"notice\":\"Estimates the total assets controlled by the strategy\"},\"getCurrentPosition()\":{\"notice\":\"Get the current position of the strategy: that is to say the amount deposited and the amount borrowed on Aave\"},\"harvest()\":{\"notice\":\"Harvests the Strategy, recognizing any profits or losses and adjusting the Strategy's position.\"},\"harvest(uint256)\":{\"notice\":\"Harvests the Strategy, recognizing any profits or losses and adjusting the Strategy's position.\"},\"initialize(address,address,address,address,address[])\":{\"notice\":\"Constructor of the `Strategy`\"},\"isActive()\":{\"notice\":\"Provides an indication of whether this strategy is currently \\\"active\\\" in that it is managing an active position, or will manage a position in the future. This should correlate to `harvest()` activity, so that Harvest events can be tracked externally by indexing agents.\"},\"manualDeleverage(uint256)\":{\"notice\":\"Emergency function that we can use to deleverage manually if something is broken\"},\"manualReleaseWant(uint256)\":{\"notice\":\"Emergency function that we can use to deleverage manually if something is broken\"},\"maxBorrowCollatRatio()\":{\"notice\":\"Maximum the Aave protocol will let us borrow\"},\"maxCollatRatio()\":{\"notice\":\"Closest to liquidation we'll risk\"},\"maxIterations()\":{\"notice\":\"Max number of iterations possible for the computation of the optimal lever\"},\"minRatio()\":{\"notice\":\"Minimum gap between the collat ratio and the target collat ratio before rectifying it\"},\"minWant()\":{\"notice\":\"Minimum amount to be moved before a deposit or a borrow\"},\"onFlashLoan(address,address,uint256,uint256,bytes)\":{\"notice\":\"Flashload callback, as defined by EIP-3156We check that the call is coming from the DAI lender and then execute the load logic\"},\"poolManager()\":{\"notice\":\"Reference to the protocol's collateral `PoolManager`\"},\"revokeGuardian(address)\":{\"notice\":\"Revokes the guardian role\"},\"sellRewards(uint256,bytes)\":{\"notice\":\"Swap earned stkAave or Aave for `want` through 1Inch\"},\"setAavePoolVariables()\":{\"notice\":\"Retrieves lending pool variables for `want`. Those variables are mostly used in the function to compute the optimal borrow amount\"},\"setBoolParams((bool,bool,bool,bool))\":{\"notice\":\"Sets all boolean parameters related to cooldown, withdraw check, flash loan and so on\"},\"setCollateralTargets(uint256,uint256,uint256,uint256)\":{\"notice\":\"Sets collateral targets and value for collateral ratio\"},\"setDebtThreshold(uint256)\":{\"notice\":\"Sets how far the Strategy can go into loss without a harvest and report being required.\"},\"setDiscountFactor(uint256)\":{\"notice\":\"Sets the discount factor for the StkAAVE price\"},\"setEmergencyExit()\":{\"notice\":\"Activates emergency exit. Once activated, the Strategy will exit its position upon the next harvest, depositing all funds into the Manager as quickly as is reasonable given on-chain conditions.\"},\"setMinsAndMaxs(uint256,uint256,uint8)\":{\"notice\":\"Sets `minWant`, `minRatio` and `maxItrations` values\"},\"sweep(address,address)\":{\"notice\":\"Removes tokens from this Strategy that are not the type of tokens managed by this Strategy. This may be used in case of accidentally sending the wrong kind of token to this Strategy. Tokens will be sent to `governance()`. This will fail if an attempt is made to sweep `want`, or any tokens that are protected by this Strategy. This may only be called by governance.\"},\"targetCollatRatio()\":{\"notice\":\"LTV the strategy is going to lever up to\"},\"want()\":{\"notice\":\"Reference to the ERC20 farmed by this strategy\"},\"wantBase()\":{\"notice\":\"Base of the ERC20 token farmed by this strategy\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws `_amountNeeded` to `poolManager`.\"}},\"notice\":\"This strategy is used to optimize lending yield on Aave by taking some form or recursivity that is to say by borrowing to maximize Aave rewards\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol\":\"AaveFlashloanStrategy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":3500},\"remappings\":[]},\"sources\":{\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n // getRoundData and latestRoundData should both raise \\\"No data present\\\"\\n // if they do not have data to report, instead of returning unset values\\n // which could be misinterpreted as actual reported values.\\n function getRoundData(uint80 _roundId)\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function latestRoundData()\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n}\\n\",\"keccak256\":\"0xf2b6c9adb3552254df1445b73563cf014434ff5e78663e9b961b6c059506ceb5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !AddressUpgradeable.isContract(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x372b0bc04e3b4c074559bbbfb1317afddb56de5504158ca25a7f9cd403980445\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55cf2bd9fc76704ddcdc19834cd288b7de00fc0f298a40ea16a954ae8991db2d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x398d3323c1932a5986bf36be7c57593e121e69d5db5b6574b4ee0d031443de37\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashBorrower.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC3156 FlashBorrower, as defined in\\n * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC3156FlashBorrower {\\n /**\\n * @dev Receive a flash loan.\\n * @param initiator The initiator of the loan.\\n * @param token The loan currency.\\n * @param amount The amount of tokens lent.\\n * @param fee The additional amount of tokens to repay.\\n * @param data Arbitrary data structure, intended to contain user-defined parameters.\\n * @return The keccak256 hash of \\\"ERC3156FlashBorrower.onFlashLoan\\\"\\n */\\n function onFlashLoan(\\n address initiator,\\n address token,\\n uint256 amount,\\n uint256 fee,\\n bytes calldata data\\n ) external returns (bytes32);\\n}\\n\",\"keccak256\":\"0xb218fa8b4b52df590ff19b9f6d08b5be7f3abfc168a0ea33f5eb612f8f4dd989\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC3156FlashBorrower.sol\\\";\\n\\n/**\\n * @dev Interface of the ERC3156 FlashLender, as defined in\\n * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC3156FlashLender {\\n /**\\n * @dev The amount of currency available to be lended.\\n * @param token The loan currency.\\n * @return The amount of `token` that can be borrowed.\\n */\\n function maxFlashLoan(address token) external view returns (uint256);\\n\\n /**\\n * @dev The fee to be charged for a given loan.\\n * @param token The loan currency.\\n * @param amount The amount of tokens lent.\\n * @return The amount of `token` to be charged for the loan, on top of the returned principal.\\n */\\n function flashFee(address token, uint256 amount) external view returns (uint256);\\n\\n /**\\n * @dev Initiate a flash loan.\\n * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.\\n * @param token The loan currency.\\n * @param amount The amount of tokens lent.\\n * @param data Arbitrary data structure, intended to contain user-defined parameters.\\n */\\n function flashLoan(\\n IERC3156FlashBorrower receiver,\\n address token,\\n uint256 amount,\\n bytes calldata data\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x0d9159aa6c1a0d8006fb152b0aee46a0f9b8938575ede1a0d7e186b3bc79c8d7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xbbc8ac883ac3c0078ce5ad3e288fbb3ffcc8a30c3a98c0fda0114d64fc44fca2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2ccf9d2313a313d41a791505f2b5abfdc62191b5d4334f7f7a82691c088a1c87\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xc995bddbca1ae19788db9f8b61e63385edd3fddf89693b612d5abd1a275974d2\",\"license\":\"MIT\"},\"contracts/external/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\nimport \\\"../interfaces/IAccessControl.sol\\\";\\n\\n/**\\n * @dev This contract is fully forked from OpenZeppelin `AccessControl`.\\n * The only difference is the removal of the ERC165 implementation as it's not\\n * needed in Angle.\\n *\\n * Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControl is Context, IAccessControl {\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, _msgSender());\\n _;\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n Strings.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n Strings.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external override {\\n require(account == _msgSender(), \\\"71\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) internal {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, _msgSender());\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) internal {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, _msgSender());\\n }\\n }\\n}\\n\",\"keccak256\":\"0x14f6a40365c520e587ddc50dbe238cea9dcd5f6b99961528376d68566b10051b\",\"license\":\"GPL-3.0\"},\"contracts/external/AccessControlUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\n\\nimport \\\"../interfaces/IAccessControl.sol\\\";\\n\\n/**\\n * @dev This contract is fully forked from OpenZeppelin `AccessControlUpgradeable`.\\n * The only difference is the removal of the ERC165 implementation as it's not\\n * needed in Angle.\\n *\\n * Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```\\n * function foo() public {\\n * require(hasRole(MY_ROLE, msg.sender));\\n * ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it.\\n */\\nabstract contract AccessControlUpgradeable is Initializable, IAccessControl {\\n function __AccessControl_init() internal initializer {\\n __AccessControl_init_unchained();\\n }\\n\\n function __AccessControl_init_unchained() internal initializer {}\\n\\n struct RoleData {\\n mapping(address => bool) members;\\n bytes32 adminRole;\\n }\\n\\n mapping(bytes32 => RoleData) private _roles;\\n\\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Modifier that checks that an account has a specific role. Reverts\\n * with a standardized message including the required role.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n *\\n * _Available since v4.1._\\n */\\n modifier onlyRole(bytes32 role) {\\n _checkRole(role, msg.sender);\\n _;\\n }\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) public view override returns (bool) {\\n return _roles[role].members[account];\\n }\\n\\n /**\\n * @dev Revert with a standard message if `account` is missing `role`.\\n *\\n * The format of the revert reason is given by the following regular expression:\\n *\\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\\n */\\n function _checkRole(bytes32 role, address account) internal view {\\n if (!hasRole(role, account)) {\\n revert(\\n string(\\n abi.encodePacked(\\n \\\"AccessControl: account \\\",\\n StringsUpgradeable.toHexString(uint160(account), 20),\\n \\\" is missing role \\\",\\n StringsUpgradeable.toHexString(uint256(role), 32)\\n )\\n )\\n );\\n }\\n }\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\\n return _roles[role].adminRole;\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external override {\\n require(account == msg.sender, \\\"71\\\");\\n\\n _revokeRole(role, account);\\n }\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event. Note that unlike {grantRole}, this function doesn't perform any\\n * checks on the calling account.\\n *\\n * [WARNING]\\n * ====\\n * This function should only be called from the constructor when setting\\n * up the initial roles for the system.\\n *\\n * Using this function in any other way is effectively circumventing the admin\\n * system imposed by {AccessControl}.\\n * ====\\n */\\n function _setupRole(bytes32 role, address account) internal {\\n _grantRole(role, account);\\n }\\n\\n /**\\n * @dev Sets `adminRole` as ``role``'s admin role.\\n *\\n * Emits a {RoleAdminChanged} event.\\n */\\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal {\\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\\n _roles[role].adminRole = adminRole;\\n }\\n\\n function _grantRole(bytes32 role, address account) internal {\\n if (!hasRole(role, account)) {\\n _roles[role].members[account] = true;\\n emit RoleGranted(role, account, msg.sender);\\n }\\n }\\n\\n function _revokeRole(bytes32 role, address account) internal {\\n if (hasRole(role, account)) {\\n _roles[role].members[account] = false;\\n emit RoleRevoked(role, account, msg.sender);\\n }\\n }\\n\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x161129b95e15270676c09330a5518e4d812b65af30a675a376dc2da463b01238\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\n/// @title IAccessControl\\n/// @author Forked from OpenZeppelin\\n/// @notice Interface for `AccessControl` contracts\\ninterface IAccessControl {\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n function grantRole(bytes32 role, address account) external;\\n\\n function revokeRole(bytes32 role, address account) external;\\n\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0xa1efc50a13a55d4e533ec03ee30006a9ce55df30d33e44fd93a9896765cea2eb\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IPoolManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\n// Struct for the parameters associated to a strategy interacting with a collateral `PoolManager`\\n// contract\\nstruct StrategyParams {\\n // Timestamp of last report made by this strategy\\n // It is also used to check if a strategy has been initialized\\n uint256 lastReport;\\n // Total amount the strategy is expected to have\\n uint256 totalStrategyDebt;\\n // The share of the total assets in the `PoolManager` contract that the `strategy` can access to.\\n uint256 debtRatio;\\n}\\n\\n/// @title IPoolManagerFunctions\\n/// @author Angle Core Team\\n/// @notice Interface for the collateral poolManager contracts handling each one type of collateral for\\n/// a given stablecoin\\n/// @dev Only the functions used in other contracts of the protocol are left here\\ninterface IPoolManagerFunctions {\\n // ============================ Yield Farming ==================================\\n\\n function creditAvailable() external view returns (uint256);\\n\\n function debtOutstanding() external view returns (uint256);\\n\\n function report(\\n uint256 _gain,\\n uint256 _loss,\\n uint256 _debtPayment\\n ) external;\\n\\n // ============================= Getters =======================================\\n\\n function getBalance() external view returns (uint256);\\n\\n function getTotalAsset() external view returns (uint256);\\n}\\n\\n/// @title IPoolManager\\n/// @author Angle Core Team\\n/// @notice Previous interface with additionnal getters for public variables and mappings\\n/// @dev Used in other contracts of the protocol\\ninterface IPoolManager is IPoolManagerFunctions {\\n function stableMaster() external view returns (address);\\n\\n function perpetualManager() external view returns (address);\\n\\n function token() external view returns (address);\\n\\n function totalDebt() external view returns (uint256);\\n\\n function strategies(address _strategy) external view returns (StrategyParams memory);\\n}\\n\",\"keccak256\":\"0xb086d495e7124d898e7b09c59906429c0242e30f2f945c1cd2540aa3bcafb778\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"./IAccessControl.sol\\\";\\n\\n/// @title IStrategy\\n/// @author Inspired by Yearn with slight changes from Angle Core Team\\n/// @notice Interface for yield farming strategies\\ninterface IStrategy is IAccessControl {\\n function estimatedAPR() external view returns (uint256);\\n\\n function poolManager() external view returns (address);\\n\\n function want() external view returns (address);\\n\\n function isActive() external view returns (bool);\\n\\n function estimatedTotalAssets() external view returns (uint256);\\n\\n function harvestTrigger(uint256 callCost) external view returns (bool);\\n\\n function harvest() external;\\n\\n function withdraw(uint256 _amountNeeded) external returns (uint256 amountFreed, uint256 _loss);\\n\\n function setEmergencyExit() external;\\n\\n function addGuardian(address _guardian) external;\\n\\n function revokeGuardian(address _guardian) external;\\n}\\n\",\"keccak256\":\"0x20a728d054df379cf30435b21cf51d8bb7038eb810b42ac2f1ab9496ceec61f6\",\"license\":\"GPL-3.0\"},\"contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol\\\";\\nimport { Math } from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\nimport \\\"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\\\";\\n\\nimport \\\"./AaveLibraries.sol\\\";\\nimport \\\"./AaveInterfaces.sol\\\";\\nimport \\\"../BaseStrategyUpgradeable.sol\\\";\\nimport \\\"./ComputeProfitability.sol\\\";\\n\\n/// @title AaveFlashloanStrategy\\n/// @author Yearn Finance (https://etherscan.io/address/0xd4E94061183b2DBF24473F28A3559cf4dE4459Db#code)\\n/// but heavily reviewed and modified by Angle Core Team\\n/// @notice This strategy is used to optimize lending yield on Aave by taking some form or recursivity that is to say\\n/// by borrowing to maximize Aave rewards\\n/// @dev Angle strategies computes the optimal collateral ratio based on AAVE rewards for deposits and borrows\\n// solhint-disable-next-line max-states-count\\ncontract AaveFlashloanStrategy is BaseStrategyUpgradeable, IERC3156FlashBorrower {\\n using SafeERC20 for IERC20;\\n using Address for address;\\n\\n // =========================== Constant Addresses ==============================\\n\\n /// @notice Router used for swaps\\n address private constant _oneInch = 0x1111111254fb6c44bAC0beD2854e76F90643097d;\\n /// @notice Chainlink oracle used to fetch data\\n AggregatorV3Interface private constant _chainlinkOracle =\\n AggregatorV3Interface(0x547a514d5e3769680Ce22B2361c10Ea13619e8a9);\\n\\n // ========================== Aave Protocol Addresses ==========================\\n\\n IAaveIncentivesController private constant _incentivesController =\\n IAaveIncentivesController(0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5);\\n ILendingPool private constant _lendingPool = ILendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);\\n IProtocolDataProvider private constant _protocolDataProvider =\\n IProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);\\n\\n // ============================== Token Addresses ==============================\\n\\n address private constant _aave = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;\\n IStakedAave private constant _stkAave = IStakedAave(0x4da27a545c0c5B758a6BA100e3a049001de870f5);\\n address private constant _weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\\n address private constant _dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\\n\\n // ============================== Ops Constants ================================\\n\\n uint256 private constant _DEFAULT_COLLAT_TARGET_MARGIN = 0.02 ether;\\n uint256 private constant _DEFAULT_COLLAT_MAX_MARGIN = 0.005 ether;\\n uint256 private constant _LIQUIDATION_WARNING_THRESHOLD = 0.01 ether;\\n uint256 private constant _BPS_WAD_RATIO = 1e14;\\n uint256 private constant _COLLATERAL_RATIO_PRECISION = 1 ether;\\n uint16 private constant _referral = 0;\\n\\n // ========================= Aave Protocol Parameters ==========================\\n\\n IReserveInterestRateStrategy private _interestRateStrategyAddress;\\n uint256 public cooldownSeconds;\\n uint256 public unstakeWindow;\\n int256 public reserveFactor;\\n int256 public slope1;\\n int256 public slope2;\\n int256 public r0;\\n int256 public uOptimal;\\n\\n // =============================== Parameters and Variables ====================\\n\\n /// @notice Maximum the Aave protocol will let us borrow\\n uint256 public maxBorrowCollatRatio;\\n /// @notice LTV the strategy is going to lever up to\\n uint256 public targetCollatRatio;\\n /// @notice Closest to liquidation we'll risk\\n uint256 public maxCollatRatio;\\n /// @notice Parameter used for flash mints\\n uint256 public daiBorrowCollatRatio;\\n /// @notice Minimum amount to be moved before a deposit or a borrow\\n uint256 public minWant;\\n /// @notice Minimum gap between the collat ratio and the target collat ratio before\\n /// rectifying it\\n uint256 public minRatio;\\n /// @notice Discount factor applied to the StkAAVE price\\n uint256 public discountFactor;\\n /// @notice Max number of iterations possible for the computation of the optimal lever\\n uint8 public maxIterations;\\n\\n struct BoolParams {\\n // Whether collateral ratio will be automatically computed\\n bool automaticallyComputeCollatRatio;\\n // Whether Flash mint is active\\n bool isFlashMintActive;\\n // Whether we should check withdrawals\\n bool withdrawCheck;\\n // Whether StkAAVE should be sent to cooldown or simply swapped for Aave all the time\\n bool cooldownStkAave;\\n }\\n /// @notice Struct with some boolean parameters of the contract\\n /// These parameters are packed in a struct for efficiency of SLOAD operations\\n BoolParams public boolParams;\\n\\n // ========================= Supply and Borrow Tokens ==========================\\n\\n IAToken private _aToken;\\n IVariableDebtToken private _debtToken;\\n\\n // ============================ Initializer ====================================\\n\\n /// @notice Constructor of the `Strategy`\\n /// @param _poolManager Address of the `PoolManager` lending to this strategy\\n /// @param interestRateStrategyAddress_ Address of the `InterestRateStrategy` defining borrow rates for the collateral\\n /// @param governor Governor address of the protocol\\n /// @param guardian Address of the guardian\\n /// @param keepers List of the addresses with keeper privilege\\n function initialize(\\n address _poolManager,\\n IReserveInterestRateStrategy interestRateStrategyAddress_,\\n address governor,\\n address guardian,\\n address[] memory keepers\\n ) external {\\n _initialize(_poolManager, governor, guardian, keepers);\\n\\n // Then initializing operational state\\n maxIterations = 6;\\n // Setting mins\\n minWant = 100;\\n minRatio = 0.005 ether;\\n discountFactor = 9000;\\n\\n boolParams = BoolParams({\\n automaticallyComputeCollatRatio: true,\\n isFlashMintActive: true,\\n withdrawCheck: false,\\n cooldownStkAave: true\\n });\\n\\n _interestRateStrategyAddress = interestRateStrategyAddress_;\\n // Setting reward params\\n _setAavePoolVariables();\\n\\n // Set AAVE tokens\\n (address aToken_, , address debtToken_) = _protocolDataProvider.getReserveTokensAddresses(address(want));\\n _aToken = IAToken(aToken_);\\n _debtToken = IVariableDebtToken(debtToken_);\\n\\n // Let collateral targets\\n (uint256 ltv, uint256 liquidationThreshold) = _getProtocolCollatRatios(address(want));\\n targetCollatRatio = liquidationThreshold - _DEFAULT_COLLAT_TARGET_MARGIN;\\n maxCollatRatio = liquidationThreshold - _DEFAULT_COLLAT_MAX_MARGIN;\\n maxBorrowCollatRatio = ltv - _DEFAULT_COLLAT_MAX_MARGIN;\\n (uint256 daiLtv, ) = _getProtocolCollatRatios(_dai);\\n daiBorrowCollatRatio = daiLtv - _DEFAULT_COLLAT_MAX_MARGIN;\\n\\n // Performing all the different approvals possible\\n _approveMaxSpend(address(want), address(_lendingPool));\\n _approveMaxSpend(aToken_, address(_lendingPool));\\n // Approve flashloan spend\\n _approveMaxSpend(_dai, FlashMintLib.LENDER);\\n // Approve swap router spend\\n _approveMaxSpend(address(_stkAave), _oneInch);\\n _approveMaxSpend(_aave, _oneInch);\\n if (address(want) != _dai) {\\n _approveMaxSpend(_dai, address(_lendingPool));\\n }\\n }\\n\\n // ======================= Helper View Functions ===============================\\n\\n /// @notice Estimates the total assets controlled by the strategy\\n /// @dev It sums the effective deposit amount to the rewards accumulated\\n function estimatedTotalAssets() public view override returns (uint256) {\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n return\\n _balanceOfWant() +\\n deposits -\\n borrows +\\n _estimatedStkAaveToWant(\\n _balanceOfStkAave() +\\n _balanceOfAave() +\\n _incentivesController.getRewardsBalance(_getAaveAssets(), address(this))\\n );\\n }\\n\\n /// @notice Get the current position of the strategy: that is to say the amount deposited\\n /// and the amount borrowed on Aave\\n /// @dev The actual amount brought is `deposits - borrows`\\n function getCurrentPosition() public view returns (uint256 deposits, uint256 borrows) {\\n deposits = _balanceOfAToken();\\n borrows = _balanceOfDebtToken();\\n }\\n\\n // ====================== Internal Strategy Functions ==========================\\n\\n /// @notice Frees up profit plus `_debtOutstanding`.\\n /// @param _debtOutstanding Amount to withdraw\\n /// @return _profit Profit freed by the call\\n /// @return _loss Loss discovered by the call\\n /// @return _debtPayment Amount freed to reimburse the debt\\n /// @dev If `_debtOutstanding` is more than we can free we get as much as possible.\\n function _prepareReturn(uint256 _debtOutstanding)\\n internal\\n override\\n returns (\\n uint256 _profit,\\n uint256 _loss,\\n uint256 _debtPayment\\n )\\n {\\n // account for profit / losses\\n uint256 totalDebt = poolManager.strategies(address(this)).totalStrategyDebt;\\n\\n // Assets immediately convertible to want only\\n uint256 amountAvailable = _balanceOfWant();\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n uint256 totalAssets = amountAvailable + deposits - borrows;\\n\\n if (totalDebt > totalAssets) {\\n // we have losses\\n _loss = totalDebt - totalAssets;\\n } else {\\n // we have profit\\n _profit = totalAssets - totalDebt;\\n }\\n\\n // free funds to repay debt + profit to the strategy\\n uint256 amountRequired = _debtOutstanding + _profit;\\n\\n if (amountRequired > amountAvailable) {\\n // we need to free funds\\n // we dismiss losses here, they cannot be generated from withdrawal\\n // but it is possible for the strategy to unwind full position\\n (amountAvailable, ) = _liquidatePosition(amountRequired, amountAvailable, deposits, borrows);\\n\\n if (amountAvailable >= amountRequired) {\\n _debtPayment = _debtOutstanding;\\n // profit remains unchanged unless there is not enough to pay it\\n if (amountRequired - _debtPayment < _profit) {\\n _profit = amountRequired - _debtPayment;\\n }\\n } else {\\n // we were not able to free enough funds\\n if (amountAvailable < _debtOutstanding) {\\n // available funds are lower than the repayment that we need to do\\n _profit = 0;\\n _debtPayment = amountAvailable;\\n // we dont report losses here as the strategy might not be able to return in this harvest\\n // but it will still be there for the next harvest\\n } else {\\n // NOTE: amountRequired is always equal or greater than _debtOutstanding\\n // important to use amountRequired just in case amountAvailable is > amountAvailable\\n _debtPayment = _debtOutstanding;\\n _profit = amountAvailable - _debtPayment;\\n }\\n }\\n } else {\\n _debtPayment = _debtOutstanding;\\n // profit remains unchanged unless there is not enough to pay it\\n if (amountRequired - _debtPayment < _profit) {\\n _profit = amountRequired - _debtPayment;\\n }\\n }\\n }\\n\\n /// @notice Function called by _harvest()\\n function _adjustPosition() internal override {\\n _adjustPosition(type(uint256).max);\\n }\\n\\n /// @notice Function called by _adjustPosition()\\n /// @param guessedBorrow First guess to the borrow amount to maximise revenue\\n /// @dev It computes the optimal collateral ratio and adjusts deposits/borrows accordingly\\n function _adjustPosition(uint256 guessedBorrow) internal override {\\n uint256 _debtOutstanding = poolManager.debtOutstanding();\\n\\n uint256 wantBalance = _balanceOfWant();\\n // deposit available want as collateral\\n if (wantBalance > _debtOutstanding && wantBalance - _debtOutstanding > minWant) {\\n _depositCollateral(wantBalance - _debtOutstanding);\\n // Updating the `wantBalance` value\\n wantBalance = _balanceOfWant();\\n }\\n\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n guessedBorrow = (guessedBorrow == type(uint256).max) ? borrows : guessedBorrow;\\n uint256 _targetCollatRatio;\\n if (boolParams.automaticallyComputeCollatRatio) {\\n _targetCollatRatio = _computeOptimalCollatRatio(\\n wantBalance + deposits - borrows,\\n deposits,\\n borrows,\\n guessedBorrow\\n );\\n } else {\\n _targetCollatRatio = targetCollatRatio;\\n }\\n\\n // check current position\\n uint256 currentCollatRatio = _getCollatRatio(deposits, borrows);\\n\\n // Either we need to free some funds OR we want to be max levered\\n if (_debtOutstanding > wantBalance) {\\n // we should free funds\\n uint256 amountRequired = _debtOutstanding - wantBalance;\\n\\n // NOTE: vault will take free funds during the next harvest\\n _freeFunds(amountRequired, deposits, borrows);\\n } else if (currentCollatRatio < _targetCollatRatio) {\\n // we should lever up\\n if (_targetCollatRatio - currentCollatRatio > minRatio) {\\n // we only act on relevant differences\\n _leverMax(deposits, borrows);\\n }\\n } else if (currentCollatRatio > _targetCollatRatio) {\\n if (currentCollatRatio - _targetCollatRatio > minRatio) {\\n uint256 newBorrow = _getBorrowFromSupply(deposits - borrows, _targetCollatRatio);\\n _leverDownTo(newBorrow, deposits, borrows);\\n }\\n }\\n }\\n\\n /// @notice Liquidates `_amountNeeded` from a position\\n /// @dev For gas efficiency this function calls another internal function\\n function _liquidatePosition(uint256 _amountNeeded) internal override returns (uint256, uint256) {\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n return _liquidatePosition(_amountNeeded, _balanceOfWant(), deposits, borrows);\\n }\\n\\n /// @notice Withdraws `_amountNeeded` of `want` from Aave\\n /// @param _amountNeeded Amount of `want` to free\\n /// @return _liquidatedAmount Amount of `want` available\\n /// @return _loss Difference between `_amountNeeded` and what is actually available\\n function _liquidatePosition(\\n uint256 _amountNeeded,\\n uint256 wantBalance,\\n uint256 deposits,\\n uint256 borrows\\n ) internal returns (uint256 _liquidatedAmount, uint256 _loss) {\\n // NOTE: Maintain invariant `want.balanceOf(this) >= _liquidatedAmount`\\n // NOTE: Maintain invariant `_liquidatedAmount + _loss <= _amountNeeded`\\n if (wantBalance > _amountNeeded) {\\n // if there is enough free want, let's use it\\n return (_amountNeeded, 0);\\n }\\n\\n // we need to free funds\\n uint256 amountRequired = _amountNeeded - wantBalance;\\n _freeFunds(amountRequired, deposits, borrows);\\n // Updating the `wantBalance` variable\\n wantBalance = _balanceOfWant();\\n if (_amountNeeded > wantBalance) {\\n _liquidatedAmount = wantBalance;\\n uint256 diff = _amountNeeded - _liquidatedAmount;\\n if (diff <= minWant) {\\n _loss = diff;\\n }\\n } else {\\n _liquidatedAmount = _amountNeeded;\\n }\\n\\n if (boolParams.withdrawCheck) {\\n require(_amountNeeded == _liquidatedAmount + _loss, \\\"54\\\"); // dev: withdraw safety check\\n }\\n }\\n\\n /// @notice Withdraw as much as we can from Aave\\n /// @return _amountFreed Amount successfully freed\\n function _liquidateAllPositions() internal override returns (uint256 _amountFreed) {\\n (_amountFreed, ) = _liquidatePosition(type(uint256).max);\\n }\\n\\n function _protectedTokens() internal view override returns (address[] memory) {}\\n\\n // ============================== Setters ======================================\\n\\n /// @notice Sets collateral targets and value for collateral ratio\\n function setCollateralTargets(\\n uint256 _targetCollatRatio,\\n uint256 _maxCollatRatio,\\n uint256 _maxBorrowCollatRatio,\\n uint256 _daiBorrowCollatRatio\\n ) external onlyRole(GUARDIAN_ROLE) {\\n (uint256 ltv, uint256 liquidationThreshold) = _getProtocolCollatRatios(address(want));\\n (uint256 daiLtv, ) = _getProtocolCollatRatios(_dai);\\n require(\\n _targetCollatRatio < liquidationThreshold &&\\n _maxCollatRatio < liquidationThreshold &&\\n _targetCollatRatio < _maxCollatRatio &&\\n _maxBorrowCollatRatio < ltv &&\\n _daiBorrowCollatRatio < daiLtv,\\n \\\"8\\\"\\n );\\n\\n targetCollatRatio = _targetCollatRatio;\\n maxCollatRatio = _maxCollatRatio;\\n maxBorrowCollatRatio = _maxBorrowCollatRatio;\\n daiBorrowCollatRatio = _daiBorrowCollatRatio;\\n }\\n\\n /// @notice Sets `minWant`, `minRatio` and `maxItrations` values\\n function setMinsAndMaxs(\\n uint256 _minWant,\\n uint256 _minRatio,\\n uint8 _maxIterations\\n ) external onlyRole(GUARDIAN_ROLE) {\\n require(_minRatio < maxBorrowCollatRatio && _maxIterations > 0 && _maxIterations < 16, \\\"8\\\");\\n minWant = _minWant;\\n minRatio = _minRatio;\\n maxIterations = _maxIterations;\\n }\\n\\n /// @notice Sets all boolean parameters related to cooldown, withdraw check, flash loan and so on\\n function setBoolParams(BoolParams memory _boolParams) external onlyRole(GUARDIAN_ROLE) {\\n boolParams = _boolParams;\\n }\\n\\n /// @notice Sets the discount factor for the StkAAVE price\\n function setDiscountFactor(uint256 _discountFactor) external onlyRole(GUARDIAN_ROLE) {\\n require(_discountFactor < 10000, \\\"4\\\");\\n discountFactor = _discountFactor;\\n }\\n\\n /// @notice Retrieves lending pool variables for `want`. Those variables are mostly used in the function\\n /// to compute the optimal borrow amount\\n /// @dev No access control needed because they fetch the values from Aave directly.\\n /// If it changes there, it will need to be updated here too\\n /// @dev We expect the values concerned not to be often modified\\n function setAavePoolVariables() external {\\n _setAavePoolVariables();\\n }\\n\\n // ========================== External Actions =================================\\n\\n /// @notice Emergency function that we can use to deleverage manually if something is broken\\n /// @param amount Amount of `want` to withdraw/repay\\n function manualDeleverage(uint256 amount) external onlyRole(GUARDIAN_ROLE) {\\n _withdrawCollateral(amount);\\n _repayWant(amount);\\n }\\n\\n /// @notice Emergency function that we can use to deleverage manually if something is broken\\n /// @param amount Amount of `want` to withdraw\\n function manualReleaseWant(uint256 amount) external onlyRole(GUARDIAN_ROLE) {\\n _withdrawCollateral(amount);\\n }\\n\\n /// @notice Adds a new guardian address\\n /// @param _guardian New guardian address\\n function addGuardian(address _guardian) external override onlyRole(POOLMANAGER_ROLE) {\\n // Granting the new role\\n // Access control for this contract\\n _grantRole(GUARDIAN_ROLE, _guardian);\\n }\\n\\n /// @notice Revokes the guardian role\\n /// @param guardian Old guardian address to revoke\\n function revokeGuardian(address guardian) external override onlyRole(POOLMANAGER_ROLE) {\\n _revokeRole(GUARDIAN_ROLE, guardian);\\n }\\n\\n /// @notice Swap earned stkAave or Aave for `want` through 1Inch\\n /// @param minAmountOut Minimum amount of `want` to receive for the swap to happen\\n /// @param payload Bytes needed for 1Inch API. Tokens swapped should be: stkAave -> `want` or Aave -> `want`\\n function sellRewards(\\n uint256 minAmountOut,\\n bytes memory payload\\n ) external onlyRole(KEEPER_ROLE) {\\n //solhint-disable-next-line\\n (bool success, bytes memory result) = _oneInch.call(payload);\\n if (!success) _revertBytes(result);\\n\\n uint256 amountOut = abi.decode(result, (uint256));\\n require(amountOut >= minAmountOut, \\\"15\\\");\\n }\\n\\n /// @notice Flashload callback, as defined by EIP-3156\\n /// @notice We check that the call is coming from the DAI lender and then execute the load logic\\n /// @dev If everything went smoothly, will return `keccak256(\\\"ERC3156FlashBorrower.onFlashLoan\\\")`\\n function onFlashLoan(\\n address initiator,\\n address,\\n uint256 amount,\\n uint256,\\n bytes calldata data\\n ) external override returns (bytes32) {\\n require(msg.sender == FlashMintLib.LENDER && initiator == address(this), \\\"1\\\");\\n (bool deficit, uint256 amountWant) = abi.decode(data, (bool, uint256));\\n\\n return FlashMintLib.loanLogic(deficit, amountWant, amount, address(want));\\n }\\n\\n // ========================== Internal Actions =================================\\n\\n /// @notice Claim earned stkAAVE (only called at `harvest`)\\n /// @dev stkAAVE require a \\\"cooldown\\\" period of 10 days before being claimed\\n function _claimRewards() internal returns (uint256 stkAaveBalance) {\\n stkAaveBalance = _balanceOfStkAave();\\n uint256 cooldownStatus;\\n if (stkAaveBalance > 0) {\\n cooldownStatus = _checkCooldown(); // don't check status if we have no stkAave\\n }\\n\\n // If it's the claim period claim\\n if (stkAaveBalance > 0 && cooldownStatus == 1) {\\n // redeem AAVE from stkAave\\n _stkAave.claimRewards(address(this), type(uint256).max);\\n _stkAave.redeem(address(this), stkAaveBalance);\\n }\\n\\n // claim stkAave from lending and borrowing, this will reset the cooldown\\n _incentivesController.claimRewards(_getAaveAssets(), type(uint256).max, address(this));\\n\\n stkAaveBalance = _balanceOfStkAave();\\n\\n // request start of cooldown period, if there's no cooldown in progress\\n if (boolParams.cooldownStkAave && stkAaveBalance > 0 && cooldownStatus == 0) {\\n _stkAave.cooldown();\\n }\\n }\\n\\n function claimRewards() external onlyRole(KEEPER_ROLE) {\\n _claimRewards();\\n }\\n\\n /// @notice Reduce exposure by withdrawing funds and repaying debt\\n /// @param amountToFree Amount of `want` to withdraw/repay\\n /// @return balance Current balance of `want`\\n /// @dev `deposits` and `borrows` are always computed prior to the call\\n function _freeFunds(\\n uint256 amountToFree,\\n uint256 deposits,\\n uint256 borrows\\n ) internal returns (uint256) {\\n if (amountToFree == 0) return 0;\\n\\n uint256 realAssets = deposits - borrows;\\n uint256 newBorrow = _getBorrowFromSupply(realAssets - Math.min(amountToFree, realAssets), targetCollatRatio);\\n\\n // repay required amount\\n _leverDownTo(newBorrow, deposits, borrows);\\n\\n return _balanceOfWant();\\n }\\n\\n /// @notice Get exposure up to `targetCollatRatio`\\n function _leverMax(uint256 deposits, uint256 borrows) internal {\\n uint256 totalAmountToBorrow = _getBorrowFromSupply(deposits - borrows, targetCollatRatio) - borrows;\\n\\n if (boolParams.isFlashMintActive) {\\n // The best approach is to lever up using regular method, then finish with flash loan\\n totalAmountToBorrow = totalAmountToBorrow - _leverUpStep(totalAmountToBorrow, deposits, borrows);\\n\\n if (totalAmountToBorrow > minWant) {\\n totalAmountToBorrow = totalAmountToBorrow - _leverUpFlashLoan(totalAmountToBorrow);\\n }\\n } else {\\n for (uint8 i = 0; i < maxIterations && totalAmountToBorrow > minWant; i++) {\\n totalAmountToBorrow = totalAmountToBorrow - _leverUpStep(totalAmountToBorrow, deposits, borrows);\\n deposits = 0;\\n borrows = 0;\\n }\\n }\\n }\\n\\n /// @notice Use a flashloan to increase our exposure in `want` on Aave\\n /// @param amount Amount we will deposit and borrow on Aave\\n /// @return amount Actual amount deposited/borrowed\\n /// @dev Amount returned should equal `amount` but can be lower if we try to flashloan more than `maxFlashLoan` authorized\\n function _leverUpFlashLoan(uint256 amount) internal returns (uint256) {\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n uint256 depositsToMeetLtv = _getDepositFromBorrow(borrows, maxBorrowCollatRatio, deposits);\\n uint256 depositsDeficitToMeetLtv = 0;\\n if (depositsToMeetLtv > deposits) {\\n depositsDeficitToMeetLtv = depositsToMeetLtv - deposits;\\n }\\n return FlashMintLib.doFlashMint(false, amount, address(want), daiBorrowCollatRatio, depositsDeficitToMeetLtv);\\n }\\n\\n /// @notice Increase exposure in `want`\\n /// @param amount Amount of `want` to borrow\\n /// @return amount Amount of `want` that was borrowed\\n function _leverUpStep(\\n uint256 amount,\\n uint256 deposits,\\n uint256 borrows\\n ) internal returns (uint256) {\\n if (deposits == 0 && borrows == 0) (deposits, borrows) = getCurrentPosition();\\n\\n uint256 wantBalance = _balanceOfWant();\\n\\n uint256 canBorrow = _getBorrowFromDeposit(deposits + wantBalance, maxBorrowCollatRatio);\\n\\n if (canBorrow <= borrows) {\\n return 0;\\n }\\n canBorrow = canBorrow - borrows;\\n\\n if (canBorrow < amount) {\\n amount = canBorrow;\\n }\\n\\n _depositCollateral(wantBalance);\\n _borrowWant(amount);\\n _depositCollateral(amount);\\n\\n return amount;\\n }\\n\\n /// @notice Reduce our exposure to `want` on Aave\\n /// @param newAmountBorrowed Total amount we want to be borrowing\\n /// @param deposits Amount currently lent\\n /// @param currentBorrowed Amount currently borrowed\\n function _leverDownTo(\\n uint256 newAmountBorrowed,\\n uint256 deposits,\\n uint256 currentBorrowed\\n ) internal {\\n if (currentBorrowed > newAmountBorrowed) {\\n uint256 totalRepayAmount = currentBorrowed - newAmountBorrowed;\\n\\n if (boolParams.isFlashMintActive) {\\n totalRepayAmount = totalRepayAmount - _leverDownFlashLoan(totalRepayAmount, currentBorrowed);\\n }\\n\\n uint256 _maxCollatRatio = maxCollatRatio;\\n\\n // in case the flashloan didn't repay the entire amount we have to repay it \\\"manually\\\"\\n // by withdrawing a bit of collateral and then repaying the debt with it\\n for (uint8 i = 0; i < maxIterations && totalRepayAmount > minWant; i++) {\\n _withdrawExcessCollateral(_maxCollatRatio, 0, 0);\\n uint256 toRepay = totalRepayAmount;\\n uint256 wantBalance = _balanceOfWant();\\n if (toRepay > wantBalance) {\\n toRepay = wantBalance;\\n }\\n uint256 repaid = _repayWant(toRepay);\\n totalRepayAmount = totalRepayAmount - repaid;\\n }\\n (deposits, currentBorrowed) = getCurrentPosition();\\n }\\n\\n // Deposit back to get `targetCollatRatio` (we always need to leave this in this ratio)\\n uint256 _targetCollatRatio = targetCollatRatio;\\n uint256 targetDeposit = _getDepositFromBorrow(currentBorrowed, _targetCollatRatio, deposits);\\n if (targetDeposit > deposits) {\\n uint256 toDeposit = targetDeposit - deposits;\\n if (toDeposit > minWant) {\\n _depositCollateral(Math.min(toDeposit, _balanceOfWant()));\\n }\\n } else {\\n if (deposits - targetDeposit > minWant) {\\n _withdrawExcessCollateral(_targetCollatRatio, deposits, currentBorrowed);\\n }\\n }\\n }\\n\\n /// @notice Use a flashloan to reduce our exposure in `want` on Aave\\n /// @param amount Amount we will need to withdraw and repay to Aave\\n /// @return amount Actual amount repaid\\n /// @dev Amount returned should equal `amount` but can be lower if we try to flashloan more than `maxFlashLoan` authorized\\n /// @dev `amount` will be withdrawn from deposits and then used to repay borrows\\n function _leverDownFlashLoan(uint256 amount, uint256 borrows) internal returns (uint256) {\\n if (amount <= minWant) return 0;\\n if (amount > borrows) {\\n amount = borrows;\\n }\\n return FlashMintLib.doFlashMint(true, amount, address(want), daiBorrowCollatRatio, 0);\\n }\\n\\n /// @notice Adjusts the deposits based on the wanted collateral ratio (does not touch the borrow)\\n /// @param collatRatio Collateral ratio to target\\n function _withdrawExcessCollateral(\\n uint256 collatRatio,\\n uint256 deposits,\\n uint256 borrows\\n ) internal returns (uint256 amount) {\\n if (deposits == 0 && borrows == 0) (deposits, borrows) = getCurrentPosition();\\n uint256 theoDeposits = _getDepositFromBorrow(borrows, collatRatio, deposits);\\n if (deposits > theoDeposits) {\\n uint256 toWithdraw = deposits - theoDeposits;\\n return _withdrawCollateral(toWithdraw);\\n }\\n }\\n\\n /// @notice Deposit `want` tokens in Aave and start earning interests\\n /// @param amount Amount to be deposited\\n /// @return amount The amount deposited\\n function _depositCollateral(uint256 amount) internal returns (uint256) {\\n if (amount == 0) return 0;\\n _lendingPool.deposit(address(want), amount, address(this), _referral);\\n return amount;\\n }\\n\\n /// @notice Withdraw `want` tokens from Aave\\n /// @param amount Amount to be withdrawn\\n /// @return amount The amount withdrawn\\n function _withdrawCollateral(uint256 amount) internal returns (uint256) {\\n if (amount == 0) return 0;\\n _lendingPool.withdraw(address(want), amount, address(this));\\n return amount;\\n }\\n\\n /// @notice Repay what we borrowed of `want` from Aave\\n /// @param amount Amount to repay\\n /// @return amount The amount repaid\\n /// @dev `interestRateMode` is set to variable rate (2)\\n function _repayWant(uint256 amount) internal returns (uint256) {\\n if (amount == 0) return 0;\\n return _lendingPool.repay(address(want), amount, 2, address(this));\\n }\\n\\n /// @notice Borrow `want` from Aave\\n /// @param amount Amount of `want` we are borrowing\\n /// @return amount The amount borrowed\\n /// @dev The third variable is the `interestRateMode`\\n /// @dev set at 2 which means we will get a variable interest rate on our borrowed tokens\\n function _borrowWant(uint256 amount) internal returns (uint256) {\\n _lendingPool.borrow(address(want), amount, 2, _referral, address(this));\\n return amount;\\n }\\n\\n /// @notice Computes the optimal collateral ratio based on current interests and incentives on Aave\\n /// @notice It modifies the state by updating the `targetCollatRatio`\\n function _computeOptimalCollatRatio(\\n uint256 balanceExcludingRewards,\\n uint256 deposits,\\n uint256 currentBorrowed,\\n uint256 guessedBorrow\\n ) internal returns (uint256) {\\n uint256 borrow = _computeMostProfitableBorrow(\\n balanceExcludingRewards,\\n deposits,\\n currentBorrowed,\\n guessedBorrow\\n );\\n uint256 _collatRatio = _getCollatRatio(balanceExcludingRewards + borrow, borrow);\\n uint256 _maxCollatRatio = maxCollatRatio;\\n if (_collatRatio > _maxCollatRatio) {\\n _collatRatio = _maxCollatRatio;\\n }\\n targetCollatRatio = _collatRatio;\\n return _collatRatio;\\n }\\n\\n /// @notice Approve `spender` maxuint of `token`\\n /// @param token Address of token to approve\\n /// @param spender Address of spender to approve\\n function _approveMaxSpend(address token, address spender) internal {\\n IERC20(token).safeApprove(spender, type(uint256).max);\\n }\\n\\n /// @notice Internal version of the `_setAavePoolVariables`\\n function _setAavePoolVariables() internal {\\n (, , , , uint256 reserveFactor_, , , , , ) = _protocolDataProvider.getReserveConfigurationData(address(want));\\n cooldownSeconds = IStakedAave(_stkAave).COOLDOWN_SECONDS();\\n unstakeWindow = IStakedAave(_stkAave).UNSTAKE_WINDOW();\\n reserveFactor = int256(reserveFactor_ * 10**23);\\n slope1 = int256(_interestRateStrategyAddress.variableRateSlope1());\\n slope2 = int256(_interestRateStrategyAddress.variableRateSlope2());\\n r0 = int256(_interestRateStrategyAddress.baseVariableBorrowRate());\\n uOptimal = int256(_interestRateStrategyAddress.OPTIMAL_UTILIZATION_RATE());\\n }\\n\\n // ========================= Internal View Functions ===========================\\n\\n /// @notice Computes the optimal amounts to borrow based on current interest rates and incentives\\n /// @dev Returns optimal `borrow` amount in base of `want`\\n function _computeMostProfitableBorrow(\\n uint256 balanceExcludingRewards,\\n uint256 deposits,\\n uint256 currentBorrow,\\n uint256 guessedBorrow\\n ) internal view returns (uint256 borrow) {\\n // This works if `wantBase < 10**27` which we should expect to be very the case for the strategies we are\\n // launching at the moment\\n uint256 normalizationFactor = 10**27 / wantBase;\\n\\n ComputeProfitability.SCalculateBorrow memory parameters;\\n\\n {\\n (\\n uint256 availableLiquidity,\\n uint256 totalStableDebt,\\n uint256 totalVariableDebt,\\n ,\\n ,\\n ,\\n uint256 averageStableBorrowRate,\\n ,\\n ,\\n\\n ) = _protocolDataProvider.getReserveData(address(want));\\n\\n parameters = ComputeProfitability.SCalculateBorrow({\\n reserveFactor: reserveFactor,\\n totalStableDebt: int256(totalStableDebt * normalizationFactor),\\n totalVariableDebt: int256((totalVariableDebt - currentBorrow) * normalizationFactor),\\n totalDeposits: int256(\\n (availableLiquidity +\\n totalStableDebt +\\n totalVariableDebt +\\n // to adapt to our future balance\\n // add the wantBalance and remove the currentBorrowed from the optimisation\\n balanceExcludingRewards -\\n deposits) * normalizationFactor\\n ),\\n stableBorrowRate: int256(averageStableBorrowRate),\\n rewardDeposit: 0,\\n rewardBorrow: 0,\\n strategyAssets: int256(balanceExcludingRewards * normalizationFactor),\\n guessedBorrowAssets: int256(guessedBorrow * normalizationFactor),\\n slope1: slope1,\\n slope2: slope2,\\n r0: r0,\\n uOptimal: uOptimal\\n });\\n }\\n\\n {\\n uint256 stkAavePriceInWant = _estimatedStkAaveToWant(1 ether);\\n\\n (uint256 emissionPerSecondAToken, , ) = _incentivesController.assets(address(_aToken));\\n (uint256 emissionPerSecondDebtToken, , ) = _incentivesController.assets(address(_debtToken));\\n\\n parameters.rewardDeposit = int256(\\n (emissionPerSecondAToken * 86400 * 365 * stkAavePriceInWant * 10**9) / wantBase\\n );\\n parameters.rewardBorrow = int256(\\n (emissionPerSecondDebtToken * 86400 * 365 * stkAavePriceInWant * 10**9) / wantBase\\n );\\n }\\n\\n borrow = uint256(ComputeProfitability.computeProfitability(parameters)) / normalizationFactor;\\n }\\n\\n function estimatedAPR() public view returns (uint256) {\\n (\\n ,\\n ,\\n uint256 totalVariableDebt,\\n uint256 liquidityRate,\\n uint256 variableBorrowRate,\\n ,\\n ,\\n ,\\n ,\\n\\n ) = _protocolDataProvider.getReserveData(address(want));\\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\\n uint256 yearlyRewardsATokenInUSDC;\\n uint256 yearlyRewardsDebtTokenInUSDC;\\n {\\n uint256 stkAavePriceInWant = _estimatedStkAaveToWant(1 ether);\\n (uint256 emissionPerSecondAToken, , ) = (_aToken.getIncentivesController()).assets(address(_aToken));\\n (uint256 emissionPerSecondDebtToken, , ) = (_debtToken.getIncentivesController()).assets(\\n address(_debtToken)\\n );\\n\\n uint256 yearlyEmissionsAToken = emissionPerSecondAToken * 60 * 60 * 24 * 365; // BASE: 18\\n uint256 yearlyEmissionsDebtToken = emissionPerSecondDebtToken * 60 * 60 * 24 * 365; // BASE: 18\\n yearlyRewardsATokenInUSDC = ((deposits * yearlyEmissionsAToken * stkAavePriceInWant * 10**9) /\\n _aToken.totalSupply()); // BASE 27 + want\\n yearlyRewardsDebtTokenInUSDC = ((borrows * yearlyEmissionsDebtToken * stkAavePriceInWant * 10**9) /\\n totalVariableDebt); // BASE 27 + want\\n }\\n\\n uint256 _totalAssets = _balanceOfWant() + _balanceOfAToken() - _balanceOfDebtToken();\\n return\\n (liquidityRate *\\n deposits +\\n yearlyRewardsATokenInUSDC +\\n yearlyRewardsDebtTokenInUSDC -\\n variableBorrowRate *\\n borrows) /\\n _totalAssets /\\n 10**18; // BASE 9\\n }\\n\\n /// @notice Returns the `want` balance\\n function _balanceOfWant() internal view returns (uint256) {\\n return want.balanceOf(address(this));\\n }\\n\\n /// @notice Returns the `aToken` balance\\n function _balanceOfAToken() internal view returns (uint256) {\\n return _aToken.balanceOf(address(this));\\n }\\n\\n /// @notice Returns the `debtToken` balance\\n function _balanceOfDebtToken() internal view returns (uint256) {\\n return _debtToken.balanceOf(address(this));\\n }\\n\\n /// @notice Returns the `AAVE` balance\\n function _balanceOfAave() internal view returns (uint256) {\\n return IERC20(_aave).balanceOf(address(this));\\n }\\n\\n /// @notice Returns the `StkAAVE` balance\\n function _balanceOfStkAave() internal view returns (uint256) {\\n return IERC20(address(_stkAave)).balanceOf(address(this));\\n }\\n\\n /// @notice Estimate the amount of `want` we will get out by swapping it for AAVE\\n /// @param amount Amount of AAVE we want to exchange (in base 18)\\n /// @return amount Amount of `want` we are getting. We include a discount to account for slippage equal to 9000\\n /// @dev Uses Chainlink spot price. Return value will be in base of `want` (6 for USDC)\\n function _estimatedStkAaveToWant(uint256 amount) internal view returns (uint256) {\\n (, int256 aavePriceUSD, , , ) = _chainlinkOracle.latestRoundData(); // stkAavePriceUSD is in base 8\\n // `aavePriceUSD` is in base 8, and the discount factor is in base 4, so ultimately we need to divide\\n // by `1e(18+8+4)\\n return (uint256(aavePriceUSD) * amount * wantBase * discountFactor) / 1e30;\\n }\\n\\n /// @notice Verifies the cooldown status for earned stkAAVE\\n /// @return cooldownStatus Status of the coolDown: if it is 0 then there is no cooldown Status, if it is 1 then\\n /// the strategy should claim\\n function _checkCooldown() internal view returns (uint256 cooldownStatus) {\\n uint256 cooldownStartTimestamp = IStakedAave(_stkAave).stakersCooldowns(address(this));\\n uint256 nextClaimStartTimestamp = cooldownStartTimestamp + cooldownSeconds;\\n if (cooldownStartTimestamp == 0) {\\n return 0;\\n }\\n if (block.timestamp > nextClaimStartTimestamp && block.timestamp <= nextClaimStartTimestamp + unstakeWindow) {\\n return 1;\\n }\\n if (block.timestamp < nextClaimStartTimestamp) {\\n return 2;\\n }\\n }\\n\\n /// @notice Get the deposit and debt token for our `want` token\\n function _getAaveAssets() internal view returns (address[] memory assets) {\\n assets = new address[](2);\\n assets[0] = address(_aToken);\\n assets[1] = address(_debtToken);\\n }\\n\\n /// @notice Get Aave ratios for a token in order to compute later our collateral ratio\\n /// @param token Address of the token for which to check the ratios (usually `want` token)\\n /// @dev `getReserveConfigurationData` returns values in base 4. So here `ltv` and `liquidationThreshold` are returned in base 18\\n function _getProtocolCollatRatios(address token) internal view returns (uint256 ltv, uint256 liquidationThreshold) {\\n (, ltv, liquidationThreshold, , , , , , , ) = _protocolDataProvider.getReserveConfigurationData(token);\\n // convert bps to wad\\n ltv = ltv * _BPS_WAD_RATIO;\\n liquidationThreshold = liquidationThreshold * _BPS_WAD_RATIO;\\n }\\n\\n // ========================= Internal Pure Functions ===========================\\n\\n /// @notice Get target borrow amount based on deposit and collateral ratio\\n /// @param deposit Current total deposited on Aave\\n /// @param collatRatio Collateral ratio to target\\n function _getBorrowFromDeposit(uint256 deposit, uint256 collatRatio) internal pure returns (uint256) {\\n return (deposit * collatRatio) / _COLLATERAL_RATIO_PRECISION;\\n }\\n\\n /// @notice Get target deposit amount based on borrow and collateral ratio\\n /// @param borrow Current total borrowed on Aave\\n /// @param collatRatio Collateral ratio to target\\n /// @param deposits Current deposit amount: this is what the function should return if the `collatRatio` is null\\n function _getDepositFromBorrow(\\n uint256 borrow,\\n uint256 collatRatio,\\n uint256 deposits\\n ) internal pure returns (uint256) {\\n if (collatRatio > 0) return (borrow * _COLLATERAL_RATIO_PRECISION) / collatRatio;\\n else return deposits;\\n }\\n\\n /// @notice Get target borrow amount based on supply (deposits - borrow) and collateral ratio\\n /// @param supply = deposits - borrows. The supply is what is \\\"actually\\\" deposited in Aave\\n /// @param collatRatio Collateral ratio to target\\n function _getBorrowFromSupply(uint256 supply, uint256 collatRatio) internal pure returns (uint256) {\\n return (supply * collatRatio) / (_COLLATERAL_RATIO_PRECISION - collatRatio);\\n }\\n\\n /// @notice Computes the position collateral ratio from deposits and borrows\\n function _getCollatRatio(uint256 deposits, uint256 borrows) internal pure returns (uint256 currentCollatRatio) {\\n if (deposits > 0) {\\n currentCollatRatio = (borrows * _COLLATERAL_RATIO_PRECISION) / deposits;\\n }\\n }\\n\\n /// @notice Processes 1Inch revert messages\\n function _revertBytes(bytes memory errMsg) internal pure {\\n if (errMsg.length > 0) {\\n //solhint-disable-next-line\\n assembly {\\n revert(add(32, errMsg), mload(errMsg))\\n }\\n }\\n revert(\\\"117\\\");\\n }\\n}\\n\",\"keccak256\":\"0x8f4f5f537087aacd26ed75b7f2b885426d492d8c54b91b8fefd8f767e7d9a993\",\"license\":\"GPL-3.0\"},\"contracts/strategies/AaveFlashloanStrategy/AaveInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.7;\\n\\nimport { DataTypes } from \\\"./AaveLibraries.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IAaveIncentivesController {\\n /**\\n * @dev Returns the total of rewards of an user, already accrued + not yet accrued\\n * @param user The address of the user\\n * @return The rewards\\n **/\\n function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256);\\n\\n /**\\n * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards\\n * @param amount Amount of rewards to claim\\n * @param to Address that will be receiving the rewards\\n * @return Rewards claimed\\n **/\\n function claimRewards(\\n address[] calldata assets,\\n uint256 amount,\\n address to\\n ) external returns (uint256);\\n\\n /**\\n * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must\\n * be whitelisted via \\\"allowClaimOnBehalf\\\" function by the RewardsAdmin role manager\\n * @param amount Amount of rewards to claim\\n * @param user Address to check and claim rewards\\n * @param to Address that will be receiving the rewards\\n * @return Rewards claimed\\n **/\\n function claimRewardsOnBehalf(\\n address[] calldata assets,\\n uint256 amount,\\n address user,\\n address to\\n ) external returns (uint256);\\n\\n /**\\n * @dev returns the unclaimed rewards of the user\\n * @param user the address of the user\\n * @return the unclaimed user rewards\\n */\\n function getUserUnclaimedRewards(address user) external view returns (uint256);\\n\\n /**\\n * @dev for backward compatibility with previous implementation of the Incentives controller\\n */\\n function REWARD_TOKEN() external view returns (address);\\n\\n function getDistributionEnd() external view returns (uint256);\\n\\n function getAssetData(address asset)\\n external\\n view\\n returns (\\n uint256,\\n uint256,\\n uint256\\n );\\n\\n function assets(address asset)\\n external\\n view\\n returns (\\n uint256 emissionPerSecond,\\n uint256 index,\\n uint256 lastUpdateTimestamp\\n );\\n\\n function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) external;\\n}\\n\\ninterface ILendingPool {\\n /**\\n * @dev Emitted on deposit()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The address initiating the deposit\\n * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens\\n * @param amount The amount deposited\\n * @param referral The referral code used\\n **/\\n event Deposit(\\n address indexed reserve,\\n address user,\\n address indexed onBehalfOf,\\n uint256 amount,\\n uint16 indexed referral\\n );\\n\\n /**\\n * @dev Emitted on withdraw()\\n * @param reserve The address of the underlyng asset being withdrawn\\n * @param user The address initiating the withdrawal, owner of aTokens\\n * @param to Address that will receive the underlying\\n * @param amount The amount to be withdrawn\\n **/\\n event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);\\n\\n /**\\n * @dev Emitted on borrow() and flashLoan() when debt needs to be opened\\n * @param reserve The address of the underlying asset being borrowed\\n * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just\\n * initiator of the transaction on flashLoan()\\n * @param onBehalfOf The address that will be getting the debt\\n * @param amount The amount borrowed out\\n * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable\\n * @param borrowRate The numeric rate at which the user has borrowed\\n * @param referral The referral code used\\n **/\\n event Borrow(\\n address indexed reserve,\\n address user,\\n address indexed onBehalfOf,\\n uint256 amount,\\n uint256 borrowRateMode,\\n uint256 borrowRate,\\n uint16 indexed referral\\n );\\n\\n /**\\n * @dev Emitted on repay()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The beneficiary of the repayment, getting his debt reduced\\n * @param repayer The address of the user initiating the repay(), providing the funds\\n * @param amount The amount repaid\\n **/\\n event Repay(address indexed reserve, address indexed user, address indexed repayer, uint256 amount);\\n\\n /**\\n * @dev Emitted on swapBorrowRateMode()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The address of the user swapping his rate mode\\n * @param rateMode The rate mode that the user wants to swap to\\n **/\\n event Swap(address indexed reserve, address indexed user, uint256 rateMode);\\n\\n /**\\n * @dev Emitted on setUserUseReserveAsCollateral()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The address of the user enabling the usage as collateral\\n **/\\n event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);\\n\\n /**\\n * @dev Emitted on setUserUseReserveAsCollateral()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The address of the user enabling the usage as collateral\\n **/\\n event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);\\n\\n /**\\n * @dev Emitted on rebalanceStableBorrowRate()\\n * @param reserve The address of the underlying asset of the reserve\\n * @param user The address of the user for which the rebalance has been executed\\n **/\\n event RebalanceStableBorrowRate(address indexed reserve, address indexed user);\\n\\n /**\\n * @dev Emitted on flashLoan()\\n * @param target The address of the flash loan receiver contract\\n * @param initiator The address initiating the flash loan\\n * @param asset The address of the asset being flash borrowed\\n * @param amount The amount flash borrowed\\n * @param premium The fee flash borrowed\\n * @param referralCode The referral code used\\n **/\\n event FlashLoan(\\n address indexed target,\\n address indexed initiator,\\n address indexed asset,\\n uint256 amount,\\n uint256 premium,\\n uint16 referralCode\\n );\\n\\n /**\\n * @dev Emitted when the pause is triggered.\\n */\\n event Paused();\\n\\n /**\\n * @dev Emitted when the pause is lifted.\\n */\\n event Unpaused();\\n\\n /**\\n * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via\\n * LendingPoolCollateral manager using a DELEGATECALL\\n * This allows to have the events in the generated ABI for LendingPool.\\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\\n * @param user The address of the borrower getting liquidated\\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\\n * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator\\n * @param liquidator The address of the liquidator\\n * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\\n * to receive the underlying collateral asset directly\\n **/\\n event LiquidationCall(\\n address indexed collateralAsset,\\n address indexed debtAsset,\\n address indexed user,\\n uint256 debtToCover,\\n uint256 liquidatedCollateralAmount,\\n address liquidator,\\n bool receiveAToken\\n );\\n\\n /**\\n * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared\\n * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,\\n * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it\\n * gets added to the LendingPool ABI\\n * @param reserve The address of the underlying asset of the reserve\\n * @param liquidityRate The new liquidity rate\\n * @param stableBorrowRate The new stable borrow rate\\n * @param variableBorrowRate The new variable borrow rate\\n * @param liquidityIndex The new liquidity index\\n * @param variableBorrowIndex The new variable borrow index\\n **/\\n event ReserveDataUpdated(\\n address indexed reserve,\\n uint256 liquidityRate,\\n uint256 stableBorrowRate,\\n uint256 variableBorrowRate,\\n uint256 liquidityIndex,\\n uint256 variableBorrowIndex\\n );\\n\\n /**\\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\\n * @param asset The address of the underlying asset to deposit\\n * @param amount The amount to be deposited\\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\\n * is a different wallet\\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n * 0 if the action is executed directly by the user, without any middle-man\\n **/\\n function deposit(\\n address asset,\\n uint256 amount,\\n address onBehalfOf,\\n uint16 referralCode\\n ) external;\\n\\n /**\\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\\n * @param asset The address of the underlying asset to withdraw\\n * @param amount The underlying amount to be withdrawn\\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\\n * @param to Address that will receive the underlying, same as msg.sender if the user\\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\\n * different wallet\\n * @return The final amount withdrawn\\n **/\\n function withdraw(\\n address asset,\\n uint256 amount,\\n address to\\n ) external returns (uint256);\\n\\n /**\\n * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower\\n * already deposited enough collateral, or he was given enough allowance by a credit delegator on the\\n * corresponding debt token (StableDebtToken or VariableDebtToken)\\n * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet\\n * and 100 stable/variable debt tokens, depending on the `interestRateMode`\\n * @param asset The address of the underlying asset to borrow\\n * @param amount The amount to be borrowed\\n * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable\\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n * 0 if the action is executed directly by the user, without any middle-man\\n * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself\\n * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator\\n * if he has been given credit delegation allowance\\n **/\\n function borrow(\\n address asset,\\n uint256 amount,\\n uint256 interestRateMode,\\n uint16 referralCode,\\n address onBehalfOf\\n ) external;\\n\\n /**\\n * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned\\n * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address\\n * @param asset The address of the borrowed underlying asset previously borrowed\\n * @param amount The amount to repay\\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\\n * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\\n * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the\\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\\n * other borrower whose debt should be removed\\n * @return The final amount repaid\\n **/\\n function repay(\\n address asset,\\n uint256 amount,\\n uint256 rateMode,\\n address onBehalfOf\\n ) external returns (uint256);\\n\\n /**\\n * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa\\n * @param asset The address of the underlying asset borrowed\\n * @param rateMode The rate mode that the user wants to swap to\\n **/\\n function swapBorrowRateMode(address asset, uint256 rateMode) external;\\n\\n /**\\n * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.\\n * - Users can be rebalanced if the following conditions are satisfied:\\n * 1. Usage ratio is above 95%\\n * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been\\n * borrowed at a stable rate and depositors are not earning enough\\n * @param asset The address of the underlying asset borrowed\\n * @param user The address of the user to be rebalanced\\n **/\\n function rebalanceStableBorrowRate(address asset, address user) external;\\n\\n /**\\n * @dev Allows depositors to enable/disable a specific deposited asset as collateral\\n * @param asset The address of the underlying asset deposited\\n * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise\\n **/\\n function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;\\n\\n /**\\n * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1\\n * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives\\n * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk\\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\\n * @param user The address of the borrower getting liquidated\\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\\n * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\\n * to receive the underlying collateral asset directly\\n **/\\n function liquidationCall(\\n address collateralAsset,\\n address debtAsset,\\n address user,\\n uint256 debtToCover,\\n bool receiveAToken\\n ) external;\\n\\n /**\\n * @dev Allows smartcontracts to access the liquidity of the pool within one transaction,\\n * as long as the amount taken plus a fee is returned.\\n * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.\\n * For further details please visit https://developers.aave.com\\n * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface\\n * @param assets The addresses of the assets being flash-borrowed\\n * @param amounts The amounts amounts being flash-borrowed\\n * @param modes Types of the debt to open if the flash loan is not returned:\\n * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver\\n * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\\n * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\\n * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2\\n * @param params Variadic packed params to pass to the receiver as extra information\\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\\n * 0 if the action is executed directly by the user, without any middle-man\\n **/\\n function flashLoan(\\n address receiverAddress,\\n address[] calldata assets,\\n uint256[] calldata amounts,\\n uint256[] calldata modes,\\n address onBehalfOf,\\n bytes calldata params,\\n uint16 referralCode\\n ) external;\\n\\n /**\\n * @dev Returns the user account data across all the reserves\\n * @param user The address of the user\\n * @return totalCollateralETH the total collateral in ETH of the user\\n * @return totalDebtETH the total debt in ETH of the user\\n * @return availableBorrowsETH the borrowing power left of the user\\n * @return currentLiquidationThreshold the liquidation threshold of the user\\n * @return ltv the loan to value of the user\\n * @return healthFactor the current health factor of the user\\n **/\\n function getUserAccountData(address user)\\n external\\n view\\n returns (\\n uint256 totalCollateralETH,\\n uint256 totalDebtETH,\\n uint256 availableBorrowsETH,\\n uint256 currentLiquidationThreshold,\\n uint256 ltv,\\n uint256 healthFactor\\n );\\n\\n function initReserve(\\n address reserve,\\n address aTokenAddress,\\n address stableDebtAddress,\\n address variableDebtAddress,\\n address interestRateStrategyAddress\\n ) external;\\n\\n function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external;\\n\\n function setConfiguration(address reserve, uint256 configuration) external;\\n\\n /**\\n * @dev Returns the configuration of the reserve\\n * @param asset The address of the underlying asset of the reserve\\n * @return The configuration of the reserve\\n **/\\n function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);\\n\\n /**\\n * @dev Returns the configuration of the user across all the reserves\\n * @param user The user address\\n * @return The configuration of the user\\n **/\\n function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);\\n\\n /**\\n * @dev Returns the normalized income normalized income of the reserve\\n * @param asset The address of the underlying asset of the reserve\\n * @return The reserve's normalized income\\n */\\n function getReserveNormalizedIncome(address asset) external view returns (uint256);\\n\\n /**\\n * @dev Returns the normalized variable debt per unit of asset\\n * @param asset The address of the underlying asset of the reserve\\n * @return The reserve normalized variable debt\\n */\\n function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);\\n\\n /**\\n * @dev Returns the state and configuration of the reserve\\n * @param asset The address of the underlying asset of the reserve\\n * @return The state of the reserve\\n **/\\n function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);\\n\\n function finalizeTransfer(\\n address asset,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 balanceFromAfter,\\n uint256 balanceToBefore\\n ) external;\\n\\n function getReservesList() external view returns (address[] memory);\\n\\n function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);\\n\\n function setPause(bool val) external;\\n\\n function paused() external view returns (bool);\\n}\\n\\ninterface IProtocolDataProvider {\\n struct TokenData {\\n string symbol;\\n address tokenAddress;\\n }\\n\\n function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);\\n\\n function getAllReservesTokens() external view returns (TokenData[] memory);\\n\\n function getAllATokens() external view returns (TokenData[] memory);\\n\\n function getReserveConfigurationData(address asset)\\n external\\n view\\n returns (\\n uint256 decimals,\\n uint256 ltv,\\n uint256 liquidationThreshold,\\n uint256 liquidationBonus,\\n uint256 reserveFactor,\\n bool usageAsCollateralEnabled,\\n bool borrowingEnabled,\\n bool stableBorrowRateEnabled,\\n bool isActive,\\n bool isFrozen\\n );\\n\\n function getReserveData(address asset)\\n external\\n view\\n returns (\\n uint256 availableLiquidity,\\n uint256 totalStableDebt,\\n uint256 totalVariableDebt,\\n uint256 liquidityRate,\\n uint256 variableBorrowRate,\\n uint256 stableBorrowRate,\\n uint256 averageStableBorrowRate,\\n uint256 liquidityIndex,\\n uint256 variableBorrowIndex,\\n uint40 lastUpdateTimestamp\\n );\\n\\n function getUserReserveData(address asset, address user)\\n external\\n view\\n returns (\\n uint256 currentATokenBalance,\\n uint256 currentStableDebt,\\n uint256 currentVariableDebt,\\n uint256 principalStableDebt,\\n uint256 scaledVariableDebt,\\n uint256 stableBorrowRate,\\n uint256 liquidityRate,\\n uint40 stableRateLastUpdated,\\n bool usageAsCollateralEnabled\\n );\\n\\n function getReserveTokensAddresses(address asset)\\n external\\n view\\n returns (\\n address aTokenAddress,\\n address stableDebtTokenAddress,\\n address variableDebtTokenAddress\\n );\\n}\\n\\ninterface IScaledBalanceToken {\\n /**\\n * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the\\n * updated stored balance divided by the reserve's liquidity index at the moment of the update\\n * @param user The user whose balance is calculated\\n * @return The scaled balance of the user\\n **/\\n function scaledBalanceOf(address user) external view returns (uint256);\\n\\n /**\\n * @dev Returns the scaled balance of the user and the scaled total supply.\\n * @param user The address of the user\\n * @return The scaled balance of the user\\n * @return The scaled balance and the scaled total supply\\n **/\\n function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);\\n\\n /**\\n * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)\\n * @return The scaled total supply\\n **/\\n function scaledTotalSupply() external view returns (uint256);\\n}\\n\\n/**\\n * @title IVariableDebtToken\\n * @author Aave\\n * @notice Defines the basic interface for a variable debt token.\\n **/\\ninterface IVariableDebtToken is IERC20, IScaledBalanceToken {\\n /**\\n * @dev Emitted after the mint action\\n * @param from The address performing the mint\\n * @param onBehalfOf The address of the user on which behalf minting has been performed\\n * @param value The amount to be minted\\n * @param index The last index of the reserve\\n **/\\n event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index);\\n\\n /**\\n * @dev Mints debt token to the `onBehalfOf` address\\n * @param user The address receiving the borrowed underlying, being the delegatee in case\\n * of credit delegate, or same as `onBehalfOf` otherwise\\n * @param onBehalfOf The address receiving the debt tokens\\n * @param amount The amount of debt being minted\\n * @param index The variable debt index of the reserve\\n * @return `true` if the the previous balance of the user is 0\\n **/\\n function mint(\\n address user,\\n address onBehalfOf,\\n uint256 amount,\\n uint256 index\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when variable debt is burnt\\n * @param user The user which debt has been burned\\n * @param amount The amount of debt being burned\\n * @param index The index of the user\\n **/\\n event Burn(address indexed user, uint256 amount, uint256 index);\\n\\n /**\\n * @dev Burns user variable debt\\n * @param user The user which debt is burnt\\n * @param index The variable debt index of the reserve\\n **/\\n function burn(\\n address user,\\n uint256 amount,\\n uint256 index\\n ) external;\\n\\n /**\\n * @dev Returns the address of the incentives controller contract\\n **/\\n function getIncentivesController() external view returns (IAaveIncentivesController);\\n}\\n\\n/**\\n * @title LendingPoolAddressesProvider contract\\n * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles\\n * - Acting also as factory of proxies and admin of those, so with right to change its implementations\\n * - Owned by the Aave Governance\\n * @author Aave\\n **/\\ninterface ILendingPoolAddressesProvider {\\n event MarketIdSet(string newMarketId);\\n event LendingPoolUpdated(address indexed newAddress);\\n event ConfigurationAdminUpdated(address indexed newAddress);\\n event EmergencyAdminUpdated(address indexed newAddress);\\n event LendingPoolConfiguratorUpdated(address indexed newAddress);\\n event LendingPoolCollateralManagerUpdated(address indexed newAddress);\\n event PriceOracleUpdated(address indexed newAddress);\\n event LendingRateOracleUpdated(address indexed newAddress);\\n event ProxyCreated(bytes32 id, address indexed newAddress);\\n event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);\\n\\n function getMarketId() external view returns (string memory);\\n\\n function setMarketId(string calldata marketId) external;\\n\\n function setAddress(bytes32 id, address newAddress) external;\\n\\n function setAddressAsProxy(bytes32 id, address impl) external;\\n\\n function getAddress(bytes32 id) external view returns (address);\\n\\n function getLendingPool() external view returns (address);\\n\\n function setLendingPoolImpl(address pool) external;\\n\\n function getLendingPoolConfigurator() external view returns (address);\\n\\n function setLendingPoolConfiguratorImpl(address configurator) external;\\n\\n function getLendingPoolCollateralManager() external view returns (address);\\n\\n function setLendingPoolCollateralManager(address manager) external;\\n\\n function getPoolAdmin() external view returns (address);\\n\\n function setPoolAdmin(address admin) external;\\n\\n function getEmergencyAdmin() external view returns (address);\\n\\n function setEmergencyAdmin(address admin) external;\\n\\n function getPriceOracle() external view returns (address);\\n\\n function setPriceOracle(address priceOracle) external;\\n\\n function getLendingRateOracle() external view returns (address);\\n\\n function setLendingRateOracle(address lendingRateOracle) external;\\n}\\n\\ninterface IOptionalERC20 {\\n function decimals() external view returns (uint8);\\n}\\n\\ninterface IPriceOracle {\\n function getAssetPrice(address _asset) external view returns (uint256);\\n\\n function getAssetsPrices(address[] calldata _assets) external view returns (uint256[] memory);\\n\\n function getSourceOfAsset(address _asset) external view returns (address);\\n\\n function getFallbackOracle() external view returns (address);\\n}\\n\\ninterface IStakedAave is IERC20 {\\n function stake(address to, uint256 amount) external;\\n\\n function redeem(address to, uint256 amount) external;\\n\\n function cooldown() external;\\n\\n function claimRewards(address to, uint256 amount) external;\\n\\n function getTotalRewardsBalance(address) external view returns (uint256);\\n\\n function COOLDOWN_SECONDS() external view returns (uint256);\\n\\n function stakersCooldowns(address) external view returns (uint256);\\n\\n function UNSTAKE_WINDOW() external view returns (uint256);\\n}\\n\\n/**\\n * @title IInitializableAToken\\n * @notice Interface for the initialize function on AToken\\n * @author Aave\\n **/\\ninterface IInitializableAToken {\\n /**\\n * @dev Emitted when an aToken is initialized\\n * @param underlyingAsset The address of the underlying asset\\n * @param pool The address of the associated lending pool\\n * @param treasury The address of the treasury\\n * @param incentivesController The address of the incentives controller for this aToken\\n * @param aTokenDecimals the decimals of the underlying\\n * @param aTokenName the name of the aToken\\n * @param aTokenSymbol the symbol of the aToken\\n * @param params A set of encoded parameters for additional initialization\\n **/\\n event Initialized(\\n address indexed underlyingAsset,\\n address indexed pool,\\n address treasury,\\n address incentivesController,\\n uint8 aTokenDecimals,\\n string aTokenName,\\n string aTokenSymbol,\\n bytes params\\n );\\n\\n /**\\n * @dev Initializes the aToken\\n * @param pool The address of the lending pool where this aToken will be used\\n * @param treasury The address of the Aave treasury, receiving the fees on this aToken\\n * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)\\n * @param incentivesController The smart contract managing potential incentives distribution\\n * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's\\n * @param aTokenName The name of the aToken\\n * @param aTokenSymbol The symbol of the aToken\\n */\\n function initialize(\\n ILendingPool pool,\\n address treasury,\\n address underlyingAsset,\\n IAaveIncentivesController incentivesController,\\n uint8 aTokenDecimals,\\n string calldata aTokenName,\\n string calldata aTokenSymbol,\\n bytes calldata params\\n ) external;\\n}\\n\\ninterface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {\\n /**\\n * @dev Emitted after the mint action\\n * @param from The address performing the mint\\n * @param value The amount being\\n * @param index The new liquidity index of the reserve\\n **/\\n event Mint(address indexed from, uint256 value, uint256 index);\\n\\n /**\\n * @dev Mints `amount` aTokens to `user`\\n * @param user The address receiving the minted tokens\\n * @param amount The amount of tokens getting minted\\n * @param index The new liquidity index of the reserve\\n * @return `true` if the the previous balance of the user was 0\\n */\\n function mint(\\n address user,\\n uint256 amount,\\n uint256 index\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted after aTokens are burned\\n * @param from The owner of the aTokens, getting them burned\\n * @param target The address that will receive the underlying\\n * @param value The amount being burned\\n * @param index The new liquidity index of the reserve\\n **/\\n event Burn(address indexed from, address indexed target, uint256 value, uint256 index);\\n\\n /**\\n * @dev Emitted during the transfer action\\n * @param from The user whose tokens are being transferred\\n * @param to The recipient\\n * @param value The amount being transferred\\n * @param index The new liquidity index of the reserve\\n **/\\n event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);\\n\\n /**\\n * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`\\n * @param user The owner of the aTokens, getting them burned\\n * @param receiverOfUnderlying The address that will receive the underlying\\n * @param amount The amount being burned\\n * @param index The new liquidity index of the reserve\\n **/\\n function burn(\\n address user,\\n address receiverOfUnderlying,\\n uint256 amount,\\n uint256 index\\n ) external;\\n\\n /**\\n * @dev Mints aTokens to the reserve treasury\\n * @param amount The amount of tokens getting minted\\n * @param index The new liquidity index of the reserve\\n */\\n function mintToTreasury(uint256 amount, uint256 index) external;\\n\\n /**\\n * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken\\n * @param from The address getting liquidated, current owner of the aTokens\\n * @param to The recipient\\n * @param value The amount of tokens getting transferred\\n **/\\n function transferOnLiquidation(\\n address from,\\n address to,\\n uint256 value\\n ) external;\\n\\n /**\\n * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer\\n * assets in borrow(), withdraw() and flashLoan()\\n * @param user The recipient of the underlying\\n * @param amount The amount getting transferred\\n * @return The amount transferred\\n **/\\n function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);\\n\\n /**\\n * @dev Invoked to execute actions on the aToken side after a repayment.\\n * @param user The user executing the repayment\\n * @param amount The amount getting repaid\\n **/\\n function handleRepayment(address user, uint256 amount) external;\\n\\n /**\\n * @dev Returns the address of the incentives controller contract\\n **/\\n function getIncentivesController() external view returns (IAaveIncentivesController);\\n\\n /**\\n * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)\\n **/\\n function UNDERLYING_ASSET_ADDRESS() external view returns (address);\\n}\\n\\n/**\\n * @title IReserveInterestRateStrategyInterface interface\\n * @dev Interface for the calculation of the interest rates\\n * @author Aave\\n */\\ninterface IReserveInterestRateStrategy {\\n function baseVariableBorrowRate() external view returns (uint256);\\n\\n function getMaxVariableBorrowRate() external view returns (uint256);\\n\\n function stableRateSlope1() external view returns (uint256);\\n\\n function stableRateSlope2() external view returns (uint256);\\n\\n function variableRateSlope1() external view returns (uint256);\\n\\n function variableRateSlope2() external view returns (uint256);\\n\\n function OPTIMAL_UTILIZATION_RATE() external view returns (uint256);\\n\\n function calculateInterestRates(\\n address reserve,\\n uint256 availableLiquidity,\\n uint256 totalStableDebt,\\n uint256 totalVariableDebt,\\n uint256 averageStableBorrowRate,\\n uint256 reserveFactor\\n )\\n external\\n view\\n returns (\\n uint256 liquidityRate,\\n uint256 stableBorrowRate,\\n uint256 variableBorrowRate\\n );\\n\\n function calculateInterestRates(\\n address reserve,\\n address aToken,\\n uint256 liquidityAdded,\\n uint256 liquidityTaken,\\n uint256 totalStableDebt,\\n uint256 totalVariableDebt,\\n uint256 averageStableBorrowRate,\\n uint256 reserveFactor\\n )\\n external\\n view\\n returns (\\n uint256 liquidityRate,\\n uint256 stableBorrowRate,\\n uint256 variableBorrowRate\\n );\\n}\\n\",\"keccak256\":\"0x4a127be3e712530ee06158c8db15cb8f72b53fee94a1afabdeddb8c734c67c5a\",\"license\":\"GPL-3.0\"},\"contracts/strategies/AaveFlashloanStrategy/AaveLibraries.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.7;\\n\\nimport { IAToken, IProtocolDataProvider, IProtocolDataProvider, ILendingPool, IPriceOracle, IOptionalERC20 } from \\\"./AaveInterfaces.sol\\\";\\nimport \\\"@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary DataTypes {\\n // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.\\n struct ReserveData {\\n //stores the reserve configuration\\n ReserveConfigurationMap configuration;\\n //the liquidity index. Expressed in ray\\n uint128 liquidityIndex;\\n //variable borrow index. Expressed in ray\\n uint128 variableBorrowIndex;\\n //the current supply rate. Expressed in ray\\n uint128 currentLiquidityRate;\\n //the current variable borrow rate. Expressed in ray\\n uint128 currentVariableBorrowRate;\\n //the current stable borrow rate. Expressed in ray\\n uint128 currentStableBorrowRate;\\n uint40 lastUpdateTimestamp;\\n //tokens addresses\\n address aTokenAddress;\\n address stableDebtTokenAddress;\\n address variableDebtTokenAddress;\\n //address of the interest rate strategy\\n address interestRateStrategyAddress;\\n //the id of the reserve. Represents the position in the list of the active reserves\\n uint8 id;\\n }\\n\\n struct ReserveConfigurationMap {\\n //bit 0-15: LTV\\n //bit 16-31: Liq. threshold\\n //bit 32-47: Liq. bonus\\n //bit 48-55: Decimals\\n //bit 56: Reserve is active\\n //bit 57: reserve is frozen\\n //bit 58: borrowing is enabled\\n //bit 59: stable rate borrowing enabled\\n //bit 60-63: reserved\\n //bit 64-79: reserve factor\\n uint256 data;\\n }\\n\\n struct UserConfigurationMap {\\n uint256 data;\\n }\\n\\n enum InterestRateMode {\\n NONE,\\n STABLE,\\n VARIABLE\\n }\\n}\\n\\nlibrary FlashMintLib {\\n event Leverage(\\n uint256 amountRequested,\\n uint256 amountUsed,\\n uint256 requiredDAI,\\n uint256 amountToCloseLTVGap,\\n bool deficit,\\n address flashLoan\\n );\\n\\n address public constant LENDER = 0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853;\\n uint256 private constant _DAI_DECIMALS = 1e18;\\n uint256 private constant _COLLAT_RATIO_PRECISION = 1 ether;\\n address private constant _WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\\n address private constant _DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\\n IAToken public constant ADAI = IAToken(0x028171bCA77440897B824Ca71D1c56caC55b68A3);\\n IProtocolDataProvider private constant _protocolDataProvider =\\n IProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);\\n ILendingPool private constant _lendingPool = ILendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);\\n\\n bytes32 public constant CALLBACK_SUCCESS = keccak256(\\\"ERC3156FlashBorrower.onFlashLoan\\\");\\n\\n uint16 private constant _referral = 0; // TODO: get our own referral code\\n\\n uint256 private constant _RAY = 10**27;\\n\\n function doFlashMint(\\n bool deficit,\\n uint256 amountDesired,\\n address token,\\n uint256 collatRatioDAI,\\n uint256 depositToCloseLTVGap\\n ) public returns (uint256 amount) {\\n if (amountDesired == 0) {\\n return 0;\\n }\\n amount = amountDesired;\\n address dai = _DAI;\\n\\n // calculate amount of dai we need\\n uint256 requiredDAI;\\n {\\n requiredDAI = (toDAI(amount, token) * _COLLAT_RATIO_PRECISION) / collatRatioDAI;\\n\\n uint256 requiredDAIToCloseLTVGap = 0;\\n if (depositToCloseLTVGap > 0) {\\n requiredDAIToCloseLTVGap = toDAI(depositToCloseLTVGap, token);\\n requiredDAI = requiredDAI + requiredDAIToCloseLTVGap;\\n }\\n\\n uint256 _maxLiquidity = maxLiquidity();\\n\\n /*\\n When depositing/withdrawing in the `lendingPool` the amounts are scaled by a `liquidityIndex` and rounded with the functions rayDiv and rayMul (in the aDAI contract)\\n Weirdly, 2 different indexes are used: `liquidityIndex` is used when depositing and `getReserveNormalizedIncome` when withdrawing\\n Therefore, we need to round `requiredDAI`, or we may get some rounding errors and revert\\n because the amount we try to withdraw (to pay back the flashloan) is not equal to the amount deposited\\n */\\n uint256 liquidityIndex = _lendingPool.getReserveData(dai).liquidityIndex;\\n uint256 getReserveNormalizedIncome = _lendingPool.getReserveNormalizedIncome(dai);\\n uint256 rayDiv = ((requiredDAI * _RAY + liquidityIndex / 2) / liquidityIndex);\\n requiredDAI = (rayDiv * getReserveNormalizedIncome + (_RAY / 2)) / _RAY;\\n\\n if (requiredDAI > _maxLiquidity) {\\n requiredDAI = (_maxLiquidity * _RAY - (_RAY / 2)) / getReserveNormalizedIncome;\\n requiredDAI = (requiredDAI * liquidityIndex - liquidityIndex / 2) / _RAY;\\n\\n // NOTE: if we cap amountDAI, we reduce amountToken we are taking too\\n amount =\\n (fromDAI(requiredDAI - requiredDAIToCloseLTVGap, token) * collatRatioDAI) /\\n _COLLAT_RATIO_PRECISION;\\n }\\n }\\n\\n bytes memory data = abi.encode(deficit, amount);\\n uint256 _fee = IERC3156FlashLender(LENDER).flashFee(dai, requiredDAI);\\n // Check that fees have not been increased without us knowing\\n require(_fee == 0);\\n uint256 _allowance = IERC20(dai).allowance(address(this), address(LENDER));\\n if (_allowance < requiredDAI) {\\n IERC20(dai).approve(address(LENDER), 0);\\n IERC20(dai).approve(address(LENDER), type(uint256).max);\\n }\\n\\n IERC3156FlashLender(LENDER).flashLoan(IERC3156FlashBorrower(address(this)), dai, requiredDAI, data);\\n\\n emit Leverage(amountDesired, amount, requiredDAI, depositToCloseLTVGap, deficit, LENDER);\\n\\n return amount; // we need to return the amount of Token we have changed our position in\\n }\\n\\n function loanLogic(\\n bool deficit,\\n uint256 amount,\\n uint256 amountFlashmint,\\n address want\\n ) public returns (bytes32) {\\n address dai = _DAI;\\n bool isDai = (want == dai);\\n\\n ILendingPool lp = _lendingPool;\\n\\n if (isDai) {\\n if (deficit) {\\n lp.deposit(dai, amountFlashmint - amount, address(this), _referral);\\n lp.repay(dai, IERC20(dai).balanceOf(address(this)), 2, address(this));\\n lp.withdraw(dai, amountFlashmint, address(this));\\n } else {\\n lp.deposit(dai, IERC20(dai).balanceOf(address(this)), address(this), _referral);\\n lp.borrow(dai, amount, 2, _referral, address(this));\\n lp.withdraw(dai, amountFlashmint - amount, address(this));\\n }\\n } else {\\n // 1. Deposit DAI in Aave as collateral\\n lp.deposit(dai, amountFlashmint, address(this), _referral);\\n\\n if (deficit) {\\n // 2a. if in deficit withdraw amount and repay it\\n lp.withdraw(want, amount, address(this));\\n lp.repay(want, IERC20(want).balanceOf(address(this)), 2, address(this));\\n } else {\\n // 2b. if levering up borrow and deposit\\n lp.borrow(want, amount, 2, _referral, address(this));\\n lp.deposit(want, IERC20(want).balanceOf(address(this)), address(this), _referral);\\n }\\n // 3. Withdraw DAI\\n lp.withdraw(dai, amountFlashmint, address(this));\\n }\\n\\n return CALLBACK_SUCCESS;\\n }\\n\\n function priceOracle() internal view returns (IPriceOracle) {\\n return IPriceOracle(_protocolDataProvider.ADDRESSES_PROVIDER().getPriceOracle());\\n }\\n\\n function toDAI(uint256 _amount, address asset) internal view returns (uint256) {\\n address dai = _DAI;\\n if (_amount == 0 || _amount == type(uint256).max || asset == dai) {\\n return _amount;\\n }\\n\\n if (asset == _WETH) {\\n return\\n (_amount * (uint256(10)**uint256(IOptionalERC20(dai).decimals()))) / priceOracle().getAssetPrice(dai);\\n }\\n\\n address[] memory tokens = new address[](2);\\n tokens[0] = asset;\\n tokens[1] = dai;\\n uint256[] memory prices = priceOracle().getAssetsPrices(tokens);\\n\\n uint256 ethPrice = (_amount * prices[0]) / (uint256(10)**uint256(IOptionalERC20(asset).decimals()));\\n return (ethPrice * _DAI_DECIMALS) / prices[1];\\n }\\n\\n function fromDAI(uint256 _amount, address asset) internal view returns (uint256) {\\n address dai = _DAI;\\n if (_amount == 0 || _amount == type(uint256).max || asset == dai) {\\n return _amount;\\n }\\n\\n if (asset == _WETH) {\\n return\\n (_amount * priceOracle().getAssetPrice(dai)) / (uint256(10)**uint256(IOptionalERC20(dai).decimals()));\\n }\\n\\n address[] memory tokens = new address[](2);\\n tokens[0] = asset;\\n tokens[1] = dai;\\n uint256[] memory prices = priceOracle().getAssetsPrices(tokens);\\n\\n uint256 ethPrice = (_amount * prices[1]) / _DAI_DECIMALS;\\n\\n return (ethPrice * (uint256(10)**uint256(IOptionalERC20(asset).decimals()))) / prices[0];\\n }\\n\\n function maxLiquidity() public view returns (uint256) {\\n return IERC3156FlashLender(LENDER).maxFlashLoan(_DAI);\\n }\\n}\\n\",\"keccak256\":\"0x2c6567605d2332c25bf03e02d6b2b22ed131308f6a4071deb6408f64edfed56b\",\"license\":\"GPL-3.0\"},\"contracts/strategies/AaveFlashloanStrategy/ComputeProfitability.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.7;\\n\\n/// @title ComputeProfitability\\n/// @author Angle Core Team\\n/// @notice Helper contract to get the optimal borrow amount from a set of provided parameters from Aave\\nlibrary ComputeProfitability {\\n struct SCalculateBorrow {\\n int256 reserveFactor;\\n int256 totalStableDebt;\\n int256 totalVariableDebt;\\n int256 totalDeposits;\\n int256 stableBorrowRate;\\n int256 rewardDeposit;\\n int256 rewardBorrow;\\n int256 strategyAssets;\\n int256 guessedBorrowAssets;\\n int256 slope1;\\n int256 slope2;\\n int256 r0;\\n int256 uOptimal;\\n }\\n\\n int256 private constant _BASE_RAY = 10**27;\\n\\n /// @notice Computes the Aave utilization ratio\\n function _computeUtilization(int256 borrow, SCalculateBorrow memory parameters) internal pure returns (int256) {\\n return\\n ((parameters.totalStableDebt + parameters.totalVariableDebt + borrow) * _BASE_RAY) /\\n (parameters.totalDeposits + borrow);\\n }\\n\\n /// @notice Computes the derivative of the utilization ratio with respect to the amount borrowed\\n function _computeUprime(int256 borrow, SCalculateBorrow memory parameters) internal pure returns (int256) {\\n return\\n ((parameters.totalDeposits - parameters.totalStableDebt - parameters.totalVariableDebt) * _BASE_RAY) /\\n (parameters.totalDeposits + borrow);\\n }\\n\\n /// @notice Computes the value of the interest rate, its first and second order derivatives\\n /// @dev The returned value is in `_BASE_RAY`\\n function _calculateInterestPrimes(int256 borrow, SCalculateBorrow memory parameters)\\n internal\\n pure\\n returns (\\n int256 interest,\\n int256 interestPrime,\\n int256 interestPrime2\\n )\\n {\\n int256 newUtilization = _computeUtilization(borrow, parameters);\\n int256 denomUPrime = (parameters.totalDeposits + borrow);\\n int256 uprime = _computeUprime(borrow, parameters);\\n uprime = (uprime * _BASE_RAY) / denomUPrime;\\n int256 uprime2nd = -2 * uprime;\\n uprime2nd = (uprime2nd * _BASE_RAY) / denomUPrime;\\n if (newUtilization < parameters.uOptimal) {\\n interest = parameters.r0 + (parameters.slope1 * newUtilization) / parameters.uOptimal;\\n interestPrime = (parameters.slope1 * uprime) / parameters.uOptimal;\\n interestPrime2 = (parameters.slope1 * uprime2nd) / parameters.uOptimal;\\n } else {\\n interest =\\n parameters.r0 +\\n parameters.slope1 +\\n (parameters.slope2 * (newUtilization - parameters.uOptimal)) /\\n (_BASE_RAY - parameters.uOptimal);\\n interestPrime = (parameters.slope2 * uprime) / (_BASE_RAY - parameters.uOptimal);\\n interestPrime2 = (parameters.slope2 * uprime2nd) / (_BASE_RAY - parameters.uOptimal);\\n }\\n }\\n\\n /// @notice Computes the value of the revenue, as well as its first and second order derivatives\\n function _revenuePrimes(\\n int256 borrow,\\n SCalculateBorrow memory parameters,\\n bool onlyRevenue\\n )\\n internal\\n pure\\n returns (\\n int256 revenue,\\n int256 revenuePrime,\\n int256 revenuePrime2nd\\n )\\n {\\n (int256 newRate, int256 newRatePrime, int256 newRatePrime2) = _calculateInterestPrimes(borrow, parameters);\\n\\n // 0 order derivative\\n int256 proportionStrat = ((borrow + parameters.strategyAssets) * (_BASE_RAY - parameters.reserveFactor)) /\\n (borrow + parameters.totalDeposits);\\n int256 poolYearlyRevenue = (parameters.totalStableDebt *\\n parameters.stableBorrowRate +\\n (borrow + parameters.totalVariableDebt) *\\n newRate) / _BASE_RAY;\\n\\n revenue =\\n (proportionStrat * poolYearlyRevenue) /\\n _BASE_RAY +\\n (borrow * parameters.rewardBorrow) /\\n (borrow + parameters.totalVariableDebt) +\\n ((borrow + parameters.strategyAssets) * parameters.rewardDeposit) /\\n (borrow + parameters.totalDeposits) -\\n (borrow * newRate) /\\n _BASE_RAY;\\n\\n if (!onlyRevenue) {\\n // 1st order derivative\\n {\\n // Computing block per block to avoid stack too deep errors\\n int256 proportionStratPrime = ((parameters.totalDeposits - parameters.strategyAssets) *\\n (_BASE_RAY - parameters.reserveFactor)) / (borrow + parameters.totalDeposits);\\n proportionStratPrime = (proportionStratPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\\n int256 poolYearlyRevenuePrime = (newRate *\\n _BASE_RAY +\\n (borrow + parameters.totalVariableDebt) *\\n newRatePrime) / _BASE_RAY;\\n\\n revenuePrime = ((proportionStratPrime * poolYearlyRevenue + poolYearlyRevenuePrime * proportionStrat) /\\n _BASE_RAY);\\n\\n {\\n int256 proportionStratPrime2nd = (-2 * (proportionStratPrime * (_BASE_RAY))) /\\n ((borrow + parameters.totalDeposits));\\n revenuePrime2nd =\\n 2 *\\n proportionStratPrime *\\n poolYearlyRevenuePrime +\\n proportionStratPrime2nd *\\n poolYearlyRevenue;\\n }\\n poolYearlyRevenuePrime =\\n (2 * newRatePrime * _BASE_RAY + (borrow + parameters.totalVariableDebt) * newRatePrime2) /\\n _BASE_RAY;\\n\\n revenuePrime2nd = (revenuePrime2nd + poolYearlyRevenuePrime * proportionStrat) / _BASE_RAY;\\n }\\n\\n int256 costPrime = (newRate * _BASE_RAY + borrow * newRatePrime) / _BASE_RAY;\\n int256 rewardBorrowPrime = (parameters.rewardBorrow * (parameters.totalVariableDebt)) /\\n (borrow + parameters.totalVariableDebt);\\n rewardBorrowPrime = (rewardBorrowPrime * _BASE_RAY) / (borrow + parameters.totalVariableDebt);\\n int256 rewardDepositPrime = (parameters.rewardDeposit *\\n (parameters.totalDeposits - parameters.strategyAssets)) / (borrow + parameters.totalDeposits);\\n rewardDepositPrime = (rewardDepositPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\\n\\n revenuePrime += rewardBorrowPrime + rewardDepositPrime - costPrime;\\n\\n // 2nd order derivative\\n // Reusing variables for the stack too deep issue\\n costPrime = ((2 * newRatePrime * _BASE_RAY) + borrow * newRatePrime2) / _BASE_RAY;\\n rewardBorrowPrime = (-2 * rewardBorrowPrime * _BASE_RAY) / (borrow + parameters.totalVariableDebt);\\n rewardDepositPrime = (-2 * rewardDepositPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\\n\\n revenuePrime2nd += (rewardBorrowPrime + rewardDepositPrime) - costPrime;\\n }\\n }\\n\\n /// @notice Returns the absolute value of an integer\\n function _abs(int256 x) private pure returns (int256) {\\n return x >= 0 ? x : -x;\\n }\\n\\n /// @notice Computes the optimal borrow amount of the strategy depending on Aave protocol parameters\\n /// to maximize folding revenues\\n /// @dev Performs a newton Raphson approximation to get the zero point of the derivative of the\\n /// revenue function of the protocol depending on the amount borrowed\\n function computeProfitability(SCalculateBorrow memory parameters) internal pure returns (int256 borrow) {\\n (int256 y, , ) = _revenuePrimes(0, parameters, true);\\n (int256 revenueWithBorrow, , ) = _revenuePrimes(_BASE_RAY, parameters, true);\\n\\n if (revenueWithBorrow <= y) {\\n return 0;\\n }\\n uint256 count;\\n int256 borrowInit;\\n int256 grad;\\n int256 grad2nd;\\n borrow = parameters.guessedBorrowAssets;\\n // Tolerance is 1% in this method: indeed we're stopping: `_abs(borrowInit - borrow)/ borrowInit < 10**(-2)`\\n while (count < 10 && (count == 0 || _abs(borrowInit - borrow) * (10**2 / 5) > borrowInit)) {\\n (, grad, grad2nd) = _revenuePrimes(borrow, parameters, false);\\n borrowInit = borrow;\\n borrow = borrowInit - (grad * _BASE_RAY) / grad2nd;\\n count += 1;\\n }\\n\\n (int256 x, , ) = _revenuePrimes(borrow, parameters, true);\\n if (x <= y) {\\n borrow = 0;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x38e8f54ce524f92f85bbbe7470333d626f98e97d085af4b4b57f51eb7cddfc33\",\"license\":\"GPL-3.0\"},\"contracts/strategies/BaseStrategyEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"../external/AccessControl.sol\\\";\\nimport \\\"../external/AccessControlUpgradeable.sol\\\";\\n\\nimport \\\"../interfaces/IStrategy.sol\\\";\\nimport \\\"../interfaces/IPoolManager.sol\\\";\\n\\n/// @title BaseStrategyEvents\\n/// @author Angle Core Team\\n/// @notice Events used in the abstract `BaseStrategy` contract\\ncontract BaseStrategyEvents {\\n // So indexers can keep track of this\\n event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);\\n\\n event UpdatedMinReportDelayed(uint256 delay);\\n\\n event UpdatedMaxReportDelayed(uint256 delay);\\n\\n event UpdatedDebtThreshold(uint256 debtThreshold);\\n\\n event UpdatedRewards(address rewards);\\n\\n event UpdatedIsRewardActivated(bool activated);\\n\\n event UpdatedRewardAmountAndMinimumAmountMoved(uint256 _rewardAmount, uint256 _minimumAmountMoved);\\n\\n event EmergencyExitActivated();\\n}\\n\",\"keccak256\":\"0xd7d356e311f65ea6c6bd9c43487d5bfc84666d636ceeb4f264a65a124e95fe1c\",\"license\":\"GPL-3.0\"},\"contracts/strategies/BaseStrategyUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"./BaseStrategyEvents.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\n/// @title BaseStrategyUpgradeable\\n/// @author Forked from https://github.com/yearn/yearn-managers/blob/master/contracts/BaseStrategy.sol\\n/// @notice `BaseStrategyUpgradeable` implements all of the required functionalities to interoperate\\n/// with the `PoolManager` Contract.\\n/// @dev This contract should be inherited and the abstract methods implemented to adapt the `Strategy`\\n/// to the particular needs it has to create a return.\\nabstract contract BaseStrategyUpgradeable is BaseStrategyEvents, AccessControlUpgradeable {\\n using SafeERC20 for IERC20;\\n\\n uint256 public constant BASE = 10**18;\\n uint256 public constant SECONDSPERYEAR = 31556952;\\n\\n /// @notice Role for `PoolManager` only\\n bytes32 public constant POOLMANAGER_ROLE = keccak256(\\\"POOLMANAGER_ROLE\\\");\\n /// @notice Role for guardians and governors\\n bytes32 public constant GUARDIAN_ROLE = keccak256(\\\"GUARDIAN_ROLE\\\");\\n /// @notice Role for keepers\\n bytes32 public constant KEEPER_ROLE = keccak256(\\\"KEEPER_ROLE\\\");\\n\\n // ======================== References to contracts ============================\\n\\n /// @notice Reference to the protocol's collateral `PoolManager`\\n IPoolManager public poolManager;\\n\\n /// @notice Reference to the ERC20 farmed by this strategy\\n IERC20 public want;\\n\\n /// @notice Base of the ERC20 token farmed by this strategy\\n uint256 public wantBase;\\n\\n // ============================ Parameters =====================================\\n\\n /// @notice Use this to adjust the threshold at which running a debt causes a\\n /// harvest trigger. See `setDebtThreshold()` for more details\\n uint256 public debtThreshold;\\n\\n /// @notice See note on `setEmergencyExit()`\\n bool public emergencyExit;\\n\\n // ============================ Constructor ====================================\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() initializer {}\\n\\n /// @notice Constructor of the `BaseStrategyUpgradeable`\\n /// @param _poolManager Address of the `PoolManager` lending collateral to this strategy\\n /// @param governor Governor address of the protocol\\n /// @param guardian Address of the guardian\\n function _initialize(\\n address _poolManager,\\n address governor,\\n address guardian,\\n address[] memory keepers\\n ) internal initializer {\\n poolManager = IPoolManager(_poolManager);\\n want = IERC20(poolManager.token());\\n wantBase = 10**(IERC20Metadata(address(want)).decimals());\\n require(guardian != address(0) && governor != address(0) && governor != guardian, \\\"0\\\");\\n // AccessControl\\n // Governor is guardian so no need for a governor role\\n _setupRole(GUARDIAN_ROLE, guardian);\\n _setupRole(GUARDIAN_ROLE, governor);\\n _setupRole(POOLMANAGER_ROLE, address(_poolManager));\\n _setRoleAdmin(POOLMANAGER_ROLE, POOLMANAGER_ROLE);\\n _setRoleAdmin(GUARDIAN_ROLE, POOLMANAGER_ROLE);\\n\\n // Initializing roles first\\n for (uint256 i = 0; i < keepers.length; i++) {\\n require(keepers[i] != address(0), \\\"0\\\");\\n _setupRole(KEEPER_ROLE, keepers[i]);\\n }\\n _setRoleAdmin(KEEPER_ROLE, GUARDIAN_ROLE);\\n\\n debtThreshold = 100 * BASE;\\n emergencyExit = false;\\n // Give `PoolManager` unlimited access (might save gas)\\n want.safeIncreaseAllowance(address(poolManager), type(uint256).max);\\n }\\n\\n // ========================== Core functions ===================================\\n\\n /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting\\n /// the Strategy's position.\\n function harvest() external {\\n _report();\\n // Check if free returns are left, and re-invest them\\n _adjustPosition();\\n }\\n\\n /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting\\n /// the Strategy's position.\\n /// @param borrowInit Approximate optimal borrows to have faster convergence on the NR method\\n function harvest(uint256 borrowInit) external onlyRole(KEEPER_ROLE) {\\n _report();\\n // Check if free returns are left, and re-invest them, gives an hint on the borrow amount to the NR method\\n // to maximise revenue\\n _adjustPosition(borrowInit);\\n }\\n\\n /// @notice Withdraws `_amountNeeded` to `poolManager`.\\n /// @param _amountNeeded How much `want` to withdraw.\\n /// @return amountFreed How much `want` withdrawn.\\n /// @return _loss Any realized losses\\n /// @dev This may only be called by the `PoolManager`\\n function withdraw(uint256 _amountNeeded)\\n external\\n onlyRole(POOLMANAGER_ROLE)\\n returns (uint256 amountFreed, uint256 _loss)\\n {\\n // Liquidate as much as possible `want` (up to `_amountNeeded`)\\n (amountFreed, _loss) = _liquidatePosition(_amountNeeded);\\n // Send it directly back (NOTE: Using `msg.sender` saves some gas here)\\n want.safeTransfer(msg.sender, amountFreed);\\n // NOTE: Reinvest anything leftover on next `tend`/`harvest`\\n }\\n\\n // ============================ View functions =================================\\n\\n /// @notice Provides an accurate estimate for the total amount of assets\\n /// (principle + return) that this Strategy is currently managing,\\n /// denominated in terms of `want` tokens.\\n /// This total should be \\\"realizable\\\" e.g. the total value that could\\n /// *actually* be obtained from this Strategy if it were to divest its\\n /// entire position based on current on-chain conditions.\\n /// @return The estimated total assets in this Strategy.\\n /// @dev Care must be taken in using this function, since it relies on external\\n /// systems, which could be manipulated by the attacker to give an inflated\\n /// (or reduced) value produced by this function, based on current on-chain\\n /// conditions (e.g. this function is possible to influence through\\n /// flashloan attacks, oracle manipulations, or other DeFi attack\\n /// mechanisms).\\n function estimatedTotalAssets() public view virtual returns (uint256);\\n\\n /// @notice Provides an indication of whether this strategy is currently \\\"active\\\"\\n /// in that it is managing an active position, or will manage a position in\\n /// the future. This should correlate to `harvest()` activity, so that Harvest\\n /// events can be tracked externally by indexing agents.\\n /// @return True if the strategy is actively managing a position.\\n function isActive() public view returns (bool) {\\n return estimatedTotalAssets() > 0;\\n }\\n\\n // ============================ Internal Functions =============================\\n\\n /// @notice PrepareReturn the Strategy, recognizing any profits or losses\\n /// @dev In the rare case the Strategy is in emergency shutdown, this will exit\\n /// the Strategy's position.\\n /// @dev When `_report()` is called, the Strategy reports to the Manager (via\\n /// `poolManager.report()`), so in some cases `harvest()` must be called in order\\n /// to take in profits, to borrow newly available funds from the Manager, or\\n /// otherwise adjust its position. In other cases `harvest()` must be\\n /// called to report to the Manager on the Strategy's position, especially if\\n /// any losses have occurred.\\n /// @dev As keepers may directly profit from this function, there may be front-running problems with miners bots,\\n /// we may have to put an access control logic for this function to only allow white-listed addresses to act\\n /// as keepers for the protocol\\n function _report() internal {\\n uint256 profit = 0;\\n uint256 loss = 0;\\n uint256 debtOutstanding = poolManager.debtOutstanding();\\n uint256 debtPayment = 0;\\n if (emergencyExit) {\\n // Free up as much capital as possible\\n uint256 amountFreed = _liquidateAllPositions();\\n if (amountFreed < debtOutstanding) {\\n loss = debtOutstanding - amountFreed;\\n } else if (amountFreed > debtOutstanding) {\\n profit = amountFreed - debtOutstanding;\\n }\\n debtPayment = debtOutstanding - loss;\\n } else {\\n // Free up returns for Manager to pull\\n (profit, loss, debtPayment) = _prepareReturn(debtOutstanding);\\n }\\n emit Harvested(profit, loss, debtPayment, debtOutstanding);\\n\\n // Allows Manager to take up to the \\\"harvested\\\" balance of this contract,\\n // which is the amount it has earned since the last time it reported to\\n // the Manager.\\n poolManager.report(profit, loss, debtPayment);\\n }\\n\\n /// @notice Performs any Strategy unwinding or other calls necessary to capture the\\n /// \\\"free return\\\" this Strategy has generated since the last time its core\\n /// position(s) were adjusted. Examples include unwrapping extra rewards.\\n /// This call is only used during \\\"normal operation\\\" of a Strategy, and\\n /// should be optimized to minimize losses as much as possible.\\n ///\\n /// This method returns any realized profits and/or realized losses\\n /// incurred, and should return the total amounts of profits/losses/debt\\n /// payments (in `want` tokens) for the Manager's accounting (e.g.\\n /// `want.balanceOf(this) >= _debtPayment + _profit`).\\n ///\\n /// `_debtOutstanding` will be 0 if the Strategy is not past the configured\\n /// debt limit, otherwise its value will be how far past the debt limit\\n /// the Strategy is. The Strategy's debt limit is configured in the Manager.\\n ///\\n /// NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.\\n /// It is okay for it to be less than `_debtOutstanding`, as that\\n /// should only used as a guide for how much is left to pay back.\\n /// Payments should be made to minimize loss from slippage, debt,\\n /// withdrawal fees, etc.\\n ///\\n /// See `poolManager.debtOutstanding()`.\\n function _prepareReturn(uint256 _debtOutstanding)\\n internal\\n virtual\\n returns (\\n uint256 _profit,\\n uint256 _loss,\\n uint256 _debtPayment\\n );\\n\\n /// @notice Performs any adjustments to the core position(s) of this Strategy given\\n /// what change the Manager made in the \\\"investable capital\\\" available to the\\n /// Strategy. Note that all \\\"free capital\\\" in the Strategy after the report\\n /// was made is available for reinvestment. Also note that this number\\n /// could be 0, and you should handle that scenario accordingly.\\n function _adjustPosition() internal virtual;\\n\\n /// @notice same as _adjustPosition but with an initial parameters\\n function _adjustPosition(uint256) internal virtual;\\n\\n /// @notice Liquidates up to `_amountNeeded` of `want` of this strategy's positions,\\n /// irregardless of slippage. Any excess will be re-invested with `_adjustPosition()`.\\n /// This function should return the amount of `want` tokens made available by the\\n /// liquidation. If there is a difference between them, `_loss` indicates whether the\\n /// difference is due to a realized loss, or if there is some other sitution at play\\n /// (e.g. locked funds) where the amount made available is less than what is needed.\\n ///\\n /// NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained\\n function _liquidatePosition(uint256 _amountNeeded)\\n internal\\n virtual\\n returns (uint256 _liquidatedAmount, uint256 _loss);\\n\\n /// @notice Liquidates everything and returns the amount that got freed.\\n /// This function is used during emergency exit instead of `_prepareReturn()` to\\n /// liquidate all of the Strategy's positions back to the Manager.\\n function _liquidateAllPositions() internal virtual returns (uint256 _amountFreed);\\n\\n /// @notice Override this to add all tokens/tokenized positions this contract\\n /// manages on a *persistent* basis (e.g. not just for swapping back to\\n /// want ephemerally).\\n ///\\n /// NOTE: Do *not* include `want`, already included in `sweep` below.\\n ///\\n /// Example:\\n /// ```\\n /// function _protectedTokens() internal override view returns (address[] memory) {\\n /// address[] memory protected = new address[](3);\\n /// protected[0] = tokenA;\\n /// protected[1] = tokenB;\\n /// protected[2] = tokenC;\\n /// return protected;\\n /// }\\n /// ```\\n function _protectedTokens() internal view virtual returns (address[] memory);\\n\\n // ============================== Governance ===================================\\n\\n /// @notice Activates emergency exit. Once activated, the Strategy will exit its\\n /// position upon the next harvest, depositing all funds into the Manager as\\n /// quickly as is reasonable given on-chain conditions.\\n /// @dev This may only be called by the `PoolManager`, because when calling this the `PoolManager` should at the same\\n /// time update the debt ratio\\n /// @dev This function can only be called once by the `PoolManager` contract\\n /// @dev See `poolManager.setEmergencyExit()` and `harvest()` for further details.\\n function setEmergencyExit() external onlyRole(POOLMANAGER_ROLE) {\\n emergencyExit = true;\\n emit EmergencyExitActivated();\\n }\\n\\n /// @notice Sets how far the Strategy can go into loss without a harvest and report\\n /// being required.\\n /// @param _debtThreshold How big of a loss this Strategy may carry without\\n /// @dev By default this is 0, meaning any losses would cause a harvest which\\n /// will subsequently report the loss to the Manager for tracking.\\n function setDebtThreshold(uint256 _debtThreshold) external onlyRole(GUARDIAN_ROLE) {\\n debtThreshold = _debtThreshold;\\n emit UpdatedDebtThreshold(_debtThreshold);\\n }\\n\\n /// @notice Removes tokens from this Strategy that are not the type of tokens\\n /// managed by this Strategy. This may be used in case of accidentally\\n /// sending the wrong kind of token to this Strategy.\\n ///\\n /// Tokens will be sent to `governance()`.\\n ///\\n /// This will fail if an attempt is made to sweep `want`, or any tokens\\n /// that are protected by this Strategy.\\n ///\\n /// This may only be called by governance.\\n /// @param _token The token to transfer out of this `PoolManager`.\\n /// @param to Address to send the tokens to.\\n /// @dev\\n /// Implement `_protectedTokens()` to specify any additional tokens that\\n /// should be protected from sweeping in addition to `want`.\\n function sweep(address _token, address to) external onlyRole(GUARDIAN_ROLE) {\\n require(_token != address(want), \\\"93\\\");\\n\\n address[] memory __protectedTokens = _protectedTokens();\\n for (uint256 i = 0; i < __protectedTokens.length; i++)\\n // In the strategy we use so far, the only protectedToken is the want token\\n // and this has been checked above\\n require(_token != __protectedTokens[i], \\\"93\\\");\\n\\n IERC20(_token).safeTransfer(to, IERC20(_token).balanceOf(address(this)));\\n }\\n\\n // ============================ Manager functions ==============================\\n\\n /// @notice Adds a new guardian address and echoes the change to the contracts\\n /// that interact with this collateral `PoolManager`\\n /// @param _guardian New guardian address\\n /// @dev This internal function has to be put in this file because Access Control is not defined\\n /// in PoolManagerInternal\\n function addGuardian(address _guardian) external virtual;\\n\\n /// @notice Revokes the guardian role and propagates the change to other contracts\\n /// @param guardian Old guardian address to revoke\\n function revokeGuardian(address guardian) external virtual;\\n}\\n\",\"keccak256\":\"0x9639fe29a8ee91e426d85d502daffccfaf8472f98597f038aaf7e18f1a15bab4\",\"license\":\"GPL-3.0\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b50600054610100900460ff166200002f5760005460ff161562000039565b62000039620000de565b620000a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c4576000805461ffff19166101011790555b8015620000d7576000805461ff00191690555b506200010b565b6000620000f630620000fc60201b62001bf51760201c565b15905090565b6001600160a01b03163b151590565b615fe9806200011b6000396000f3fe608060405234801561001057600080fd5b506004361061036d5760003560e01c80634c3f425f116101d3578063abac6e1111610104578063d94fa4af116100a2578063ec342ad01161007c578063ec342ad01461072b578063efbb5cb01461073a578063f8453e7c14610742578063fcf2d0ad1461075557600080fd5b8063d94fa4af146106fc578063dc4c90d314610705578063ddc632621461071857600080fd5b8063b8221bc4116100de578063b8221bc4146106c4578063b8dc491b146106cd578063d0134cb7146106e0578063d547741f146106e957600080fd5b8063abac6e1114610693578063af306e16146106a6578063af648c3d146106b157600080fd5b80638e5b14b011610171578063a34a42231161014b578063a34a42231461065b578063a526d83b1461066e578063a62b75a814610681578063a8f9c0d81461068a57600080fd5b80638e5b14b01461063757806391d1485414610640578063a217fddf1461065357600080fd5b80635e4a1e01116101ad5780635e4a1e01146106135780636314e8841461061c578063659621b51461062557806386d8745b1461062e57600080fd5b80634c3f425f146105f65780635641ec03146105fe5780635a5cd45e1461060b57600080fd5b80632e1a7d4d116102ad578063372500ab1161024b578063418f35cc11610225578063418f35cc146105d45780634322b714146105dc5780634641257d146105e55780634c32e270146105ed57600080fd5b8063372500ab1461059a578063387f504a146105a2578063396794cd146105c157600080fd5b80633042087c116102875780633042087c146104fa578063364bc15a1461050d57806336568abe14610534578063368a9d6d1461054757600080fd5b80632e1a7d4d146104b65780632e4debb3146104de5780632f2ff15d146104e757600080fd5b80631f1fcd511161031a57806323cf978f116102f457806323cf978f1461044557806323e30c8b14610458578063248a9ca31461046b57806324ea54f41461048f57600080fd5b80631f1fcd51146103f9578063205409d31461042457806322f3e2d41461042d57600080fd5b80630c016dc01161034b5780630c016dc0146103b65780630f969b87146103dd5780631d12f28b146103f057600080fd5b806305b4193414610372578063060ca2ba146103875780630b6d1d171461039a575b600080fd5b61038561038036600461570b565b61075d565b005b6103856103953660046157d8565b610881565b6103a360355481565b6040519081526020015b60405180910390f35b6103a37f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56281565b6103856103eb3660046155d3565b61097f565b6103a360365481565b60345461040c906001600160a01b031681565b6040516001600160a01b0390911681526020016103ad565b6103a360435481565b6104356109e6565b60405190151581526020016103ad565b6103856104533660046155d3565b6109f7565b6103a36104663660046153da565b610a79565b6103a36104793660046155d3565b6000908152600160208190526040909120015490565b6103a37f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b6104c96104c43660046155d3565b610bd1565b604080519283526020830191909152016103ad565b6103a3603e5481565b6103856104f5366004615605565b610c2a565b6103856105083660046155d3565b610c56565b6103a37ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab81565b610385610542366004615605565b610c94565b6047546105709060ff808216916101008104821691620100008204811691630100000090041684565b604080519415158552921515602085015290151591830191909152151560608201526080016103ad565b610385610cfa565b6046546105af9060ff1681565b60405160ff90911681526020016103ad565b6103856105cf3660046155d3565b610d2d565b6104c9610d61565b6103a3603a5481565b610385610d7c565b6103a360405481565b610385610d8e565b6037546104359060ff1681565b6103a3610d96565b6103a360455481565b6103a360395481565b6103a3603d5481565b6103a360445481565b6103a360415481565b61043561064e366004615605565b61129b565b6103a3600081565b61038561066936600461562a565b6112c8565b61038561067c36600461531a565b61138f565b6103a3603b5481565b6103a3603f5481565b6103856106a1366004615927565b6113e4565b6103a36301e1855881565b6103856106bf36600461531a565b61149d565b6103a360385481565b6103856106db366004615354565b6114f2565b6103a3603c5481565b6103856106f7366004615605565b6116ab565b6103a360425481565b60335461040c906001600160a01b031681565b6103856107263660046155d3565b6116d2565b6103a3670de0b6b3a764000081565b6103a361170e565b610385610750366004615484565b61180b565b610385611b91565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab6107888133611c04565b600080731111111254fb6c44bac0bed2854e76f90643097d6001600160a01b0316846040516107b791906159fb565b6000604051808303816000865af19150503d80600081146107f4576040519150601f19603f3d011682016040523d82523d6000602084013e6107f9565b606091505b50915091508161080c5761080c81611c68565b60008180602001905181019061082291906155ec565b9050858110156108795760405162461bcd60e51b815260206004820152600260248201527f313500000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b505050505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416108ac8133611c04565b60345460009081906108c6906001600160a01b0316611cbf565b9150915060006108e9736b175474e89094c44da98b954eedeac495271d0f611cbf565b50905081881080156108fa57508187105b801561090557508688105b801561091057508286105b801561091b57508085105b6109675760405162461bcd60e51b815260206004820152600160248201527f38000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b505050604094909455604192909255603f5560425550565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416109aa8133611c04565b60368290556040518281527fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a86009060200160405180910390a15050565b6000806109f161170e565b11905090565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610a228133611c04565b6127108210610a735760405162461bcd60e51b815260206004820152600160248201527f34000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b50604555565b600033731eb4cf3a948e7d72a198fe073ccb8c7a948cd853148015610aa657506001600160a01b03871630145b610af25760405162461bcd60e51b815260206004820152600160248201527f31000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b600080610b01848601866155a7565b6034546040517fbf04d6e8000000000000000000000000000000000000000000000000000000008152831515600482015260248101839052604481018b90526001600160a01b039091166064820152919350915073169487a55de79476125a56b07c36ca8dbf37a3739063bf04d6e89060840160206040518083038186803b158015610b8c57600080fd5b505af4158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906155ec565b9998505050505050505050565b6000807f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562610bff8133611c04565b610c0884611da4565b6034549194509250610c24906001600160a01b03163385611dd4565b50915091565b60008281526001602081905260409091200154610c478133611c04565b610c518383611e7d565b505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610c818133611c04565b610c8a82611ee8565b50610c5182611fb5565b6001600160a01b0381163314610cec5760405162461bcd60e51b815260206004820152600260248201527f37310000000000000000000000000000000000000000000000000000000000006044820152606401610870565b610cf68282612082565b5050565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab610d258133611c04565b610cf66120e9565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610d588133611c04565b610c5182611ee8565b600080610d6c61235d565b9150610d766123df565b90509091565b610d84612410565b610d8c6125dc565b565b610d8c6125e7565b6034546040517f35ea6a750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009081908190819073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b158015610e1057600080fd5b505afa158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4891906158b1565b50505050509450945094505050600080610e60610d61565b915091506000806000610e7a670de0b6b3a76400006129fb565b90506000604860009054906101000a90046001600160a01b03166001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b158015610ecc57600080fd5b505afa158015610ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f049190615337565b6048546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015291169063f11b81889060240160606040518083038186803b158015610f6157600080fd5b505afa158015610f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9991906157aa565b505090506000604960009054906101000a90046001600160a01b03166001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b158015610fed57600080fd5b505afa158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190615337565b6049546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015291169063f11b81889060240160606040518083038186803b15801561108257600080fd5b505afa158015611096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ba91906157aa565b50509050600082603c6110cd9190615d99565b6110d890603c615d99565b6110e3906018615d99565b6110ef9061016d615d99565b905060006110fe83603c615d99565b61110990603c615d99565b611114906018615d99565b6111209061016d615d99565b9050604860009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a891906155ec565b856111b3848c615d99565b6111bd9190615d99565b6111cb90633b9aca00615d99565b6111d59190615bf7565b96508b856111e3838b615d99565b6111ed9190615d99565b6111fb90633b9aca00615d99565b6112059190615bf7565b9550505050505060006112166123df565b61121e61235d565b611226612ace565b6112309190615bb1565b61123a9190615e10565b9050670de0b6b3a7640000816112508689615d99565b848661125c8a8d615d99565b6112669190615bb1565b6112709190615bb1565b61127a9190615e10565b6112849190615bf7565b61128e9190615bf7565b9850505050505050505090565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416112f38133611c04565b508051604780546020840151604085015160609095015161ffff1990921693151561ff0019169390931761010093151593909302929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1662010000931515939093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff1692909217630100000091151591909102179055565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe5626113ba8133611c04565b610cf67f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183611e7d565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161140f8133611c04565b603f5483108015611423575060008260ff16115b8015611432575060108260ff16105b61147e5760405162461bcd60e51b815260206004820152600160248201527f38000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b506043929092556044556046805460ff191660ff909216919091179055565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe5626114c88133611c04565b610cf67f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183612082565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161151d8133611c04565b6034546001600160a01b038481169116141561157b5760405162461bcd60e51b815260206004820152600260248201527f39330000000000000000000000000000000000000000000000000000000000006044820152606401610870565b606060005b81518110156116165781818151811061159b5761159b615f20565b60200260200101516001600160a01b0316856001600160a01b031614156116045760405162461bcd60e51b815260206004820152600260248201527f39330000000000000000000000000000000000000000000000000000000000006044820152606401610870565b8061160e81615e6a565b915050611580565b506040516370a0823160e01b81523060048201526116a59084906001600160a01b038716906370a082319060240160206040518083038186803b15801561165c57600080fd5b505afa158015611670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169491906155ec565b6001600160a01b0387169190611dd4565b50505050565b600082815260016020819052604090912001546116c88133611c04565b610c518383612082565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab6116fd8133611c04565b611705612410565b610cf682612aff565b600080600061171b610d61565b90925090506117dc73d784927ff2f95ba542bfc824c8a8a98f3495f6b5638b599f26611745612ce2565b306040518363ffffffff1660e01b8152600401611763929190615a98565b60206040518083038186803b15801561177b57600080fd5b505afa15801561178f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b391906155ec565b6117bb612d76565b6117c3612db0565b6117cd9190615bb1565b6117d79190615bb1565b6129fb565b81836117e6612ace565b6117f09190615bb1565b6117fa9190615e10565b6118049190615bb1565b9250505090565b61181785848484612dea565b60468054600660ff1990911617905560646043556611c37937e080006044556123286045556040805160808101825260018082526020820181905260009282019290925260600152604780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000166301000101179055603780547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101006001600160a01b038716021790556118cc6125e7565b6034546040517fd2493b6c0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152600090819073057835ad21a177dbdd3090bb1cae03eacf78fc6d9063d2493b6c9060240160606040518083038186803b15801561194157600080fd5b505afa158015611955573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611979919061538d565b604880546001600160a01b038086167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556049805483851692169190911790556034549395509093506000928392506119d89116611cbf565b90925090506119ee66470de4df82000082615e10565b604055611a026611c37937e0800082615e10565b604155611a166611c37937e0800083615e10565b603f556000611a38736b175474e89094c44da98b954eedeac495271d0f611cbf565b509050611a4c6611c37937e0800082615e10565b604255603454611a79906001600160a01b0316737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b611a9785737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b611ac9736b175474e89094c44da98b954eedeac495271d0f731eb4cf3a948e7d72a198fe073ccb8c7a948cd853613322565b611afb734da27a545c0c5b758a6ba100e3a049001de870f5731111111254fb6c44bac0bed2854e76f90643097d613322565b611b2d737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9731111111254fb6c44bac0bed2854e76f90643097d613322565b6034546001600160a01b0316736b175474e89094c44da98b954eedeac495271d0f14611b8557611b85736b175474e89094c44da98b954eedeac495271d0f737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b50505050505050505050565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562611bbc8133611c04565b6037805460ff191660011790556040517f17fa25a1c2ac074f71f0cf4f6af525c06fab7d83eff5ffcf6df5277f2919ae2490600090a150565b6001600160a01b03163b151590565b611c0e828261129b565b610cf657611c26816001600160a01b03166014613338565b611c31836020613338565b604051602001611c42929190615a17565b60408051601f198184030181529082905262461bcd60e51b825261087091600401615af5565b805115611c7757805181602001fd5b60405162461bcd60e51b815260206004820152600360248201527f31313700000000000000000000000000000000000000000000000000000000006044820152606401610870565b6040517f3e1501410000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152600090819073057835ad21a177dbdd3090bb1cae03eacf78fc6d90633e150141906024016101406040518083038186803b158015611d3157600080fd5b505afa158015611d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d69919061580a565b50969950949750611d8b9650655af3107a40009550889450615d999350505050565b9150611d9d655af3107a400082615d99565b9050915091565b600080600080611db2610d61565b91509150611dc985611dc2612ace565b8484613561565b935093505050915091565b6040516001600160a01b038316602482015260448101829052610c519084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261363f565b611e87828261129b565b610cf65760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b600081611ef757506000919050565b6034546040517f69328dec0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260248101839052306044820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a9906369328dec90606401602060405180830381600087803b158015611f7657600080fd5b505af1158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae91906155ec565b5090919050565b600081611fc457506000919050565b6034546040517f573ade810000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024810183905260026044820152306064820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063573ade8190608401602060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c291906155ec565b61208c828261129b565b15610cf65760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006120f3612db0565b90506000811561210857612105613724565b90505b6000821180156121185750806001145b15612227576040517f9a99b4f00000000000000000000000000000000000000000000000000000000081523060048201526000196024820152734da27a545c0c5b758a6ba100e3a049001de870f590639a99b4f090604401600060405180830381600087803b15801561218a57600080fd5b505af115801561219e573d6000803e3d6000fd5b50506040517f1e9a695000000000000000000000000000000000000000000000000000000000815230600482015260248101859052734da27a545c0c5b758a6ba100e3a049001de870f59250631e9a69509150604401600060405180830381600087803b15801561220e57600080fd5b505af1158015612222573d6000803e3d6000fd5b505050505b73d784927ff2f95ba542bfc824c8a8a98f3495f6b5633111e7b3612249612ce2565b600019306040518463ffffffff1660e01b815260040161226b93929190615ac3565b602060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd91906155ec565b506122c6612db0565b6047549092506301000000900460ff1680156122e25750600082115b80156122ec575080155b1561235957734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b031663787a08a66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561234057600080fd5b505af1158015612354573d6000803e3d6000fd5b505050505b5090565b6048546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b60206040518083038186803b1580156123a257600080fd5b505afa1580156123b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123da91906155ec565b905090565b6049546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240161238a565b6000806000603360009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561246357600080fd5b505afa158015612477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249b91906155ec565b60375490915060009060ff16156124f85760006124b6613825565b9050828110156124d1576124ca8184615e10565b93506124e6565b828111156124e6576124e38382615e10565b94505b6124f08484615e10565b915050612509565b61250182613838565b919550935090505b6040805185815260208101859052908101829052606081018390527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a16033546040517fa1d9bafc0000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018390526001600160a01b039091169063a1d9bafc90606401600060405180830381600087803b1580156125be57600080fd5b505af11580156125d2573d6000803e3d6000fd5b5050505050505050565b610d8c600019612aff565b6034546040517f3e1501410000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009073057835ad21a177dbdd3090bb1cae03eacf78fc6d90633e150141906024016101406040518083038186803b15801561265b57600080fd5b505afa15801561266f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612693919061580a565b5050505050945050505050734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b03166372b49d636040518163ffffffff1660e01b815260040160206040518083038186803b1580156126eb57600080fd5b505afa1580156126ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272391906155ec565b603881905550734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b031663359c4a966040518163ffffffff1660e01b815260040160206040518083038186803b15801561277657600080fd5b505afa15801561278a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ae91906155ec565b6039556127c58169152d02c7e14af6800000615d99565b603a81905550603760019054906101000a90046001600160a01b03166001600160a01b0316637b832f586040518163ffffffff1660e01b815260040160206040518083038186803b15801561281957600080fd5b505afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285191906155ec565b603b81905550603760019054906101000a90046001600160a01b03166001600160a01b03166365614f816040518163ffffffff1660e01b815260040160206040518083038186803b1580156128a557600080fd5b505afa1580156128b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128dd91906155ec565b603c81905550603760019054906101000a90046001600160a01b03166001600160a01b031663b25895446040518163ffffffff1660e01b815260040160206040518083038186803b15801561293157600080fd5b505afa158015612945573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296991906155ec565b603d81905550603760019054906101000a90046001600160a01b03166001600160a01b031663a15f30ac6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129bd57600080fd5b505afa1580156129d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f591906155ec565b603e5550565b60008073547a514d5e3769680ce22b2361c10ea13619e8a96001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015612a4b57600080fd5b505afa158015612a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a839190615955565b5050509150506c0c9f2c9cd04674edea400000006045546035548584612aa99190615d99565b612ab39190615d99565b612abd9190615d99565b612ac79190615bf7565b9392505050565b6034546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240161238a565b603354604080517fbf3759b500000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612b5d57600080fd5b505afa158015612b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b9591906155ec565b90506000612ba1612ace565b90508181118015612bbc5750604354612bba8383615e10565b115b15612bdf57612bd3612bce8383615e10565b6139d7565b50612bdc612ace565b90505b600080612bea610d61565b915091506000198514612bfd5784612bff565b805b60475490955060009060ff1615612c3757612c3082612c1e8587615bb1565b612c289190615e10565b848489613a8b565b9050612c3c565b506040545b6000612c488484613ad3565b905084861115612c72576000612c5e8688615e10565b9050612c6b818686613aee565b5050612cd9565b81811015612c9c57604454612c878284615e10565b1115612c9757612c978484613b4b565b612cd9565b81811115612cd957604454612cb18383615e10565b1115612cd9576000612ccc612cc68587615e10565b84613bfd565b90506125d2818686613c1b565b50505050505050565b6040805160028082526060808301845292602083019080368337505060485482519293506001600160a01b031691839150600090612d2257612d22615f20565b6001600160a01b039283166020918202929092010152604954825191169082906001908110612d5357612d53615f20565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b6040516370a0823160e01b8152306004820152600090737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9906370a082319060240161238a565b6040516370a0823160e01b8152306004820152600090734da27a545c0c5b758a6ba100e3a049001de870f5906370a082319060240161238a565b600054610100900460ff16612e055760005460ff1615612e09565b303b155b612e7b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610870565b600054610100900460ff16158015612e9d576000805461ffff19166101011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905163fc0c546a91600480820192602092909190829003018186803b158015612f2257600080fd5b505afa158015612f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5a9190615337565b603480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169182179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce56791600480820192602092909190829003018186803b158015612fe057600080fd5b505afa158015612ff4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301891906159a5565b61302390600a615c4e565b6035556001600160a01b0383161580159061304657506001600160a01b03841615155b80156130645750826001600160a01b0316846001600160a01b031614155b6130b05760405162461bcd60e51b815260206004820152600160248201527f30000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b6130da7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504184613d4f565b6131047f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504185613d4f565b61312e7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56286613d4f565b6131587f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56280613d59565b6131a27f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50417f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562613d59565b60005b825181101561327f5760006001600160a01b03168382815181106131cb576131cb615f20565b60200260200101516001600160a01b0316141561322a5760405162461bcd60e51b815260206004820152600160248201527f30000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b61326d7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab84838151811061326057613260615f20565b6020026020010151613d4f565b8061327781615e6a565b9150506131a5565b506132ca7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041613d59565b6132dd670de0b6b3a76400006064615d99565b6036556037805460ff19169055603354603454613309916001600160a01b039182169116600019613db0565b801561331b576000805461ff00191690555b5050505050565b610cf66001600160a01b03831682600019613ea3565b60606000613347836002615d99565b613352906002615bb1565b67ffffffffffffffff81111561336a5761336a615f4f565b6040519080825280601f01601f191660200182016040528015613394576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106133cb576133cb615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061342e5761342e615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061346a846002615d99565b613475906001615bb1565b90505b6001811115613512577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106134b6576134b6615f20565b1a60f81b8282815181106134cc576134cc615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361350b81615e53565b9050613478565b508315612ac75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610870565b6000808585111561357757508490506000613636565b60006135838688615e10565b9050613590818686613aee565b50613599612ace565b9550858711156135c75785925060006135b28489615e10565b905060435481116135c1578092505b506135cb565b8692505b60475462010000900460ff1615613634576135e68284615bb1565b87146136345760405162461bcd60e51b815260206004820152600260248201527f35340000000000000000000000000000000000000000000000000000000000006044820152606401610870565b505b94509492505050565b6000613694826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166140009092919063ffffffff16565b805190915015610c5157808060200190518101906136b2919061558a565b610c515760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610870565b6040517f091030c30000000000000000000000000000000000000000000000000000000081523060048201526000908190734da27a545c0c5b758a6ba100e3a049001de870f59063091030c39060240160206040518083038186803b15801561378c57600080fd5b505afa1580156137a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c491906155ec565b90506000603854826137d69190615bb1565b9050816137e65760009250505090565b804211801561380157506039546137fd9082615bb1565b4211155b1561380f5760019250505090565b804210156138205760029250505090565b505090565b6000613832600019611da4565b50919050565b6033546040517f39ebf8230000000000000000000000000000000000000000000000000000000081523060048201526000918291829182916001600160a01b03909116906339ebf8239060240160606040518083038186803b15801561389d57600080fd5b505afa1580156138b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d591906156af565b60200151905060006138e5612ace565b90506000806138f2610d61565b90925090506000816139048486615bb1565b61390e9190615e10565b905080851115613929576139228186615e10565b9650613936565b6139338582615e10565b97505b6000613942898b615bb1565b9050848111156139a95761395881868686613561565b50945080851061398857899650886139708883615e10565b1015613983576139808782615e10565b98505b6139ca565b8985101561399c57600098508496506139ca565b8996506139808786615e10565b899650886139b78883615e10565b10156139ca576139c78782615e10565b98505b5050505050509193909250565b6000816139e657506000919050565b6034546040517fe8eda9df0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024810183905230604482015260006064820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063e8eda9df906084015b600060405180830381600087803b158015613a6d57600080fd5b505af1158015613a81573d6000803e3d6000fd5b5093949350505050565b600080613a9a86868686614017565b90506000613ab1613aab8389615bb1565b83613ad3565b60415490915080821115613ac3578091505b5060408190559695505050505050565b600082156112c25782612abd670de0b6b3a764000084615d99565b600083613afd57506000612ac7565b6000613b098385615e10565b90506000613b2c613b1a8784614455565b613b249084615e10565b604054613bfd565b9050613b39818686613c1b565b613b41612ace565b9695505050505050565b600081613b5b613b248286615e10565b613b659190615e10565b604754909150610100900460ff1615613bac57613b83818484614464565b613b8d9082615e10565b9050604354811115610c5157613ba2816144fc565b6116a59082615e10565b60005b60465460ff908116908216108015613bc8575060435482115b156116a557613bd8828585614464565b613be29083615e10565b60009450849350915080613bf581615e85565b915050613baf565b6000613c1182670de0b6b3a7640000615e10565b612abd8385615d99565b82811115613ce3576000613c2f8483615e10565b604754909150610100900460ff1615613c5957613c4c81836145fa565b613c569082615e10565b90505b60415460005b60465460ff908116908216108015613c78575060435483115b15613cd257613c89826000806146de565b50826000613c95612ace565b905080821115613ca3578091505b6000613cae83611fb5565b9050613cba8187615e10565b95505050508080613cca90615e85565b915050613c5f565b50613cdb610d61565b909450925050505b6040546000613cf383838661473e565b905083811115613d31576000613d098583615e10565b9050604354811115613d2b57613d29612bce82613d24612ace565b614455565b505b5061331b565b604354613d3e8286615e10565b111561331b576108798285856146de565b610cf68282611e7d565b60008281526001602081905260409091200154819060405184907fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff90600090a4600091825260016020819052604090922090910155565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015613e1557600080fd5b505afa158015613e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e4d91906155ec565b613e579190615bb1565b6040516001600160a01b0385166024820152604481018290529091506116a59085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611e19565b801580613f4557506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613f0b57600080fd5b505afa158015613f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4391906155ec565b155b613fb75760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610870565b6040516001600160a01b038316602482015260448101829052610c519084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611e19565b606061400f8484600085614771565b949350505050565b6000806035546b033b2e3c9fd0803ce80000006140349190615bf7565b90506140a1604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6034546040517f35ea6a750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009081908190819073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b15801561411b57600080fd5b505afa15801561412f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415391906158b1565b5050509650505050935093509350604051806101a00160405280603a54815260200187856141819190615d99565b8152602001876141918c86615e10565b61419b9190615d99565b8152602001878c8e866141ae898b615bb1565b6141b89190615bb1565b6141c29190615bb1565b6141cc9190615e10565b6141d69190615d99565b81526020018281526020016000815260200160008152602001878d6141fb9190615d99565b815260200161420a888b615d99565b8152602001603b548152602001603c548152602001603d548152602001603e548152509450505050506000614246670de0b6b3a76400006129fb565b6048546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015290915060009073d784927ff2f95ba542bfc824c8a8a98f3495f6b59063f11b81889060240160606040518083038186803b1580156142bc57600080fd5b505afa1580156142d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f491906157aa565b50506049546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015290915060009073d784927ff2f95ba542bfc824c8a8a98f3495f6b59063f11b81889060240160606040518083038186803b15801561436c57600080fd5b505afa158015614380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143a491906157aa565b5050603554909150836143ba8462015180615d99565b6143c69061016d615d99565b6143d09190615d99565b6143de90633b9aca00615d99565b6143e89190615bf7565b60a0850152603554836143fe8362015180615d99565b61440a9061016d615d99565b6144149190615d99565b61442290633b9aca00615d99565b61442c9190615bf7565b60c0850152508391506144409050826148ae565b61444a9190615bf7565b979650505050505050565b6000818310611fae5781612ac7565b600082158015614472575081155b156144855761447f610d61565b90935091505b600061448f612ace565b905060006144a86144a08387615bb1565b603f546149b7565b90508381116144bc57600092505050612ac7565b6144c68482615e10565b9050858110156144d4578095505b6144dd826139d7565b506144e7866149cc565b506144f1866139d7565b509495945050505050565b6000806000614509610d61565b91509150600061451c82603f548561473e565b9050600083821115614535576145328483615e10565b90505b6034546042546040517fbf5061df00000000000000000000000000000000000000000000000000000000815260006004820152602481018990526001600160a01b03909216604483015260648201526084810182905273169487a55de79476125a56b07c36ca8dbf37a3739063bf5061df9060a40160206040518083038186803b1580156145c257600080fd5b505af41580156145d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4191906155ec565b6000604354831161460d575060006112c2565b81831115614619578192505b6034546042546040517fbf5061df00000000000000000000000000000000000000000000000000000000815260016004820152602481018690526001600160a01b03909216604483015260648201526000608482015273169487a55de79476125a56b07c36ca8dbf37a3739063bf5061df9060a40160206040518083038186803b1580156146a657600080fd5b505af41580156146ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac791906155ec565b6000821580156146ec575081155b156146ff576146f9610d61565b90935091505b600061470c83868661473e565b9050808411156147365760006147228286615e10565b905061472d81611ee8565b92505050612ac7565b509392505050565b6000821561476a5782614759670de0b6b3a764000086615d99565b6147639190615bf7565b9050612ac7565b5080612ac7565b6060824710156147e95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610870565b6001600160a01b0385163b6148405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610870565b600080866001600160a01b0316858760405161485c91906159fb565b60006040518083038185875af1925050503d8060008114614899576040519150601f19603f3d011682016040523d82523d6000602084013e61489e565b606091505b509150915061444a828286614a47565b6000806148be6000846001614a80565b5050905060006148dc6b033b2e3c9fd0803ce8000000856001614a80565b505090508181136148f1575060009392505050565b60008060008087610100015196505b600a8410801561493357508315806149335750826149266149218983615db8565b615052565b614931906014615cf9565b135b1561498d5761494487896000614a80565b89955090935091508190506149656b033b2e3c9fd0803ce800000084615cf9565b61496f9190615bc9565b6149799084615db8565b9650614986600185615bb1565b9350614900565b600061499b888a6001614a80565b505090508681136149ab57600097505b50505050505050919050565b6000670de0b6b3a7640000612abd8385615d99565b6034546040517fa415bcad0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602481018290526002604482015260006064820181905230608483015290737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063a415bcad9060a401613a53565b60608315614a56575081612ac7565b825115614a665782518084602001fd5b8160405162461bcd60e51b81526004016108709190615af5565b600080600080600080614a93898961506a565b925092509250600088606001518a614aab9190615b59565b8951614ac3906b033b2e3c9fd0803ce8000000615db8565b60e08b0151614ad2908d615b59565b614adc9190615cf9565b614ae69190615bc9565b905060006b033b2e3c9fd0803ce8000000858b604001518d614b089190615b59565b614b129190615cf9565b8b608001518c60200151614b269190615cf9565b614b309190615b59565b614b3a9190615bc9565b90506b033b2e3c9fd0803ce8000000614b53868d615cf9565b614b5d9190615bc9565b60608b0151614b6c908d615b59565b60a08c015160e08d0151614b80908f615b59565b614b8a9190615cf9565b614b949190615bc9565b60408c0151614ba3908e615b59565b60c08d0151614bb2908f615cf9565b614bbc9190615bc9565b6b033b2e3c9fd0803ce8000000614bd38587615cf9565b614bdd9190615bc9565b614be79190615b59565b614bf19190615b59565b614bfb9190615db8565b9750886150445760008a606001518c614c149190615b59565b8b51614c2c906b033b2e3c9fd0803ce8000000615db8565b8c60e001518d60600151614c409190615db8565b614c4a9190615cf9565b614c549190615bc9565b90508a606001518c614c669190615b59565b614c7c6b033b2e3c9fd0803ce800000083615cf9565b614c869190615bc9565b905060006b033b2e3c9fd0803ce8000000868d604001518f614ca89190615b59565b614cb29190615cf9565b614cc86b033b2e3c9fd0803ce80000008a615cf9565b614cd29190615b59565b614cdc9190615bc9565b90506b033b2e3c9fd0803ce8000000614cf58583615cf9565b614cff8585615cf9565b614d099190615b59565b614d139190615bc9565b985060008c606001518e614d279190615b59565b614d3d6b033b2e3c9fd0803ce800000085615cf9565b614d4990600119615cf9565b614d539190615bc9565b9050614d5f8482615cf9565b82614d6b856002615cf9565b614d759190615cf9565b614d7f9190615b59565b9850506b033b2e3c9fd0803ce8000000858d604001518f614da09190615b59565b614daa9190615cf9565b6b033b2e3c9fd0803ce8000000614dc2896002615cf9565b614dcc9190615cf9565b614dd69190615b59565b614de09190615bc9565b90506b033b2e3c9fd0803ce8000000614df98583615cf9565b614e03908a615b59565b614e0d9190615bc9565b9750505060006b033b2e3c9fd0803ce8000000858d614e2c9190615cf9565b614e426b033b2e3c9fd0803ce800000089615cf9565b614e4c9190615b59565b614e569190615bc9565b905060008b604001518d614e6a9190615b59565b8c604001518d60c00151614e7e9190615cf9565b614e889190615bc9565b90508b604001518d614e9a9190615b59565b614eb06b033b2e3c9fd0803ce800000083615cf9565b614eba9190615bc9565b905060008c606001518e614ece9190615b59565b8d60e001518e60600151614ee29190615db8565b8e60a00151614ef19190615cf9565b614efb9190615bc9565b90508c606001518e614f0d9190615b59565b614f236b033b2e3c9fd0803ce800000083615cf9565b614f2d9190615bc9565b905082614f3a8284615b59565b614f449190615db8565b614f4e908b615b59565b99506b033b2e3c9fd0803ce8000000868f614f699190615cf9565b6b033b2e3c9fd0803ce8000000614f818a6002615cf9565b614f8b9190615cf9565b614f959190615b59565b614f9f9190615bc9565b92508c604001518e614fb19190615b59565b6b033b2e3c9fd0803ce8000000614fca84600119615cf9565b614fd49190615cf9565b614fde9190615bc9565b91508c606001518e614ff09190615b59565b6b033b2e3c9fd0803ce800000061500983600119615cf9565b6150139190615cf9565b61501d9190615bc9565b90508261502a8284615b59565b6150349190615db8565b61503e908a615b59565b98505050505b505050505093509350939050565b6000808212156123595761506582615ea5565b6112c2565b60008060008061507a8686615267565b9050600086866060015161508e9190615b59565b9050600061509c88886152b9565b9050816150b56b033b2e3c9fd0803ce800000083615cf9565b6150bf9190615bc9565b905060006150cf82600119615cf9565b9050826150e86b033b2e3c9fd0803ce800000083615cf9565b6150f29190615bc9565b905087610180015184121561517f57876101800151848961012001516151189190615cf9565b6151229190615bc9565b8861016001516151329190615b59565b96508761018001518289610120015161514b9190615cf9565b6151559190615bc9565b95508761018001518189610120015161516e9190615cf9565b6151789190615bc9565b945061525c565b61018088015161519b906b033b2e3c9fd0803ce8000000615db8565b6101808901516151ab9086615db8565b8961014001516151bb9190615cf9565b6151c59190615bc9565b8861012001518961016001516151db9190615b59565b6151e59190615b59565b96508761018001516b033b2e3c9fd0803ce80000006152049190615db8565b828961014001516152159190615cf9565b61521f9190615bc9565b95508761018001516b033b2e3c9fd0803ce800000061523e9190615db8565b8189610140015161524f9190615cf9565b6152599190615bc9565b94505b505050509250925092565b60008282606001516152799190615b59565b6b033b2e3c9fd0803ce8000000848460400151856020015161529b9190615b59565b6152a59190615b59565b6152af9190615cf9565b612ac79190615bc9565b60008282606001516152cb9190615b59565b6b033b2e3c9fd0803ce80000008360400151846020015185606001516152f19190615db8565b6152a59190615db8565b805169ffffffffffffffffffff8116811461531557600080fd5b919050565b60006020828403121561532c57600080fd5b8135612ac781615f7e565b60006020828403121561534957600080fd5b8151612ac781615f7e565b6000806040838503121561536757600080fd5b823561537281615f7e565b9150602083013561538281615f7e565b809150509250929050565b6000806000606084860312156153a257600080fd5b83516153ad81615f7e565b60208501519093506153be81615f7e565b60408501519092506153cf81615f7e565b809150509250925092565b60008060008060008060a087890312156153f357600080fd5b86356153fe81615f7e565b9550602087013561540e81615f7e565b94506040870135935060608701359250608087013567ffffffffffffffff8082111561543957600080fd5b818901915089601f83011261544d57600080fd5b81358181111561545c57600080fd5b8a602082850101111561546e57600080fd5b6020830194508093505050509295509295509295565b600080600080600060a0868803121561549c57600080fd5b85356154a781615f7e565b94506020868101356154b881615f7e565b945060408701356154c881615f7e565b935060608701356154d881615f7e565b9250608087013567ffffffffffffffff808211156154f557600080fd5b818901915089601f83011261550957600080fd5b81358181111561551b5761551b615f4f565b8060051b915061552c848301615b28565b8181528481019084860184860187018e101561554757600080fd5b600095505b83861015615576578035945061556185615f7e565b8483526001959095019491860191860161554c565b508096505050505050509295509295909350565b60006020828403121561559c57600080fd5b8151612ac781615f96565b600080604083850312156155ba57600080fd5b82356155c581615f96565b946020939093013593505050565b6000602082840312156155e557600080fd5b5035919050565b6000602082840312156155fe57600080fd5b5051919050565b6000806040838503121561561857600080fd5b82359150602083013561538281615f7e565b60006080828403121561563c57600080fd5b6040516080810181811067ffffffffffffffff8211171561565f5761565f615f4f565b604052823561566d81615f96565b8152602083013561567d81615f96565b6020820152604083013561569081615f96565b604082015260608301356156a381615f96565b60608201529392505050565b6000606082840312156156c157600080fd5b6040516060810181811067ffffffffffffffff821117156156e4576156e4615f4f565b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000806040838503121561571e57600080fd5b8235915060208084013567ffffffffffffffff8082111561573e57600080fd5b818601915086601f83011261575257600080fd5b81358181111561576457615764615f4f565b61577684601f19601f84011601615b28565b9150808252878482850101111561578c57600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000606084860312156157bf57600080fd5b8351925060208401519150604084015190509250925092565b600080600080608085870312156157ee57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806000806000806000806101408b8d03121561582a57600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b015161585881615f96565b60c08c015190955061586981615f96565b60e08c015190945061587a81615f96565b6101008c015190935061588c81615f96565b6101208c015190925061589e81615f96565b809150509295989b9194979a5092959850565b6000806000806000806000806000806101408b8d0312156158d157600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015164ffffffffff8116811461589e57600080fd5b60008060006060848603121561593c57600080fd5b833592506020840135915060408401356153cf81615fa4565b600080600080600060a0868803121561596d57600080fd5b615976866152fb565b9450602086015193506040860151925060608601519150615999608087016152fb565b90509295509295909350565b6000602082840312156159b757600080fd5b8151612ac781615fa4565b600081518084526020808501945080840160005b838110156144f15781516001600160a01b0316875295820195908201906001016159d6565b60008251615a0d818460208701615e27565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615a4f816017850160208801615e27565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351615a8c816028840160208801615e27565b01602801949350505050565b604081526000615aab60408301856159c2565b90506001600160a01b03831660208301529392505050565b606081526000615ad660608301866159c2565b90508360208301526001600160a01b0383166040830152949350505050565b6020815260008251806020840152615b14816040850160208701615e27565b601f01601f19169190910160400192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b5157615b51615f4f565b604052919050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615b9357615b93615ec2565b82600160ff1b038412811615615bab57615bab615ec2565b50500190565b60008219821115615bc457615bc4615ec2565b500190565b600082615bd857615bd8615ef1565b6000198314600160ff1b83141615615bf257615bf2615ec2565b500590565b600082615c0657615c06615ef1565b500490565b600181815b80851115615c46578160001904821115615c2c57615c2c615ec2565b80851615615c3957918102915b93841c9390800290615c10565b509250929050565b6000612ac760ff841683600082615c67575060016112c2565b81615c74575060006112c2565b8160018114615c8a5760028114615c9457615cb0565b60019150506112c2565b60ff841115615ca557615ca5615ec2565b50506001821b6112c2565b5060208310610133831016604e8410600b8410161715615cd3575081810a6112c2565b615cdd8383615c0b565b8060001904821115615cf157615cf1615ec2565b029392505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615d3a57615d3a615ec2565b600160ff1b6000871286820588128184161615615d5957615d59615ec2565b60008712925087820587128484161615615d7557615d75615ec2565b87850587128184161615615d8b57615d8b615ec2565b505050929093029392505050565b6000816000190483118215151615615db357615db3615ec2565b500290565b600080831283600160ff1b01831281151615615dd657615dd6615ec2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615615e0a57615e0a615ec2565b50500390565b600082821015615e2257615e22615ec2565b500390565b60005b83811015615e42578181015183820152602001615e2a565b838111156116a55750506000910152565b600081615e6257615e62615ec2565b506000190190565b6000600019821415615e7e57615e7e615ec2565b5060010190565b600060ff821660ff811415615e9c57615e9c615ec2565b60010192915050565b6000600160ff1b821415615ebb57615ebb615ec2565b5060000390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6001600160a01b0381168114615f9357600080fd5b50565b8015158114615f9357600080fd5b60ff81168114615f9357600080fdfea26469706673582212203e12c5fad3dc4c7106028ae10a2d8d3d16954abde5a2cabf5a82e92475f77c7b64736f6c63430008070033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061036d5760003560e01c80634c3f425f116101d3578063abac6e1111610104578063d94fa4af116100a2578063ec342ad01161007c578063ec342ad01461072b578063efbb5cb01461073a578063f8453e7c14610742578063fcf2d0ad1461075557600080fd5b8063d94fa4af146106fc578063dc4c90d314610705578063ddc632621461071857600080fd5b8063b8221bc4116100de578063b8221bc4146106c4578063b8dc491b146106cd578063d0134cb7146106e0578063d547741f146106e957600080fd5b8063abac6e1114610693578063af306e16146106a6578063af648c3d146106b157600080fd5b80638e5b14b011610171578063a34a42231161014b578063a34a42231461065b578063a526d83b1461066e578063a62b75a814610681578063a8f9c0d81461068a57600080fd5b80638e5b14b01461063757806391d1485414610640578063a217fddf1461065357600080fd5b80635e4a1e01116101ad5780635e4a1e01146106135780636314e8841461061c578063659621b51461062557806386d8745b1461062e57600080fd5b80634c3f425f146105f65780635641ec03146105fe5780635a5cd45e1461060b57600080fd5b80632e1a7d4d116102ad578063372500ab1161024b578063418f35cc11610225578063418f35cc146105d45780634322b714146105dc5780634641257d146105e55780634c32e270146105ed57600080fd5b8063372500ab1461059a578063387f504a146105a2578063396794cd146105c157600080fd5b80633042087c116102875780633042087c146104fa578063364bc15a1461050d57806336568abe14610534578063368a9d6d1461054757600080fd5b80632e1a7d4d146104b65780632e4debb3146104de5780632f2ff15d146104e757600080fd5b80631f1fcd511161031a57806323cf978f116102f457806323cf978f1461044557806323e30c8b14610458578063248a9ca31461046b57806324ea54f41461048f57600080fd5b80631f1fcd51146103f9578063205409d31461042457806322f3e2d41461042d57600080fd5b80630c016dc01161034b5780630c016dc0146103b65780630f969b87146103dd5780631d12f28b146103f057600080fd5b806305b4193414610372578063060ca2ba146103875780630b6d1d171461039a575b600080fd5b61038561038036600461570b565b61075d565b005b6103856103953660046157d8565b610881565b6103a360355481565b6040519081526020015b60405180910390f35b6103a37f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56281565b6103856103eb3660046155d3565b61097f565b6103a360365481565b60345461040c906001600160a01b031681565b6040516001600160a01b0390911681526020016103ad565b6103a360435481565b6104356109e6565b60405190151581526020016103ad565b6103856104533660046155d3565b6109f7565b6103a36104663660046153da565b610a79565b6103a36104793660046155d3565b6000908152600160208190526040909120015490565b6103a37f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504181565b6104c96104c43660046155d3565b610bd1565b604080519283526020830191909152016103ad565b6103a3603e5481565b6103856104f5366004615605565b610c2a565b6103856105083660046155d3565b610c56565b6103a37ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab81565b610385610542366004615605565b610c94565b6047546105709060ff808216916101008104821691620100008204811691630100000090041684565b604080519415158552921515602085015290151591830191909152151560608201526080016103ad565b610385610cfa565b6046546105af9060ff1681565b60405160ff90911681526020016103ad565b6103856105cf3660046155d3565b610d2d565b6104c9610d61565b6103a3603a5481565b610385610d7c565b6103a360405481565b610385610d8e565b6037546104359060ff1681565b6103a3610d96565b6103a360455481565b6103a360395481565b6103a3603d5481565b6103a360445481565b6103a360415481565b61043561064e366004615605565b61129b565b6103a3600081565b61038561066936600461562a565b6112c8565b61038561067c36600461531a565b61138f565b6103a3603b5481565b6103a3603f5481565b6103856106a1366004615927565b6113e4565b6103a36301e1855881565b6103856106bf36600461531a565b61149d565b6103a360385481565b6103856106db366004615354565b6114f2565b6103a3603c5481565b6103856106f7366004615605565b6116ab565b6103a360425481565b60335461040c906001600160a01b031681565b6103856107263660046155d3565b6116d2565b6103a3670de0b6b3a764000081565b6103a361170e565b610385610750366004615484565b61180b565b610385611b91565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab6107888133611c04565b600080731111111254fb6c44bac0bed2854e76f90643097d6001600160a01b0316846040516107b791906159fb565b6000604051808303816000865af19150503d80600081146107f4576040519150601f19603f3d011682016040523d82523d6000602084013e6107f9565b606091505b50915091508161080c5761080c81611c68565b60008180602001905181019061082291906155ec565b9050858110156108795760405162461bcd60e51b815260206004820152600260248201527f313500000000000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b505050505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416108ac8133611c04565b60345460009081906108c6906001600160a01b0316611cbf565b9150915060006108e9736b175474e89094c44da98b954eedeac495271d0f611cbf565b50905081881080156108fa57508187105b801561090557508688105b801561091057508286105b801561091b57508085105b6109675760405162461bcd60e51b815260206004820152600160248201527f38000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b505050604094909455604192909255603f5560425550565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416109aa8133611c04565b60368290556040518281527fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a86009060200160405180910390a15050565b6000806109f161170e565b11905090565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610a228133611c04565b6127108210610a735760405162461bcd60e51b815260206004820152600160248201527f34000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b50604555565b600033731eb4cf3a948e7d72a198fe073ccb8c7a948cd853148015610aa657506001600160a01b03871630145b610af25760405162461bcd60e51b815260206004820152600160248201527f31000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b600080610b01848601866155a7565b6034546040517fbf04d6e8000000000000000000000000000000000000000000000000000000008152831515600482015260248101839052604481018b90526001600160a01b039091166064820152919350915073__$769b0789f1f3504b29e5e16055ef62b17c$__9063bf04d6e89060840160206040518083038186803b158015610b8c57600080fd5b505af4158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc491906155ec565b9998505050505050505050565b6000807f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562610bff8133611c04565b610c0884611da4565b6034549194509250610c24906001600160a01b03163385611dd4565b50915091565b60008281526001602081905260409091200154610c478133611c04565b610c518383611e7d565b505050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610c818133611c04565b610c8a82611ee8565b50610c5182611fb5565b6001600160a01b0381163314610cec5760405162461bcd60e51b815260206004820152600260248201527f37310000000000000000000000000000000000000000000000000000000000006044820152606401610870565b610cf68282612082565b5050565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab610d258133611c04565b610cf66120e9565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041610d588133611c04565b610c5182611ee8565b600080610d6c61235d565b9150610d766123df565b90509091565b610d84612410565b610d8c6125dc565b565b610d8c6125e7565b6034546040517f35ea6a750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009081908190819073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b158015610e1057600080fd5b505afa158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4891906158b1565b50505050509450945094505050600080610e60610d61565b915091506000806000610e7a670de0b6b3a76400006129fb565b90506000604860009054906101000a90046001600160a01b03166001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b158015610ecc57600080fd5b505afa158015610ee0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f049190615337565b6048546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015291169063f11b81889060240160606040518083038186803b158015610f6157600080fd5b505afa158015610f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9991906157aa565b505090506000604960009054906101000a90046001600160a01b03166001600160a01b03166375d264136040518163ffffffff1660e01b815260040160206040518083038186803b158015610fed57600080fd5b505afa158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190615337565b6049546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015291169063f11b81889060240160606040518083038186803b15801561108257600080fd5b505afa158015611096573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ba91906157aa565b50509050600082603c6110cd9190615d99565b6110d890603c615d99565b6110e3906018615d99565b6110ef9061016d615d99565b905060006110fe83603c615d99565b61110990603c615d99565b611114906018615d99565b6111209061016d615d99565b9050604860009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a891906155ec565b856111b3848c615d99565b6111bd9190615d99565b6111cb90633b9aca00615d99565b6111d59190615bf7565b96508b856111e3838b615d99565b6111ed9190615d99565b6111fb90633b9aca00615d99565b6112059190615bf7565b9550505050505060006112166123df565b61121e61235d565b611226612ace565b6112309190615bb1565b61123a9190615e10565b9050670de0b6b3a7640000816112508689615d99565b848661125c8a8d615d99565b6112669190615bb1565b6112709190615bb1565b61127a9190615e10565b6112849190615bf7565b61128e9190615bf7565b9850505050505050505090565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50416112f38133611c04565b508051604780546020840151604085015160609095015161ffff1990921693151561ff0019169390931761010093151593909302929092177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1662010000931515939093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff1692909217630100000091151591909102179055565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe5626113ba8133611c04565b610cf67f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183611e7d565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161140f8133611c04565b603f5483108015611423575060008260ff16115b8015611432575060108260ff16105b61147e5760405162461bcd60e51b815260206004820152600160248201527f38000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b506043929092556044556046805460ff191660ff909216919091179055565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe5626114c88133611c04565b610cf67f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504183612082565b7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504161151d8133611c04565b6034546001600160a01b038481169116141561157b5760405162461bcd60e51b815260206004820152600260248201527f39330000000000000000000000000000000000000000000000000000000000006044820152606401610870565b606060005b81518110156116165781818151811061159b5761159b615f20565b60200260200101516001600160a01b0316856001600160a01b031614156116045760405162461bcd60e51b815260206004820152600260248201527f39330000000000000000000000000000000000000000000000000000000000006044820152606401610870565b8061160e81615e6a565b915050611580565b506040516370a0823160e01b81523060048201526116a59084906001600160a01b038716906370a082319060240160206040518083038186803b15801561165c57600080fd5b505afa158015611670573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169491906155ec565b6001600160a01b0387169190611dd4565b50505050565b600082815260016020819052604090912001546116c88133611c04565b610c518383612082565b7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab6116fd8133611c04565b611705612410565b610cf682612aff565b600080600061171b610d61565b90925090506117dc73d784927ff2f95ba542bfc824c8a8a98f3495f6b5638b599f26611745612ce2565b306040518363ffffffff1660e01b8152600401611763929190615a98565b60206040518083038186803b15801561177b57600080fd5b505afa15801561178f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b391906155ec565b6117bb612d76565b6117c3612db0565b6117cd9190615bb1565b6117d79190615bb1565b6129fb565b81836117e6612ace565b6117f09190615bb1565b6117fa9190615e10565b6118049190615bb1565b9250505090565b61181785848484612dea565b60468054600660ff1990911617905560646043556611c37937e080006044556123286045556040805160808101825260018082526020820181905260009282019290925260600152604780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000166301000101179055603780547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101006001600160a01b038716021790556118cc6125e7565b6034546040517fd2493b6c0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152600090819073057835ad21a177dbdd3090bb1cae03eacf78fc6d9063d2493b6c9060240160606040518083038186803b15801561194157600080fd5b505afa158015611955573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611979919061538d565b604880546001600160a01b038086167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556049805483851692169190911790556034549395509093506000928392506119d89116611cbf565b90925090506119ee66470de4df82000082615e10565b604055611a026611c37937e0800082615e10565b604155611a166611c37937e0800083615e10565b603f556000611a38736b175474e89094c44da98b954eedeac495271d0f611cbf565b509050611a4c6611c37937e0800082615e10565b604255603454611a79906001600160a01b0316737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b611a9785737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b611ac9736b175474e89094c44da98b954eedeac495271d0f731eb4cf3a948e7d72a198fe073ccb8c7a948cd853613322565b611afb734da27a545c0c5b758a6ba100e3a049001de870f5731111111254fb6c44bac0bed2854e76f90643097d613322565b611b2d737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9731111111254fb6c44bac0bed2854e76f90643097d613322565b6034546001600160a01b0316736b175474e89094c44da98b954eedeac495271d0f14611b8557611b85736b175474e89094c44da98b954eedeac495271d0f737d2768de32b0b80b7a3454c06bdac94a69ddc7a9613322565b50505050505050505050565b7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562611bbc8133611c04565b6037805460ff191660011790556040517f17fa25a1c2ac074f71f0cf4f6af525c06fab7d83eff5ffcf6df5277f2919ae2490600090a150565b6001600160a01b03163b151590565b611c0e828261129b565b610cf657611c26816001600160a01b03166014613338565b611c31836020613338565b604051602001611c42929190615a17565b60408051601f198184030181529082905262461bcd60e51b825261087091600401615af5565b805115611c7757805181602001fd5b60405162461bcd60e51b815260206004820152600360248201527f31313700000000000000000000000000000000000000000000000000000000006044820152606401610870565b6040517f3e1501410000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152600090819073057835ad21a177dbdd3090bb1cae03eacf78fc6d90633e150141906024016101406040518083038186803b158015611d3157600080fd5b505afa158015611d45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d69919061580a565b50969950949750611d8b9650655af3107a40009550889450615d999350505050565b9150611d9d655af3107a400082615d99565b9050915091565b600080600080611db2610d61565b91509150611dc985611dc2612ace565b8484613561565b935093505050915091565b6040516001600160a01b038316602482015260448101829052610c519084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261363f565b611e87828261129b565b610cf65760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b600081611ef757506000919050565b6034546040517f69328dec0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260248101839052306044820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a9906369328dec90606401602060405180830381600087803b158015611f7657600080fd5b505af1158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae91906155ec565b5090919050565b600081611fc457506000919050565b6034546040517f573ade810000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024810183905260026044820152306064820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063573ade8190608401602060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c291906155ec565b61208c828261129b565b15610cf65760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006120f3612db0565b90506000811561210857612105613724565b90505b6000821180156121185750806001145b15612227576040517f9a99b4f00000000000000000000000000000000000000000000000000000000081523060048201526000196024820152734da27a545c0c5b758a6ba100e3a049001de870f590639a99b4f090604401600060405180830381600087803b15801561218a57600080fd5b505af115801561219e573d6000803e3d6000fd5b50506040517f1e9a695000000000000000000000000000000000000000000000000000000000815230600482015260248101859052734da27a545c0c5b758a6ba100e3a049001de870f59250631e9a69509150604401600060405180830381600087803b15801561220e57600080fd5b505af1158015612222573d6000803e3d6000fd5b505050505b73d784927ff2f95ba542bfc824c8a8a98f3495f6b5633111e7b3612249612ce2565b600019306040518463ffffffff1660e01b815260040161226b93929190615ac3565b602060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd91906155ec565b506122c6612db0565b6047549092506301000000900460ff1680156122e25750600082115b80156122ec575080155b1561235957734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b031663787a08a66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561234057600080fd5b505af1158015612354573d6000803e3d6000fd5b505050505b5090565b6048546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a08231906024015b60206040518083038186803b1580156123a257600080fd5b505afa1580156123b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123da91906155ec565b905090565b6049546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240161238a565b6000806000603360009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561246357600080fd5b505afa158015612477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249b91906155ec565b60375490915060009060ff16156124f85760006124b6613825565b9050828110156124d1576124ca8184615e10565b93506124e6565b828111156124e6576124e38382615e10565b94505b6124f08484615e10565b915050612509565b61250182613838565b919550935090505b6040805185815260208101859052908101829052606081018390527f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5099060800160405180910390a16033546040517fa1d9bafc0000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018390526001600160a01b039091169063a1d9bafc90606401600060405180830381600087803b1580156125be57600080fd5b505af11580156125d2573d6000803e3d6000fd5b5050505050505050565b610d8c600019612aff565b6034546040517f3e1501410000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009073057835ad21a177dbdd3090bb1cae03eacf78fc6d90633e150141906024016101406040518083038186803b15801561265b57600080fd5b505afa15801561266f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612693919061580a565b5050505050945050505050734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b03166372b49d636040518163ffffffff1660e01b815260040160206040518083038186803b1580156126eb57600080fd5b505afa1580156126ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272391906155ec565b603881905550734da27a545c0c5b758a6ba100e3a049001de870f56001600160a01b031663359c4a966040518163ffffffff1660e01b815260040160206040518083038186803b15801561277657600080fd5b505afa15801561278a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ae91906155ec565b6039556127c58169152d02c7e14af6800000615d99565b603a81905550603760019054906101000a90046001600160a01b03166001600160a01b0316637b832f586040518163ffffffff1660e01b815260040160206040518083038186803b15801561281957600080fd5b505afa15801561282d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285191906155ec565b603b81905550603760019054906101000a90046001600160a01b03166001600160a01b03166365614f816040518163ffffffff1660e01b815260040160206040518083038186803b1580156128a557600080fd5b505afa1580156128b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128dd91906155ec565b603c81905550603760019054906101000a90046001600160a01b03166001600160a01b031663b25895446040518163ffffffff1660e01b815260040160206040518083038186803b15801561293157600080fd5b505afa158015612945573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061296991906155ec565b603d81905550603760019054906101000a90046001600160a01b03166001600160a01b031663a15f30ac6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129bd57600080fd5b505afa1580156129d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f591906155ec565b603e5550565b60008073547a514d5e3769680ce22b2361c10ea13619e8a96001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015612a4b57600080fd5b505afa158015612a5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a839190615955565b5050509150506c0c9f2c9cd04674edea400000006045546035548584612aa99190615d99565b612ab39190615d99565b612abd9190615d99565b612ac79190615bf7565b9392505050565b6034546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240161238a565b603354604080517fbf3759b500000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612b5d57600080fd5b505afa158015612b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b9591906155ec565b90506000612ba1612ace565b90508181118015612bbc5750604354612bba8383615e10565b115b15612bdf57612bd3612bce8383615e10565b6139d7565b50612bdc612ace565b90505b600080612bea610d61565b915091506000198514612bfd5784612bff565b805b60475490955060009060ff1615612c3757612c3082612c1e8587615bb1565b612c289190615e10565b848489613a8b565b9050612c3c565b506040545b6000612c488484613ad3565b905084861115612c72576000612c5e8688615e10565b9050612c6b818686613aee565b5050612cd9565b81811015612c9c57604454612c878284615e10565b1115612c9757612c978484613b4b565b612cd9565b81811115612cd957604454612cb18383615e10565b1115612cd9576000612ccc612cc68587615e10565b84613bfd565b90506125d2818686613c1b565b50505050505050565b6040805160028082526060808301845292602083019080368337505060485482519293506001600160a01b031691839150600090612d2257612d22615f20565b6001600160a01b039283166020918202929092010152604954825191169082906001908110612d5357612d53615f20565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b6040516370a0823160e01b8152306004820152600090737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9906370a082319060240161238a565b6040516370a0823160e01b8152306004820152600090734da27a545c0c5b758a6ba100e3a049001de870f5906370a082319060240161238a565b600054610100900460ff16612e055760005460ff1615612e09565b303b155b612e7b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610870565b600054610100900460ff16158015612e9d576000805461ffff19166101011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155604080517ffc0c546a000000000000000000000000000000000000000000000000000000008152905163fc0c546a91600480820192602092909190829003018186803b158015612f2257600080fd5b505afa158015612f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5a9190615337565b603480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169182179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce56791600480820192602092909190829003018186803b158015612fe057600080fd5b505afa158015612ff4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301891906159a5565b61302390600a615c4e565b6035556001600160a01b0383161580159061304657506001600160a01b03841615155b80156130645750826001600160a01b0316846001600160a01b031614155b6130b05760405162461bcd60e51b815260206004820152600160248201527f30000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b6130da7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504184613d4f565b6131047f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a504185613d4f565b61312e7f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56286613d4f565b6131587f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe56280613d59565b6131a27f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a50417f5916f72c85af4ac6f7e34636ecc97619c4b2085da099a5d28f3e58436cfbe562613d59565b60005b825181101561327f5760006001600160a01b03168382815181106131cb576131cb615f20565b60200260200101516001600160a01b0316141561322a5760405162461bcd60e51b815260206004820152600160248201527f30000000000000000000000000000000000000000000000000000000000000006044820152606401610870565b61326d7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab84838151811061326057613260615f20565b6020026020010151613d4f565b8061327781615e6a565b9150506131a5565b506132ca7ffc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab7f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041613d59565b6132dd670de0b6b3a76400006064615d99565b6036556037805460ff19169055603354603454613309916001600160a01b039182169116600019613db0565b801561331b576000805461ff00191690555b5050505050565b610cf66001600160a01b03831682600019613ea3565b60606000613347836002615d99565b613352906002615bb1565b67ffffffffffffffff81111561336a5761336a615f4f565b6040519080825280601f01601f191660200182016040528015613394576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106133cb576133cb615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061342e5761342e615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061346a846002615d99565b613475906001615bb1565b90505b6001811115613512577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106134b6576134b6615f20565b1a60f81b8282815181106134cc576134cc615f20565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361350b81615e53565b9050613478565b508315612ac75760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610870565b6000808585111561357757508490506000613636565b60006135838688615e10565b9050613590818686613aee565b50613599612ace565b9550858711156135c75785925060006135b28489615e10565b905060435481116135c1578092505b506135cb565b8692505b60475462010000900460ff1615613634576135e68284615bb1565b87146136345760405162461bcd60e51b815260206004820152600260248201527f35340000000000000000000000000000000000000000000000000000000000006044820152606401610870565b505b94509492505050565b6000613694826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166140009092919063ffffffff16565b805190915015610c5157808060200190518101906136b2919061558a565b610c515760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610870565b6040517f091030c30000000000000000000000000000000000000000000000000000000081523060048201526000908190734da27a545c0c5b758a6ba100e3a049001de870f59063091030c39060240160206040518083038186803b15801561378c57600080fd5b505afa1580156137a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c491906155ec565b90506000603854826137d69190615bb1565b9050816137e65760009250505090565b804211801561380157506039546137fd9082615bb1565b4211155b1561380f5760019250505090565b804210156138205760029250505090565b505090565b6000613832600019611da4565b50919050565b6033546040517f39ebf8230000000000000000000000000000000000000000000000000000000081523060048201526000918291829182916001600160a01b03909116906339ebf8239060240160606040518083038186803b15801561389d57600080fd5b505afa1580156138b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d591906156af565b60200151905060006138e5612ace565b90506000806138f2610d61565b90925090506000816139048486615bb1565b61390e9190615e10565b905080851115613929576139228186615e10565b9650613936565b6139338582615e10565b97505b6000613942898b615bb1565b9050848111156139a95761395881868686613561565b50945080851061398857899650886139708883615e10565b1015613983576139808782615e10565b98505b6139ca565b8985101561399c57600098508496506139ca565b8996506139808786615e10565b899650886139b78883615e10565b10156139ca576139c78782615e10565b98505b5050505050509193909250565b6000816139e657506000919050565b6034546040517fe8eda9df0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911660048201526024810183905230604482015260006064820152737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063e8eda9df906084015b600060405180830381600087803b158015613a6d57600080fd5b505af1158015613a81573d6000803e3d6000fd5b5093949350505050565b600080613a9a86868686614017565b90506000613ab1613aab8389615bb1565b83613ad3565b60415490915080821115613ac3578091505b5060408190559695505050505050565b600082156112c25782612abd670de0b6b3a764000084615d99565b600083613afd57506000612ac7565b6000613b098385615e10565b90506000613b2c613b1a8784614455565b613b249084615e10565b604054613bfd565b9050613b39818686613c1b565b613b41612ace565b9695505050505050565b600081613b5b613b248286615e10565b613b659190615e10565b604754909150610100900460ff1615613bac57613b83818484614464565b613b8d9082615e10565b9050604354811115610c5157613ba2816144fc565b6116a59082615e10565b60005b60465460ff908116908216108015613bc8575060435482115b156116a557613bd8828585614464565b613be29083615e10565b60009450849350915080613bf581615e85565b915050613baf565b6000613c1182670de0b6b3a7640000615e10565b612abd8385615d99565b82811115613ce3576000613c2f8483615e10565b604754909150610100900460ff1615613c5957613c4c81836145fa565b613c569082615e10565b90505b60415460005b60465460ff908116908216108015613c78575060435483115b15613cd257613c89826000806146de565b50826000613c95612ace565b905080821115613ca3578091505b6000613cae83611fb5565b9050613cba8187615e10565b95505050508080613cca90615e85565b915050613c5f565b50613cdb610d61565b909450925050505b6040546000613cf383838661473e565b905083811115613d31576000613d098583615e10565b9050604354811115613d2b57613d29612bce82613d24612ace565b614455565b505b5061331b565b604354613d3e8286615e10565b111561331b576108798285856146de565b610cf68282611e7d565b60008281526001602081905260409091200154819060405184907fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff90600090a4600091825260016020819052604090922090910155565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015613e1557600080fd5b505afa158015613e29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e4d91906155ec565b613e579190615bb1565b6040516001600160a01b0385166024820152604481018290529091506116a59085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611e19565b801580613f4557506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613f0b57600080fd5b505afa158015613f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4391906155ec565b155b613fb75760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610870565b6040516001600160a01b038316602482015260448101829052610c519084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611e19565b606061400f8484600085614771565b949350505050565b6000806035546b033b2e3c9fd0803ce80000006140349190615bf7565b90506140a1604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6034546040517f35ea6a750000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260009081908190819073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b15801561411b57600080fd5b505afa15801561412f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061415391906158b1565b5050509650505050935093509350604051806101a00160405280603a54815260200187856141819190615d99565b8152602001876141918c86615e10565b61419b9190615d99565b8152602001878c8e866141ae898b615bb1565b6141b89190615bb1565b6141c29190615bb1565b6141cc9190615e10565b6141d69190615d99565b81526020018281526020016000815260200160008152602001878d6141fb9190615d99565b815260200161420a888b615d99565b8152602001603b548152602001603c548152602001603d548152602001603e548152509450505050506000614246670de0b6b3a76400006129fb565b6048546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015290915060009073d784927ff2f95ba542bfc824c8a8a98f3495f6b59063f11b81889060240160606040518083038186803b1580156142bc57600080fd5b505afa1580156142d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142f491906157aa565b50506049546040517ff11b81880000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015290915060009073d784927ff2f95ba542bfc824c8a8a98f3495f6b59063f11b81889060240160606040518083038186803b15801561436c57600080fd5b505afa158015614380573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143a491906157aa565b5050603554909150836143ba8462015180615d99565b6143c69061016d615d99565b6143d09190615d99565b6143de90633b9aca00615d99565b6143e89190615bf7565b60a0850152603554836143fe8362015180615d99565b61440a9061016d615d99565b6144149190615d99565b61442290633b9aca00615d99565b61442c9190615bf7565b60c0850152508391506144409050826148ae565b61444a9190615bf7565b979650505050505050565b6000818310611fae5781612ac7565b600082158015614472575081155b156144855761447f610d61565b90935091505b600061448f612ace565b905060006144a86144a08387615bb1565b603f546149b7565b90508381116144bc57600092505050612ac7565b6144c68482615e10565b9050858110156144d4578095505b6144dd826139d7565b506144e7866149cc565b506144f1866139d7565b509495945050505050565b6000806000614509610d61565b91509150600061451c82603f548561473e565b9050600083821115614535576145328483615e10565b90505b6034546042546040517fbf5061df00000000000000000000000000000000000000000000000000000000815260006004820152602481018990526001600160a01b03909216604483015260648201526084810182905273__$769b0789f1f3504b29e5e16055ef62b17c$__9063bf5061df9060a40160206040518083038186803b1580156145c257600080fd5b505af41580156145d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b4191906155ec565b6000604354831161460d575060006112c2565b81831115614619578192505b6034546042546040517fbf5061df00000000000000000000000000000000000000000000000000000000815260016004820152602481018690526001600160a01b03909216604483015260648201526000608482015273__$769b0789f1f3504b29e5e16055ef62b17c$__9063bf5061df9060a40160206040518083038186803b1580156146a657600080fd5b505af41580156146ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac791906155ec565b6000821580156146ec575081155b156146ff576146f9610d61565b90935091505b600061470c83868661473e565b9050808411156147365760006147228286615e10565b905061472d81611ee8565b92505050612ac7565b509392505050565b6000821561476a5782614759670de0b6b3a764000086615d99565b6147639190615bf7565b9050612ac7565b5080612ac7565b6060824710156147e95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610870565b6001600160a01b0385163b6148405760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610870565b600080866001600160a01b0316858760405161485c91906159fb565b60006040518083038185875af1925050503d8060008114614899576040519150601f19603f3d011682016040523d82523d6000602084013e61489e565b606091505b509150915061444a828286614a47565b6000806148be6000846001614a80565b5050905060006148dc6b033b2e3c9fd0803ce8000000856001614a80565b505090508181136148f1575060009392505050565b60008060008087610100015196505b600a8410801561493357508315806149335750826149266149218983615db8565b615052565b614931906014615cf9565b135b1561498d5761494487896000614a80565b89955090935091508190506149656b033b2e3c9fd0803ce800000084615cf9565b61496f9190615bc9565b6149799084615db8565b9650614986600185615bb1565b9350614900565b600061499b888a6001614a80565b505090508681136149ab57600097505b50505050505050919050565b6000670de0b6b3a7640000612abd8385615d99565b6034546040517fa415bcad0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602481018290526002604482015260006064820181905230608483015290737d2768de32b0b80b7a3454c06bdac94a69ddc7a99063a415bcad9060a401613a53565b60608315614a56575081612ac7565b825115614a665782518084602001fd5b8160405162461bcd60e51b81526004016108709190615af5565b600080600080600080614a93898961506a565b925092509250600088606001518a614aab9190615b59565b8951614ac3906b033b2e3c9fd0803ce8000000615db8565b60e08b0151614ad2908d615b59565b614adc9190615cf9565b614ae69190615bc9565b905060006b033b2e3c9fd0803ce8000000858b604001518d614b089190615b59565b614b129190615cf9565b8b608001518c60200151614b269190615cf9565b614b309190615b59565b614b3a9190615bc9565b90506b033b2e3c9fd0803ce8000000614b53868d615cf9565b614b5d9190615bc9565b60608b0151614b6c908d615b59565b60a08c015160e08d0151614b80908f615b59565b614b8a9190615cf9565b614b949190615bc9565b60408c0151614ba3908e615b59565b60c08d0151614bb2908f615cf9565b614bbc9190615bc9565b6b033b2e3c9fd0803ce8000000614bd38587615cf9565b614bdd9190615bc9565b614be79190615b59565b614bf19190615b59565b614bfb9190615db8565b9750886150445760008a606001518c614c149190615b59565b8b51614c2c906b033b2e3c9fd0803ce8000000615db8565b8c60e001518d60600151614c409190615db8565b614c4a9190615cf9565b614c549190615bc9565b90508a606001518c614c669190615b59565b614c7c6b033b2e3c9fd0803ce800000083615cf9565b614c869190615bc9565b905060006b033b2e3c9fd0803ce8000000868d604001518f614ca89190615b59565b614cb29190615cf9565b614cc86b033b2e3c9fd0803ce80000008a615cf9565b614cd29190615b59565b614cdc9190615bc9565b90506b033b2e3c9fd0803ce8000000614cf58583615cf9565b614cff8585615cf9565b614d099190615b59565b614d139190615bc9565b985060008c606001518e614d279190615b59565b614d3d6b033b2e3c9fd0803ce800000085615cf9565b614d4990600119615cf9565b614d539190615bc9565b9050614d5f8482615cf9565b82614d6b856002615cf9565b614d759190615cf9565b614d7f9190615b59565b9850506b033b2e3c9fd0803ce8000000858d604001518f614da09190615b59565b614daa9190615cf9565b6b033b2e3c9fd0803ce8000000614dc2896002615cf9565b614dcc9190615cf9565b614dd69190615b59565b614de09190615bc9565b90506b033b2e3c9fd0803ce8000000614df98583615cf9565b614e03908a615b59565b614e0d9190615bc9565b9750505060006b033b2e3c9fd0803ce8000000858d614e2c9190615cf9565b614e426b033b2e3c9fd0803ce800000089615cf9565b614e4c9190615b59565b614e569190615bc9565b905060008b604001518d614e6a9190615b59565b8c604001518d60c00151614e7e9190615cf9565b614e889190615bc9565b90508b604001518d614e9a9190615b59565b614eb06b033b2e3c9fd0803ce800000083615cf9565b614eba9190615bc9565b905060008c606001518e614ece9190615b59565b8d60e001518e60600151614ee29190615db8565b8e60a00151614ef19190615cf9565b614efb9190615bc9565b90508c606001518e614f0d9190615b59565b614f236b033b2e3c9fd0803ce800000083615cf9565b614f2d9190615bc9565b905082614f3a8284615b59565b614f449190615db8565b614f4e908b615b59565b99506b033b2e3c9fd0803ce8000000868f614f699190615cf9565b6b033b2e3c9fd0803ce8000000614f818a6002615cf9565b614f8b9190615cf9565b614f959190615b59565b614f9f9190615bc9565b92508c604001518e614fb19190615b59565b6b033b2e3c9fd0803ce8000000614fca84600119615cf9565b614fd49190615cf9565b614fde9190615bc9565b91508c606001518e614ff09190615b59565b6b033b2e3c9fd0803ce800000061500983600119615cf9565b6150139190615cf9565b61501d9190615bc9565b90508261502a8284615b59565b6150349190615db8565b61503e908a615b59565b98505050505b505050505093509350939050565b6000808212156123595761506582615ea5565b6112c2565b60008060008061507a8686615267565b9050600086866060015161508e9190615b59565b9050600061509c88886152b9565b9050816150b56b033b2e3c9fd0803ce800000083615cf9565b6150bf9190615bc9565b905060006150cf82600119615cf9565b9050826150e86b033b2e3c9fd0803ce800000083615cf9565b6150f29190615bc9565b905087610180015184121561517f57876101800151848961012001516151189190615cf9565b6151229190615bc9565b8861016001516151329190615b59565b96508761018001518289610120015161514b9190615cf9565b6151559190615bc9565b95508761018001518189610120015161516e9190615cf9565b6151789190615bc9565b945061525c565b61018088015161519b906b033b2e3c9fd0803ce8000000615db8565b6101808901516151ab9086615db8565b8961014001516151bb9190615cf9565b6151c59190615bc9565b8861012001518961016001516151db9190615b59565b6151e59190615b59565b96508761018001516b033b2e3c9fd0803ce80000006152049190615db8565b828961014001516152159190615cf9565b61521f9190615bc9565b95508761018001516b033b2e3c9fd0803ce800000061523e9190615db8565b8189610140015161524f9190615cf9565b6152599190615bc9565b94505b505050509250925092565b60008282606001516152799190615b59565b6b033b2e3c9fd0803ce8000000848460400151856020015161529b9190615b59565b6152a59190615b59565b6152af9190615cf9565b612ac79190615bc9565b60008282606001516152cb9190615b59565b6b033b2e3c9fd0803ce80000008360400151846020015185606001516152f19190615db8565b6152a59190615db8565b805169ffffffffffffffffffff8116811461531557600080fd5b919050565b60006020828403121561532c57600080fd5b8135612ac781615f7e565b60006020828403121561534957600080fd5b8151612ac781615f7e565b6000806040838503121561536757600080fd5b823561537281615f7e565b9150602083013561538281615f7e565b809150509250929050565b6000806000606084860312156153a257600080fd5b83516153ad81615f7e565b60208501519093506153be81615f7e565b60408501519092506153cf81615f7e565b809150509250925092565b60008060008060008060a087890312156153f357600080fd5b86356153fe81615f7e565b9550602087013561540e81615f7e565b94506040870135935060608701359250608087013567ffffffffffffffff8082111561543957600080fd5b818901915089601f83011261544d57600080fd5b81358181111561545c57600080fd5b8a602082850101111561546e57600080fd5b6020830194508093505050509295509295509295565b600080600080600060a0868803121561549c57600080fd5b85356154a781615f7e565b94506020868101356154b881615f7e565b945060408701356154c881615f7e565b935060608701356154d881615f7e565b9250608087013567ffffffffffffffff808211156154f557600080fd5b818901915089601f83011261550957600080fd5b81358181111561551b5761551b615f4f565b8060051b915061552c848301615b28565b8181528481019084860184860187018e101561554757600080fd5b600095505b83861015615576578035945061556185615f7e565b8483526001959095019491860191860161554c565b508096505050505050509295509295909350565b60006020828403121561559c57600080fd5b8151612ac781615f96565b600080604083850312156155ba57600080fd5b82356155c581615f96565b946020939093013593505050565b6000602082840312156155e557600080fd5b5035919050565b6000602082840312156155fe57600080fd5b5051919050565b6000806040838503121561561857600080fd5b82359150602083013561538281615f7e565b60006080828403121561563c57600080fd5b6040516080810181811067ffffffffffffffff8211171561565f5761565f615f4f565b604052823561566d81615f96565b8152602083013561567d81615f96565b6020820152604083013561569081615f96565b604082015260608301356156a381615f96565b60608201529392505050565b6000606082840312156156c157600080fd5b6040516060810181811067ffffffffffffffff821117156156e4576156e4615f4f565b80604052508251815260208301516020820152604083015160408201528091505092915050565b6000806040838503121561571e57600080fd5b8235915060208084013567ffffffffffffffff8082111561573e57600080fd5b818601915086601f83011261575257600080fd5b81358181111561576457615764615f4f565b61577684601f19601f84011601615b28565b9150808252878482850101111561578c57600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000606084860312156157bf57600080fd5b8351925060208401519150604084015190509250925092565b600080600080608085870312156157ee57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806000806000806000806101408b8d03121561582a57600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b015161585881615f96565b60c08c015190955061586981615f96565b60e08c015190945061587a81615f96565b6101008c015190935061588c81615f96565b6101208c015190925061589e81615f96565b809150509295989b9194979a5092959850565b6000806000806000806000806000806101408b8d0312156158d157600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015164ffffffffff8116811461589e57600080fd5b60008060006060848603121561593c57600080fd5b833592506020840135915060408401356153cf81615fa4565b600080600080600060a0868803121561596d57600080fd5b615976866152fb565b9450602086015193506040860151925060608601519150615999608087016152fb565b90509295509295909350565b6000602082840312156159b757600080fd5b8151612ac781615fa4565b600081518084526020808501945080840160005b838110156144f15781516001600160a01b0316875295820195908201906001016159d6565b60008251615a0d818460208701615e27565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351615a4f816017850160208801615e27565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351615a8c816028840160208801615e27565b01602801949350505050565b604081526000615aab60408301856159c2565b90506001600160a01b03831660208301529392505050565b606081526000615ad660608301866159c2565b90508360208301526001600160a01b0383166040830152949350505050565b6020815260008251806020840152615b14816040850160208701615e27565b601f01601f19169190910160400192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b5157615b51615f4f565b604052919050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615b9357615b93615ec2565b82600160ff1b038412811615615bab57615bab615ec2565b50500190565b60008219821115615bc457615bc4615ec2565b500190565b600082615bd857615bd8615ef1565b6000198314600160ff1b83141615615bf257615bf2615ec2565b500590565b600082615c0657615c06615ef1565b500490565b600181815b80851115615c46578160001904821115615c2c57615c2c615ec2565b80851615615c3957918102915b93841c9390800290615c10565b509250929050565b6000612ac760ff841683600082615c67575060016112c2565b81615c74575060006112c2565b8160018114615c8a5760028114615c9457615cb0565b60019150506112c2565b60ff841115615ca557615ca5615ec2565b50506001821b6112c2565b5060208310610133831016604e8410600b8410161715615cd3575081810a6112c2565b615cdd8383615c0b565b8060001904821115615cf157615cf1615ec2565b029392505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615d3a57615d3a615ec2565b600160ff1b6000871286820588128184161615615d5957615d59615ec2565b60008712925087820587128484161615615d7557615d75615ec2565b87850587128184161615615d8b57615d8b615ec2565b505050929093029392505050565b6000816000190483118215151615615db357615db3615ec2565b500290565b600080831283600160ff1b01831281151615615dd657615dd6615ec2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615615e0a57615e0a615ec2565b50500390565b600082821015615e2257615e22615ec2565b500390565b60005b83811015615e42578181015183820152602001615e2a565b838111156116a55750506000910152565b600081615e6257615e62615ec2565b506000190190565b6000600019821415615e7e57615e7e615ec2565b5060010190565b600060ff821660ff811415615e9c57615e9c615ec2565b60010192915050565b6000600160ff1b821415615ebb57615ebb615ec2565b5060000390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6001600160a01b0381168114615f9357600080fd5b50565b8015158114615f9357600080fd5b60ff81168114615f9357600080fdfea26469706673582212203e12c5fad3dc4c7106028ae10a2d8d3d16954abde5a2cabf5a82e92475f77c7b64736f6c63430008070033", + "libraries": { + "FlashMintLib": "0x169487a55de79476125a56b07c36ca8dbf37a373" + }, + "devdoc": { + "author": "Yearn Finance (https://etherscan.io/address/0xd4E94061183b2DBF24473F28A3559cf4dE4459Db#code) but heavily reviewed and modified by Angle Core Team", + "details": "Angle strategies computes the optimal collateral ratio based on AAVE rewards for deposits and borrows", + "kind": "dev", + "methods": { + "addGuardian(address)": { + "params": { + "_guardian": "New guardian address" + } + }, + "estimatedTotalAssets()": { + "details": "It sums the effective deposit amount to the rewards accumulated" + }, + "getCurrentPosition()": { + "details": "The actual amount brought is `deposits - borrows`" + }, + "getRoleAdmin(bytes32)": { + "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}." + }, + "grantRole(bytes32,address)": { + "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role." + }, + "harvest(uint256)": { + "params": { + "borrowInit": "Approximate optimal borrows to have faster convergence on the NR method" + } + }, + "hasRole(bytes32,address)": { + "details": "Returns `true` if `account` has been granted `role`." + }, + "initialize(address,address,address,address,address[])": { + "params": { + "_poolManager": "Address of the `PoolManager` lending to this strategy", + "governor": "Governor address of the protocol", + "guardian": "Address of the guardian", + "interestRateStrategyAddress_": "Address of the `InterestRateStrategy` defining borrow rates for the collateral", + "keepers": "List of the addresses with keeper privilege" + } + }, + "isActive()": { + "returns": { + "_0": "True if the strategy is actively managing a position." + } + }, + "manualDeleverage(uint256)": { + "params": { + "amount": "Amount of `want` to withdraw/repay" + } + }, + "manualReleaseWant(uint256)": { + "params": { + "amount": "Amount of `want` to withdraw" + } + }, + "onFlashLoan(address,address,uint256,uint256,bytes)": { + "details": "If everything went smoothly, will return `keccak256(\"ERC3156FlashBorrower.onFlashLoan\")`" + }, + "renounceRole(bytes32,address)": { + "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`." + }, + "revokeGuardian(address)": { + "params": { + "guardian": "Old guardian address to revoke" + } + }, + "revokeRole(bytes32,address)": { + "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role." + }, + "sellRewards(uint256,bytes)": { + "params": { + "minAmountOut": "Minimum amount of `want` to receive for the swap to happen", + "payload": "Bytes needed for 1Inch API. Tokens swapped should be: stkAave -> `want` or Aave -> `want`" + } + }, + "setAavePoolVariables()": { + "details": "No access control needed because they fetch the values from Aave directly. If it changes there, it will need to be updated here tooWe expect the values concerned not to be often modified" + }, + "setDebtThreshold(uint256)": { + "details": "By default this is 0, meaning any losses would cause a harvest which will subsequently report the loss to the Manager for tracking.", + "params": { + "_debtThreshold": "How big of a loss this Strategy may carry without" + } + }, + "setEmergencyExit()": { + "details": "This may only be called by the `PoolManager`, because when calling this the `PoolManager` should at the same time update the debt ratioThis function can only be called once by the `PoolManager` contractSee `poolManager.setEmergencyExit()` and `harvest()` for further details." + }, + "sweep(address,address)": { + "details": "Implement `_protectedTokens()` to specify any additional tokens that should be protected from sweeping in addition to `want`.", + "params": { + "_token": "The token to transfer out of this `PoolManager`.", + "to": "Address to send the tokens to." + } + }, + "withdraw(uint256)": { + "details": "This may only be called by the `PoolManager`", + "params": { + "_amountNeeded": "How much `want` to withdraw." + }, + "returns": { + "_loss": "Any realized losses", + "amountFreed": "How much `want` withdrawn." + } + } + }, + "title": "AaveFlashloanStrategy", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "GUARDIAN_ROLE()": { + "notice": "Role for guardians and governors" + }, + "KEEPER_ROLE()": { + "notice": "Role for keepers" + }, + "POOLMANAGER_ROLE()": { + "notice": "Role for `PoolManager` only" + }, + "addGuardian(address)": { + "notice": "Adds a new guardian address" + }, + "boolParams()": { + "notice": "Struct with some boolean parameters of the contract These parameters are packed in a struct for efficiency of SLOAD operations" + }, + "daiBorrowCollatRatio()": { + "notice": "Parameter used for flash mints" + }, + "debtThreshold()": { + "notice": "Use this to adjust the threshold at which running a debt causes a harvest trigger. See `setDebtThreshold()` for more details" + }, + "discountFactor()": { + "notice": "Discount factor applied to the StkAAVE price" + }, + "emergencyExit()": { + "notice": "See note on `setEmergencyExit()`" + }, + "estimatedTotalAssets()": { + "notice": "Estimates the total assets controlled by the strategy" + }, + "getCurrentPosition()": { + "notice": "Get the current position of the strategy: that is to say the amount deposited and the amount borrowed on Aave" + }, + "harvest()": { + "notice": "Harvests the Strategy, recognizing any profits or losses and adjusting the Strategy's position." + }, + "harvest(uint256)": { + "notice": "Harvests the Strategy, recognizing any profits or losses and adjusting the Strategy's position." + }, + "initialize(address,address,address,address,address[])": { + "notice": "Constructor of the `Strategy`" + }, + "isActive()": { + "notice": "Provides an indication of whether this strategy is currently \"active\" in that it is managing an active position, or will manage a position in the future. This should correlate to `harvest()` activity, so that Harvest events can be tracked externally by indexing agents." + }, + "manualDeleverage(uint256)": { + "notice": "Emergency function that we can use to deleverage manually if something is broken" + }, + "manualReleaseWant(uint256)": { + "notice": "Emergency function that we can use to deleverage manually if something is broken" + }, + "maxBorrowCollatRatio()": { + "notice": "Maximum the Aave protocol will let us borrow" + }, + "maxCollatRatio()": { + "notice": "Closest to liquidation we'll risk" + }, + "maxIterations()": { + "notice": "Max number of iterations possible for the computation of the optimal lever" + }, + "minRatio()": { + "notice": "Minimum gap between the collat ratio and the target collat ratio before rectifying it" + }, + "minWant()": { + "notice": "Minimum amount to be moved before a deposit or a borrow" + }, + "onFlashLoan(address,address,uint256,uint256,bytes)": { + "notice": "Flashload callback, as defined by EIP-3156We check that the call is coming from the DAI lender and then execute the load logic" + }, + "poolManager()": { + "notice": "Reference to the protocol's collateral `PoolManager`" + }, + "revokeGuardian(address)": { + "notice": "Revokes the guardian role" + }, + "sellRewards(uint256,bytes)": { + "notice": "Swap earned stkAave or Aave for `want` through 1Inch" + }, + "setAavePoolVariables()": { + "notice": "Retrieves lending pool variables for `want`. Those variables are mostly used in the function to compute the optimal borrow amount" + }, + "setBoolParams((bool,bool,bool,bool))": { + "notice": "Sets all boolean parameters related to cooldown, withdraw check, flash loan and so on" + }, + "setCollateralTargets(uint256,uint256,uint256,uint256)": { + "notice": "Sets collateral targets and value for collateral ratio" + }, + "setDebtThreshold(uint256)": { + "notice": "Sets how far the Strategy can go into loss without a harvest and report being required." + }, + "setDiscountFactor(uint256)": { + "notice": "Sets the discount factor for the StkAAVE price" + }, + "setEmergencyExit()": { + "notice": "Activates emergency exit. Once activated, the Strategy will exit its position upon the next harvest, depositing all funds into the Manager as quickly as is reasonable given on-chain conditions." + }, + "setMinsAndMaxs(uint256,uint256,uint8)": { + "notice": "Sets `minWant`, `minRatio` and `maxItrations` values" + }, + "sweep(address,address)": { + "notice": "Removes tokens from this Strategy that are not the type of tokens managed by this Strategy. This may be used in case of accidentally sending the wrong kind of token to this Strategy. Tokens will be sent to `governance()`. This will fail if an attempt is made to sweep `want`, or any tokens that are protected by this Strategy. This may only be called by governance." + }, + "targetCollatRatio()": { + "notice": "LTV the strategy is going to lever up to" + }, + "want()": { + "notice": "Reference to the ERC20 farmed by this strategy" + }, + "wantBase()": { + "notice": "Base of the ERC20 token farmed by this strategy" + }, + "withdraw(uint256)": { + "notice": "Withdraws `_amountNeeded` to `poolManager`." + } + }, + "notice": "This strategy is used to optimize lending yield on Aave by taking some form or recursivity that is to say by borrowing to maximize Aave rewards", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 52, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 55, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 3409, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_roles", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_struct(RoleData)3404_storage)" + }, + { + "astId": 3695, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 12950, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "poolManager", + "offset": 0, + "slot": "51", + "type": "t_contract(IPoolManager)3973" + }, + { + "astId": 12954, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "want", + "offset": 0, + "slot": "52", + "type": "t_contract(IERC20)2114" + }, + { + "astId": 12957, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "wantBase", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 12960, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "debtThreshold", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 12963, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "emergencyExit", + "offset": 0, + "slot": "55", + "type": "t_bool" + }, + { + "astId": 7375, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_interestRateStrategyAddress", + "offset": 1, + "slot": "55", + "type": "t_contract(IReserveInterestRateStrategy)11137" + }, + { + "astId": 7377, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "cooldownSeconds", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 7379, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "unstakeWindow", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 7381, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "reserveFactor", + "offset": 0, + "slot": "58", + "type": "t_int256" + }, + { + "astId": 7383, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "slope1", + "offset": 0, + "slot": "59", + "type": "t_int256" + }, + { + "astId": 7385, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "slope2", + "offset": 0, + "slot": "60", + "type": "t_int256" + }, + { + "astId": 7387, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "r0", + "offset": 0, + "slot": "61", + "type": "t_int256" + }, + { + "astId": 7389, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "uOptimal", + "offset": 0, + "slot": "62", + "type": "t_int256" + }, + { + "astId": 7392, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "maxBorrowCollatRatio", + "offset": 0, + "slot": "63", + "type": "t_uint256" + }, + { + "astId": 7395, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "targetCollatRatio", + "offset": 0, + "slot": "64", + "type": "t_uint256" + }, + { + "astId": 7398, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "maxCollatRatio", + "offset": 0, + "slot": "65", + "type": "t_uint256" + }, + { + "astId": 7401, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "daiBorrowCollatRatio", + "offset": 0, + "slot": "66", + "type": "t_uint256" + }, + { + "astId": 7404, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "minWant", + "offset": 0, + "slot": "67", + "type": "t_uint256" + }, + { + "astId": 7407, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "minRatio", + "offset": 0, + "slot": "68", + "type": "t_uint256" + }, + { + "astId": 7410, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "discountFactor", + "offset": 0, + "slot": "69", + "type": "t_uint256" + }, + { + "astId": 7413, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "maxIterations", + "offset": 0, + "slot": "70", + "type": "t_uint8" + }, + { + "astId": 7426, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "boolParams", + "offset": 0, + "slot": "71", + "type": "t_struct(BoolParams)7422_storage" + }, + { + "astId": 7429, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_aToken", + "offset": 0, + "slot": "72", + "type": "t_contract(IAToken)11054" + }, + { + "astId": 7432, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "_debtToken", + "offset": 0, + "slot": "73", + "type": "t_contract(IVariableDebtToken)10665" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IAToken)11054": { + "encoding": "inplace", + "label": "contract IAToken", + "numberOfBytes": "20" + }, + "t_contract(IERC20)2114": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IPoolManager)3973": { + "encoding": "inplace", + "label": "contract IPoolManager", + "numberOfBytes": "20" + }, + "t_contract(IReserveInterestRateStrategy)11137": { + "encoding": "inplace", + "label": "contract IReserveInterestRateStrategy", + "numberOfBytes": "20" + }, + "t_contract(IVariableDebtToken)10665": { + "encoding": "inplace", + "label": "contract IVariableDebtToken", + "numberOfBytes": "20" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_struct(RoleData)3404_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32", + "value": "t_struct(RoleData)3404_storage" + }, + "t_struct(BoolParams)7422_storage": { + "encoding": "inplace", + "label": "struct AaveFlashloanStrategy.BoolParams", + "members": [ + { + "astId": 7415, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "automaticallyComputeCollatRatio", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 7417, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "isFlashMintActive", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 7419, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "withdrawCheck", + "offset": 2, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 7421, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "cooldownStkAave", + "offset": 3, + "slot": "0", + "type": "t_bool" + } + ], + "numberOfBytes": "32" + }, + "t_struct(RoleData)3404_storage": { + "encoding": "inplace", + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "astId": 3401, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "members", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 3403, + "contract": "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol:AaveFlashloanStrategy", + "label": "adminRole", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/FlashMintLib.json b/deployments/mainnet/FlashMintLib.json new file mode 100644 index 0000000..76c3045 --- /dev/null +++ b/deployments/mainnet/FlashMintLib.json @@ -0,0 +1,47 @@ +{ + "address": "0x169487a55dE79476125A56B07C36cA8dbF37a373", + "abi": [ + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "amountRequested", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountUsed", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "requiredDAI", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountToCloseLTVGap", "type": "uint256" }, + { "indexed": false, "internalType": "bool", "name": "deficit", "type": "bool" }, + { "indexed": false, "internalType": "address", "name": "flashLoan", "type": "address" } + ], + "name": "Leverage", + "type": "event" + }, + { + "inputs": [], + "name": "ADAI", + "outputs": [{ "internalType": "contract IAToken", "name": "", "type": "IAToken" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CALLBACK_SUCCESS", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LENDER", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLiquidity", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe46165728b4cba73047f3b387642b6c7283bfdf2da684034e6322472ccca3d4e" +} diff --git a/deployments/mainnet/solcInputs/cca16ad1f0f505ca7a8330fb58e463cc.json b/deployments/mainnet/solcInputs/cca16ad1f0f505ca7a8330fb58e463cc.json new file mode 100644 index 0000000..834fd72 --- /dev/null +++ b/deployments/mainnet/solcInputs/cca16ad1f0f505ca7a8330fb58e463cc.json @@ -0,0 +1,169 @@ +{ + "language": "Solidity", + "sources": { + "contracts/external/AccessControl.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/utils/Context.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\n\nimport \"../interfaces/IAccessControl.sol\";\n\n/**\n * @dev This contract is fully forked from OpenZeppelin `AccessControl`.\n * The only difference is the removal of the ERC165 implementation as it's not\n * needed in Angle.\n *\n * Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external override {\n require(account == _msgSender(), \"71\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal {\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) internal {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n function _revokeRole(bytes32 role, address account) internal {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "contracts/interfaces/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\n/// @title IAccessControl\n/// @author Forked from OpenZeppelin\n/// @notice Interface for `AccessControl` contracts\ninterface IAccessControl {\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n function grantRole(bytes32 role, address account) external;\n\n function revokeRole(bytes32 role, address account) external;\n\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "contracts/strategies/BaseStrategyEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"../external/AccessControl.sol\";\nimport \"../external/AccessControlUpgradeable.sol\";\n\nimport \"../interfaces/IStrategy.sol\";\nimport \"../interfaces/IPoolManager.sol\";\n\n/// @title BaseStrategyEvents\n/// @author Angle Core Team\n/// @notice Events used in the abstract `BaseStrategy` contract\ncontract BaseStrategyEvents {\n // So indexers can keep track of this\n event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);\n\n event UpdatedMinReportDelayed(uint256 delay);\n\n event UpdatedMaxReportDelayed(uint256 delay);\n\n event UpdatedDebtThreshold(uint256 debtThreshold);\n\n event UpdatedRewards(address rewards);\n\n event UpdatedIsRewardActivated(bool activated);\n\n event UpdatedRewardAmountAndMinimumAmountMoved(uint256 _rewardAmount, uint256 _minimumAmountMoved);\n\n event EmergencyExitActivated();\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "contracts/external/AccessControlUpgradeable.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"../interfaces/IAccessControl.sol\";\n\n/**\n * @dev This contract is fully forked from OpenZeppelin `AccessControlUpgradeable`.\n * The only difference is the removal of the ERC165 implementation as it's not\n * needed in Angle.\n *\n * Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, IAccessControl {\n function __AccessControl_init() internal initializer {\n __AccessControl_init_unchained();\n }\n\n function __AccessControl_init_unchained() internal initializer {}\n\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, msg.sender);\n _;\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n StringsUpgradeable.toHexString(uint160(account), 20),\n \" is missing role \",\n StringsUpgradeable.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external override {\n require(account == msg.sender, \"71\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n */\n function _setupRole(bytes32 role, address account) internal {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal {\n emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);\n _roles[role].adminRole = adminRole;\n }\n\n function _grantRole(bytes32 role, address account) internal {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, msg.sender);\n }\n }\n\n function _revokeRole(bytes32 role, address account) internal {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, msg.sender);\n }\n }\n\n uint256[49] private __gap;\n}\n" + }, + "contracts/interfaces/IStrategy.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"./IAccessControl.sol\";\n\n/// @title IStrategy\n/// @author Inspired by Yearn with slight changes from Angle Core Team\n/// @notice Interface for yield farming strategies\ninterface IStrategy is IAccessControl {\n function estimatedAPR() external view returns (uint256);\n\n function poolManager() external view returns (address);\n\n function want() external view returns (address);\n\n function isActive() external view returns (bool);\n\n function estimatedTotalAssets() external view returns (uint256);\n\n function harvestTrigger(uint256 callCost) external view returns (bool);\n\n function harvest() external;\n\n function withdraw(uint256 _amountNeeded) external returns (uint256 amountFreed, uint256 _loss);\n\n function setEmergencyExit() external;\n\n function addGuardian(address _guardian) external;\n\n function revokeGuardian(address _guardian) external;\n}\n" + }, + "contracts/interfaces/IPoolManager.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\n// Struct for the parameters associated to a strategy interacting with a collateral `PoolManager`\n// contract\nstruct StrategyParams {\n // Timestamp of last report made by this strategy\n // It is also used to check if a strategy has been initialized\n uint256 lastReport;\n // Total amount the strategy is expected to have\n uint256 totalStrategyDebt;\n // The share of the total assets in the `PoolManager` contract that the `strategy` can access to.\n uint256 debtRatio;\n}\n\n/// @title IPoolManagerFunctions\n/// @author Angle Core Team\n/// @notice Interface for the collateral poolManager contracts handling each one type of collateral for\n/// a given stablecoin\n/// @dev Only the functions used in other contracts of the protocol are left here\ninterface IPoolManagerFunctions {\n // ============================ Yield Farming ==================================\n\n function creditAvailable() external view returns (uint256);\n\n function debtOutstanding() external view returns (uint256);\n\n function report(\n uint256 _gain,\n uint256 _loss,\n uint256 _debtPayment\n ) external;\n\n // ============================= Getters =======================================\n\n function getBalance() external view returns (uint256);\n\n function getTotalAsset() external view returns (uint256);\n}\n\n/// @title IPoolManager\n/// @author Angle Core Team\n/// @notice Previous interface with additionnal getters for public variables and mappings\n/// @dev Used in other contracts of the protocol\ninterface IPoolManager is IPoolManagerFunctions {\n function stableMaster() external view returns (address);\n\n function perpetualManager() external view returns (address);\n\n function token() external view returns (address);\n\n function totalDebt() external view returns (uint256);\n\n function strategies(address _strategy) external view returns (StrategyParams memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() initializer {}\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\n // contract may have been reentered.\n require(_initializing ? _isConstructor() : !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} modifier, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/mock/MockStrategy.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"../interfaces/IPoolManager.sol\";\n\ncontract MockStrategy {\n address public poolManager;\n\n address public want;\n\n constructor(address _poolManager, address _want) {\n poolManager = _poolManager;\n want = _want;\n }\n\n function report(\n uint256 gain,\n uint256 loss,\n uint256 debtPayment\n ) external {\n IPoolManager(poolManager).report(gain, loss, debtPayment);\n }\n\n function withdraw(uint256 amount) external pure returns (uint256, uint256) {\n return (amount, 1);\n }\n\n function creditAvailable() external view returns (uint256 credit) {\n credit = IPoolManager(poolManager).creditAvailable();\n }\n}\n" + }, + "contracts/mock/MockPoolManager2.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\nimport \"../external/AccessControlUpgradeable.sol\";\n\nimport \"../interfaces/IPoolManager.sol\";\nimport \"../interfaces/IStrategy.sol\";\n\nimport \"../utils/FunctionUtils.sol\";\n\nstruct SLPData {\n // Last timestamp at which the `sanRate` has been updated for SLPs\n uint256 lastBlockUpdated;\n // Fees accumulated from previous blocks and to be distributed to SLPs\n uint256 lockedInterests;\n // Max interests used to update the `sanRate` in a single block\n // Should be in collateral token base\n uint256 maxInterestsDistributed;\n // Amount of fees left aside for SLPs and that will be distributed\n // when the protocol is collateralized back again\n uint256 feesAside;\n // Part of the fees normally going to SLPs that is left aside\n // before the protocol is collateralized back again (depends on collateral ratio)\n // Updated by keepers and scaled by `BASE_PARAMS`\n uint64 slippageFee;\n // Portion of the fees from users minting and burning\n // that goes to SLPs (the rest goes to surplus)\n uint64 feesForSLPs;\n // Slippage factor that's applied to SLPs exiting (depends on collateral ratio)\n // If `slippage = BASE_PARAMS`, SLPs can get nothing, if `slippage = 0` they get their full claim\n // Updated by keepers and scaled by `BASE_PARAMS`\n uint64 slippage;\n // Portion of the interests from lending\n // that goes to SLPs (the rest goes to surplus)\n uint64 interestsForSLPs;\n}\n\nstruct MintBurnData {\n // Values of the thresholds to compute the minting fees\n // depending on HA hedge (scaled by `BASE_PARAMS`)\n uint64[] xFeeMint;\n // Values of the fees at thresholds (scaled by `BASE_PARAMS`)\n uint64[] yFeeMint;\n // Values of the thresholds to compute the burning fees\n // depending on HA hedge (scaled by `BASE_PARAMS`)\n uint64[] xFeeBurn;\n // Values of the fees at thresholds (scaled by `BASE_PARAMS`)\n uint64[] yFeeBurn;\n // Max proportion of collateral from users that can be covered by HAs\n // It is exactly the same as the parameter of the same name in `PerpetualManager`, whenever one is updated\n // the other changes accordingly\n uint64 targetHAHedge;\n // Minting fees correction set by the `FeeManager` contract: they are going to be multiplied\n // to the value of the fees computed using the hedge curve\n // Scaled by `BASE_PARAMS`\n uint64 bonusMalusMint;\n // Burning fees correction set by the `FeeManager` contract: they are going to be multiplied\n // to the value of the fees computed using the hedge curve\n // Scaled by `BASE_PARAMS`\n uint64 bonusMalusBurn;\n // Parameter used to limit the number of stablecoins that can be issued using the concerned collateral\n uint256 capOnStableMinted;\n}\n\ninterface IOracle {\n function read() external view returns (uint256);\n\n function readAll() external view returns (uint256 lowerRate, uint256 upperRate);\n\n function readLower() external view returns (uint256);\n\n function readUpper() external view returns (uint256);\n\n function readQuote(uint256 baseAmount) external view returns (uint256);\n\n function readQuoteLower(uint256 baseAmount) external view returns (uint256);\n\n function inBase() external view returns (uint256);\n}\n\ninterface ISanToken is IERC20 {\n function mint(address account, uint256 amount) external;\n function burnFrom(\n uint256 amount,\n address burner,\n address sender\n ) external;\n function burnSelf(uint256 amount, address burner) external;\n function stableMaster() external view returns (address);\n function poolManager() external view returns (address);\n}\n\ninterface IStableMaster {\n function agToken() external view returns (address);\n function signalLoss(uint256 loss) external;\n function accumulateInterest(uint256 gain) external;\n function collateralMap(IPoolManager poolManager)\n external\n view\n returns (\n IERC20 token,\n ISanToken sanToken,\n address perpetualManager,\n IOracle oracle,\n uint256 stocksUsers,\n uint256 sanRate,\n uint256 collatBase,\n SLPData memory slpData,\n MintBurnData memory feeData\n );\n}\n\n/// @title PoolManager\n/// @author Angle Core Team\n/// @notice The `PoolManager` contract corresponds to a collateral pool of the protocol for a stablecoin,\n/// it manages a single ERC20 token. It is responsible for interacting with the strategies enabling the protocol\n/// to get yield on its collateral\n/// @dev This file contains the functions that are callable by governance or by other contracts of the protocol\n/// @dev References to this contract are called `PoolManager`\ncontract PoolManager is IPoolManagerFunctions, AccessControlUpgradeable, FunctionUtils {\n using SafeERC20 for IERC20;\n\n /// @notice Interface for the underlying token accepted by this contract\n IERC20 public token;\n\n /// @notice Reference to the `StableMaster` contract corresponding to this `PoolManager`\n IStableMaster public stableMaster;\n\n // ============================= Yield Farming =================================\n\n /// @notice Funds currently given to strategies\n uint256 public totalDebt;\n\n /// @notice Proportion of the funds managed dedicated to strategies\n /// Has to be between 0 and `BASE_PARAMS`\n uint256 public debtRatio;\n\n /// The struct `StrategyParams` is defined in the interface `IPoolManager`\n /// @notice Mapping between the address of a strategy contract and its corresponding details\n mapping(address => StrategyParams) public strategies;\n\n /// @notice List of the current strategies\n address[] public strategyList;\n\n /// @notice Address of the surplus distributor allowed to distribute rewards\n address public surplusConverter;\n\n /// @notice Share of the interests going to surplus and share going to SLPs\n uint64 public interestsForSurplus;\n\n /// @notice Interests accumulated by the protocol and to be distributed through ANGLE or veANGLE\n /// token holders\n uint256 public interestsAccumulated;\n\n /// @notice Debt that must be paid by admins after a loss on a strategy\n uint256 public adminDebt;\n\n event FeesDistributed(uint256 amountDistributed);\n\n event Recovered(address indexed token, address indexed to, uint256 amount);\n\n event StrategyAdded(address indexed strategy, uint256 debtRatio);\n\n event InterestsForSurplusUpdated(uint64 _interestsForSurplus);\n\n event SurplusConverterUpdated(address indexed newSurplusConverter, address indexed oldSurplusConverter);\n\n event StrategyRevoked(address indexed strategy);\n\n event StrategyReported(\n address indexed strategy,\n uint256 gain,\n uint256 loss,\n uint256 debtPayment,\n uint256 totalDebt\n );\n\n // Roles need to be defined here because there are some internal access control functions\n // in the `PoolManagerInternal` file\n\n /// @notice Role for `StableMaster` only\n bytes32 public constant STABLEMASTER_ROLE = keccak256(\"STABLEMASTER_ROLE\");\n /// @notice Role for governors only\n bytes32 public constant GOVERNOR_ROLE = keccak256(\"GOVERNOR_ROLE\");\n /// @notice Role for guardians and governors\n bytes32 public constant GUARDIAN_ROLE = keccak256(\"GUARDIAN_ROLE\");\n /// @notice Role for `Strategy` only\n bytes32 public constant STRATEGY_ROLE = keccak256(\"STRATEGY_ROLE\");\n\n // ============================= Yield Farming =================================\n\n /// @notice Internal version of `updateStrategyDebtRatio`\n /// @dev Updates the debt ratio for a strategy\n function _updateStrategyDebtRatio(address strategy, uint256 _debtRatio) internal {\n StrategyParams storage params = strategies[strategy];\n require(params.lastReport != 0, \"78\");\n debtRatio = debtRatio + _debtRatio - params.debtRatio;\n require(debtRatio <= BASE_PARAMS, \"76\");\n params.debtRatio = _debtRatio;\n emit StrategyAdded(strategy, debtRatio);\n }\n\n // ============================ Utils ==========================================\n\n /// @notice Returns this `PoolManager`'s reserve of collateral (not including what has been lent)\n function _getBalance() internal view returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n /// @notice Returns the amount of assets owned by this `PoolManager`\n /// @dev This sums the current balance of the contract to what has been given to strategies\n /// @dev This amount can be manipulated by flash loans\n function _getTotalAsset() internal view returns (uint256) {\n return _getBalance() + totalDebt;\n }\n\n // ============================= Yield Farming =================================\n\n /// @notice Provides an estimated Annual Percentage Rate for SLPs based on lending to other protocols\n /// @dev This function is an estimation and is made for external use only\n /// @dev This does not take into account transaction fees which accrue to SLPs too\n /// @dev This can be manipulated by a flash loan attack (SLP deposit/ withdraw) via `_getTotalAsset`\n /// when entering you should make sure this hasn't be called by a flash loan and look\n /// at a mean of past APR.\n function estimatedAPR() external view returns (uint256 apr) {\n apr = 0;\n (, ISanToken sanTokenForAPR, , , , uint256 sanRate, , SLPData memory slpData, ) = stableMaster.collateralMap(\n IPoolManager(address(this))\n );\n uint256 supply = sanTokenForAPR.totalSupply();\n\n // `sanRate` should never be equal to 0\n if (supply == 0) return type(uint256).max;\n\n for (uint256 i = 0; i < strategyList.length; i++) {\n apr =\n apr +\n (strategies[strategyList[i]].debtRatio * IStrategy(strategyList[i]).estimatedAPR()) /\n BASE_PARAMS;\n }\n apr = (apr * slpData.interestsForSLPs * _getTotalAsset()) / sanRate / supply;\n }\n\n /// @notice Tells a strategy how much it can borrow from this `PoolManager`\n /// @return Amount of token a strategy has access to as a credit line\n /// @dev Since this function is a view function, there is no need to have an access control logic\n /// even though it will just be relevant for a strategy\n /// @dev Manipulating `_getTotalAsset` with a flashloan will only\n /// result in tokens being transferred at the cost of the caller\n function creditAvailable() external view override returns (uint256) {\n StrategyParams storage params = strategies[msg.sender];\n\n uint256 target = (_getTotalAsset() * params.debtRatio) / BASE_PARAMS;\n\n if (target < params.totalStrategyDebt) return 0;\n\n return Math.min(target - params.totalStrategyDebt, _getBalance());\n }\n\n /// @notice Tells a strategy how much it owes to this `PoolManager`\n /// @return Amount of token a strategy has to reimburse\n /// @dev Manipulating `_getTotalAsset` with a flashloan will only\n /// result in tokens being transferred at the cost of the caller\n function debtOutstanding() external view override returns (uint256) {\n StrategyParams storage params = strategies[msg.sender];\n\n uint256 target = (_getTotalAsset() * params.debtRatio) / BASE_PARAMS;\n\n if (target > params.totalStrategyDebt) return 0;\n\n return (params.totalStrategyDebt - target);\n }\n\n /// @notice Reports the gains or loss made by a strategy\n /// @param gain Amount strategy has realized as a gain on its investment since its\n /// last report, and is free to be given back to `PoolManager` as earnings\n /// @param loss Amount strategy has realized as a loss on its investment since its\n /// last report, and should be accounted for on the `PoolManager`'s balance sheet.\n /// The loss will reduce the `debtRatio`. The next time the strategy will harvest,\n /// it will pay back the debt in an attempt to adjust to the new debt limit.\n /// @param debtPayment Amount strategy has made available to cover outstanding debt\n /// @dev This is the main contact point where the strategy interacts with the `PoolManager`\n /// @dev The strategy reports back what it has free, then the `PoolManager` contract \"decides\"\n /// whether to take some back or give it more. Note that the most it can\n /// take is `gain + _debtPayment`, and the most it can give is all of the\n /// remaining reserves. Anything outside of those bounds is abnormal behavior.\n function report(\n uint256 gain,\n uint256 loss,\n uint256 debtPayment\n ) external override onlyRole(STRATEGY_ROLE) {\n require(token.balanceOf(msg.sender) >= gain + debtPayment, \"72\");\n\n StrategyParams storage params = strategies[msg.sender];\n // Updating parameters in the `perpetualManager`\n // This needs to be done now because it has implications in `_getTotalAsset()`\n params.totalStrategyDebt = params.totalStrategyDebt + gain - loss;\n totalDebt = totalDebt + gain - loss;\n params.lastReport = block.timestamp;\n\n // Warning: `_getTotalAsset` could be manipulated by flashloan attacks.\n // It may allow external users to transfer funds into strategy or remove funds\n // from the strategy. Yet, as it does not impact the profit or loss and as attackers\n // have no interest in making such txs to have a direct profit, we let it as is.\n // The only issue is if the strategy is compromised; in this case governance\n // should revoke the strategy\n uint256 target = ((_getTotalAsset()) * params.debtRatio) / BASE_PARAMS;\n if (target > params.totalStrategyDebt) {\n // If the strategy has some credit left, tokens can be transferred to this strategy\n uint256 available = Math.min(target - params.totalStrategyDebt, _getBalance());\n params.totalStrategyDebt = params.totalStrategyDebt + available;\n totalDebt = totalDebt + available;\n if (available > 0) {\n token.safeTransfer(msg.sender, available);\n }\n } else {\n uint256 available = Math.min(params.totalStrategyDebt - target, debtPayment + gain);\n params.totalStrategyDebt = params.totalStrategyDebt - available;\n totalDebt = totalDebt - available;\n if (available > 0) {\n token.safeTransferFrom(msg.sender, address(this), available);\n }\n }\n emit StrategyReported(msg.sender, gain, loss, debtPayment, params.totalStrategyDebt);\n\n // Handle gains before losses\n if (gain > 0) {\n uint256 gainForSurplus = (gain * interestsForSurplus) / BASE_PARAMS;\n uint256 adminDebtPre = adminDebt;\n // Depending on the current admin debt distribute the necessary gain from the strategies\n if (adminDebtPre == 0) interestsAccumulated += gainForSurplus;\n else if (adminDebtPre <= gainForSurplus) {\n interestsAccumulated += gainForSurplus - adminDebtPre;\n adminDebt = 0;\n } else adminDebt -= gainForSurplus;\n stableMaster.accumulateInterest(gain - gainForSurplus);\n emit FeesDistributed(gain);\n }\n\n // Handle eventual losses\n if (loss > 0) {\n uint256 lossForSurplus = (loss * interestsForSurplus) / BASE_PARAMS;\n uint256 interestsAccumulatedPreLoss = interestsAccumulated;\n // If the loss can not be entirely soaked by the interests to be distributed then\n // the protocol keeps track of the debt\n if (lossForSurplus > interestsAccumulatedPreLoss) {\n interestsAccumulated = 0;\n adminDebt += lossForSurplus - interestsAccumulatedPreLoss;\n } else interestsAccumulated -= lossForSurplus;\n // The rest is incurred to SLPs\n stableMaster.signalLoss(loss - lossForSurplus);\n }\n }\n\n // =========================== Governor Functions ==============================\n\n /// @notice Allows to recover any ERC20 token, including the token handled by this contract, and to send it\n /// to a contract\n /// @param tokenAddress Address of the token to recover\n /// @param to Address of the contract to send collateral to\n /// @param amountToRecover Amount of collateral to transfer\n /// @dev As this function can be used to transfer funds to another contract, it has to be a `GOVERNOR` function\n /// @dev In case the concerned token is the specific token handled by this contract, this function checks that the\n /// amount entered is not too big and approximates the surplus of the protocol\n /// @dev To esimate the amount of user claims on the concerned collateral, this function uses the `stocksUsers` for\n /// this collateral, but this is just an approximation as users can claim the collateral of their choice provided\n /// that they own a stablecoin\n /// @dev The sanity check excludes the HA claims: to get a sense of it, this function would need to compute the cash out\n /// amount of all the perpetuals, and this cannot be done on-chain in a cheap manner\n /// @dev Overall, even though there is a sanity check, this function relies on the fact that governance is not corrupted\n /// in this protocol and will not try to withdraw too much funds\n function recoverERC20(\n address tokenAddress,\n address to,\n uint256 amountToRecover\n ) external onlyRole(GOVERNOR_ROLE) {\n if (tokenAddress == address(token)) {\n // Fetching info from the `StableMaster`\n (\n ,\n ISanToken sanToken,\n ,\n IOracle oracle,\n uint256 stocksUsers,\n uint256 sanRate,\n uint256 collatBase,\n ,\n\n ) = stableMaster.collateralMap(IPoolManager(address(this)));\n\n // Checking if there are enough reserves for the amount to withdraw\n require(\n _getTotalAsset() >=\n amountToRecover +\n (sanToken.totalSupply() * sanRate) /\n BASE_TOKENS +\n (stocksUsers * collatBase) /\n oracle.readUpper() +\n interestsAccumulated,\n \"66\"\n );\n\n token.safeTransfer(to, amountToRecover);\n } else {\n IERC20(tokenAddress).safeTransfer(to, amountToRecover);\n }\n emit Recovered(tokenAddress, to, amountToRecover);\n }\n\n /// @notice Adds a strategy to the `PoolManager`\n /// @param strategy The address of the strategy to add\n /// @param _debtRatio The share of the total assets that the strategy has access to\n /// @dev Multiple checks are made. For instance, the contract must not already belong to the `PoolManager`\n /// and the underlying token of the strategy has to be consistent with the `PoolManager` contracts\n /// @dev This function is a `governor` function and not a `guardian` one because a `guardian` could add a strategy\n /// enabling the withdraw of the funds of the protocol\n /// @dev The `_debtRatio` should be expressed in `BASE_PARAMS`\n function addStrategy(address strategy, uint256 _debtRatio) external onlyRole(GOVERNOR_ROLE) {\n StrategyParams storage params = strategies[strategy];\n\n require(params.lastReport == 0, \"73\");\n require(address(this) == IStrategy(strategy).poolManager(), \"74\");\n // Using current code, this condition should always be verified as in the constructor\n // of the strategy the `want()` is set to the token of this `PoolManager`\n require(address(token) == IStrategy(strategy).want(), \"75\");\n require(debtRatio + _debtRatio <= BASE_PARAMS, \"76\");\n\n // Add strategy to approved strategies\n params.lastReport = 1;\n params.totalStrategyDebt = 0;\n params.debtRatio = _debtRatio;\n\n _grantRole(STRATEGY_ROLE, strategy);\n\n // Update global parameters\n debtRatio += _debtRatio;\n emit StrategyAdded(strategy, debtRatio);\n\n strategyList.push(strategy);\n }\n\n // =========================== Guardian Functions ==============================\n\n /// @notice Modifies the funds a strategy has access to\n /// @param strategy The address of the Strategy\n /// @param _debtRatio The share of the total assets that the strategy has access to\n /// @dev The update has to be such that the `debtRatio` does not exceeds the 100% threshold\n /// as this `PoolManager` cannot lend collateral that it doesn't not own.\n /// @dev `_debtRatio` is stored as a uint256 but as any parameter of the protocol, it should be expressed\n /// in `BASE_PARAMS`\n function updateStrategyDebtRatio(address strategy, uint256 _debtRatio) external onlyRole(GUARDIAN_ROLE) {\n _updateStrategyDebtRatio(strategy, _debtRatio);\n }\n\n /// @notice Triggers an emergency exit for a strategy and then harvests it to fetch all the funds\n /// @param strategy The address of the `Strategy`\n function setStrategyEmergencyExit(address strategy) external onlyRole(GUARDIAN_ROLE) {\n _updateStrategyDebtRatio(strategy, 0);\n IStrategy(strategy).setEmergencyExit();\n IStrategy(strategy).harvest();\n }\n\n /// @notice Revokes a strategy\n /// @param strategy The address of the strategy to revoke\n /// @dev This should only be called after the following happened in order: the `strategy.debtRatio` has been set to 0,\n /// `harvest` has been called enough times to recover all capital gain/losses.\n function revokeStrategy(address strategy) external onlyRole(GUARDIAN_ROLE) {\n StrategyParams storage params = strategies[strategy];\n\n require(params.debtRatio == 0, \"77\");\n require(params.totalStrategyDebt == 0, \"77\");\n uint256 strategyListLength = strategyList.length;\n require(params.lastReport != 0 && strategyListLength >= 1, \"78\");\n // It has already been checked whether the strategy was a valid strategy\n for (uint256 i = 0; i < strategyListLength - 1; i++) {\n if (strategyList[i] == strategy) {\n strategyList[i] = strategyList[strategyListLength - 1];\n break;\n }\n }\n\n strategyList.pop();\n\n // Update global parameters\n debtRatio -= params.debtRatio;\n delete strategies[strategy];\n\n _revokeRole(STRATEGY_ROLE, strategy);\n\n emit StrategyRevoked(strategy);\n }\n\n /// @notice Withdraws a given amount from a strategy\n /// @param strategy The address of the strategy\n /// @param amount The amount to withdraw\n /// @dev This function tries to recover `amount` from the strategy, but it may not go through\n /// as we may not be able to withdraw from the lending protocol the full amount\n /// @dev In this last case we only update the parameters by setting the loss as the gap between\n /// what has been asked and what has been returned.\n function withdrawFromStrategy(IStrategy strategy, uint256 amount) external onlyRole(GUARDIAN_ROLE) {\n StrategyParams storage params = strategies[address(strategy)];\n require(params.lastReport != 0, \"78\");\n\n uint256 loss;\n (amount, loss) = strategy.withdraw(amount);\n\n // Handling eventual losses\n params.totalStrategyDebt = params.totalStrategyDebt - loss - amount;\n totalDebt = totalDebt - loss - amount;\n\n emit StrategyReported(address(strategy), 0, loss, amount - loss, params.totalStrategyDebt);\n\n // Handle eventual losses\n // With the strategy we are using in current tests, it is going to be impossible to have\n // a positive loss by calling strategy.withdraw, this function indeed calls _liquidatePosition\n // which output value is always zero\n if (loss > 0) stableMaster.signalLoss(loss);\n }\n\n // =================== Surplus Distributor Function ============================\n\n /// @notice Allows to push interests revenue accumulated by the protocol to the `surplusConverter` to do buybacks\n /// or another form of redistribution to ANGLE or veANGLE token holders\n /// @dev This function is permissionless and anyone can transfer the `interestsAccumulated` by the protocol\n /// to the `surplusConverter`\n function pushSurplus() external {\n // If the `surplusConverter` has not been initialized, surplus should not be distributed\n // Storing the `surplusConverter` in an intermediate variable to avoid multiple reads in\n // storage\n address surplusConverterMem = surplusConverter;\n require(surplusConverterMem != address(0), \"0\");\n uint256 amount = interestsAccumulated;\n interestsAccumulated = 0;\n // Storing the `token` in memory to avoid duplicate reads in storage\n IERC20 tokenMem = token;\n tokenMem.safeTransfer(surplusConverterMem, amount);\n emit Recovered(address(tokenMem), surplusConverterMem, amount);\n }\n\n // ======================== Getters - View Functions ===========================\n\n /// @notice Gets the current balance of this `PoolManager` contract\n /// @return The amount of the underlying collateral that the contract currently owns\n /// @dev This balance does not take into account what has been lent to strategies\n function getBalance() external view override returns (uint256) {\n return _getBalance();\n }\n\n /// @notice Gets the total amount of collateral that is controlled by this `PoolManager` contract\n /// @return The amount of collateral owned by this contract plus the amount that has been lent to strategies\n /// @dev This is the value that is used to compute the debt ratio for a given strategy\n function getTotalAsset() external view override returns (uint256) {\n return _getTotalAsset();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "contracts/utils/FunctionUtils.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\n/// @title FunctionUtils\n/// @author Angle Core Team\n/// @notice Contains all the utility functions that are needed in different places of the protocol\n/// @dev Functions in this contract should typically be pure functions\n/// @dev This contract is voluntarily a contract and not a library to save some gas cost every time it is used\ncontract FunctionUtils {\n /// @notice Base that is used to compute ratios and floating numbers\n uint256 public constant BASE_TOKENS = 10**18;\n /// @notice Base that is used to define parameters that need to have a floating value (for instance parameters\n /// that are defined as ratios)\n uint256 public constant BASE_PARAMS = 10**9;\n\n /// @notice Computes the value of a linear by part function at a given point\n /// @param x Point of the function we want to compute\n /// @param xArray List of breaking points (in ascending order) that define the linear by part function\n /// @param yArray List of values at breaking points (not necessarily in ascending order)\n /// @dev The evolution of the linear by part function between two breaking points is linear\n /// @dev Before the first breaking point and after the last one, the function is constant with a value\n /// equal to the first or last value of the yArray\n /// @dev This function is relevant if `x` is between O and `BASE_PARAMS`. If `x` is greater than that, then\n /// everything will be as if `x` is equal to the greater element of the `xArray`\n function _piecewiseLinear(\n uint64 x,\n uint64[] memory xArray,\n uint64[] memory yArray\n ) internal pure returns (uint64) {\n if (x >= xArray[xArray.length - 1]) {\n return yArray[xArray.length - 1];\n } else if (x <= xArray[0]) {\n return yArray[0];\n } else {\n uint256 lower;\n uint256 upper = xArray.length - 1;\n uint256 mid;\n while (upper - lower > 1) {\n mid = lower + (upper - lower) / 2;\n if (xArray[mid] <= x) {\n lower = mid;\n } else {\n upper = mid;\n }\n }\n if (yArray[upper] > yArray[lower]) {\n // There is no risk of overflow here as in the product of the difference of `y`\n // with the difference of `x`, the product is inferior to `BASE_PARAMS**2` which does not\n // overflow for `uint64`\n return\n yArray[lower] +\n ((yArray[upper] - yArray[lower]) * (x - xArray[lower])) /\n (xArray[upper] - xArray[lower]);\n } else {\n return\n yArray[lower] -\n ((yArray[lower] - yArray[upper]) * (x - xArray[lower])) /\n (xArray[upper] - xArray[lower]);\n }\n }\n }\n\n /// @notice Checks if the input arrays given by governance to update the fee structure is valid\n /// @param xArray List of breaking points (in ascending order) that define the linear by part function\n /// @param yArray List of values at breaking points (not necessarily in ascending order)\n /// @dev This function is a way to avoid some governance attacks or errors\n /// @dev The modifier checks if the arrays have a non null length, if their length is the same, if the values\n /// in the `xArray` are in ascending order and if the values in the `xArray` and in the `yArray` are not superior\n /// to `BASE_PARAMS`\n modifier onlyCompatibleInputArrays(uint64[] memory xArray, uint64[] memory yArray) {\n require(xArray.length == yArray.length && xArray.length > 0, \"5\");\n for (uint256 i = 0; i <= yArray.length - 1; i++) {\n require(yArray[i] <= uint64(BASE_PARAMS) && xArray[i] <= uint64(BASE_PARAMS), \"6\");\n if (i > 0) {\n require(xArray[i] > xArray[i - 1], \"7\");\n }\n }\n _;\n }\n\n /// @notice Checks if the new value given for the parameter is consistent (it should be inferior to 1\n /// if it corresponds to a ratio)\n /// @param fees Value of the new parameter to check\n modifier onlyCompatibleFees(uint64 fees) {\n require(fees <= BASE_PARAMS, \"4\");\n _;\n }\n\n /// @notice Checks if the new address given is not null\n /// @param newAddress Address to check\n /// @dev Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation\n modifier zeroCheck(address newAddress) {\n require(newAddress != address(0), \"0\");\n _;\n }\n}\n" + }, + "contracts/mock/MockPoolManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\nimport \"../interfaces/IPoolManager.sol\";\nimport \"../interfaces/IStrategy.sol\";\n\ncontract MockPoolManager is AccessControl {\n using SafeERC20 for IERC20;\n\n uint256 public constant BASE_TOKENS = 10**18;\n uint256 public constant BASE_PARAMS = 10**9;\n\n bytes32 public constant STRATEGY_ROLE = keccak256(\"STRATEGY_ROLE\");\n\n mapping(address => StrategyParams) public strategies;\n address[] public strategyList;\n\n IERC20 public token;\n uint256 public creditAvailable;\n uint256 public totalDebt;\n uint256 public debtRatio;\n\n event StrategyReported(\n address indexed strategy,\n uint256 gain,\n uint256 loss,\n uint256 debtPayment,\n uint256 totalDebt\n );\n event StrategyAdded(address indexed strategy, uint256 debtRatio);\n event StrategyRevoked(address indexed strategy);\n\n constructor(address _token, uint256 _creditAvailable) {\n token = IERC20(_token);\n creditAvailable = _creditAvailable;\n }\n\n function debtOutstanding() external view returns (uint256) {\n StrategyParams storage params = strategies[msg.sender];\n\n uint256 target = (_getTotalAsset() * params.debtRatio) / BASE_PARAMS;\n\n // console.log(\"debtOutstanding: totalStrategyDebt %s / target: %s / debtRatio: %s\", params.totalStrategyDebt, target, params.debtRatio);\n\n if (target > params.totalStrategyDebt) return 0;\n\n return (params.totalStrategyDebt - target);\n }\n\n function report(\n uint256 gain,\n uint256 loss,\n uint256 debtPayment\n ) external {\n require(token.balanceOf(msg.sender) >= gain + debtPayment, \"72\");\n\n StrategyParams storage params = strategies[msg.sender];\n // Updating parameters in the `perpetualManager`\n // This needs to be done now because it has implications in `_getTotalAsset()`\n params.totalStrategyDebt = params.totalStrategyDebt + gain - loss;\n totalDebt = totalDebt + gain - loss;\n params.lastReport = block.timestamp;\n\n // Warning: `_getTotalAsset` could be manipulated by flashloan attacks.\n // It may allow external users to transfer funds into strategy or remove funds\n // from the strategy. Yet, as it does not impact the profit or loss and as attackers\n // have no interest in making such txs to have a direct profit, we let it as is.\n // The only issue is if the strategy is compromised; in this case governance\n // should revoke the strategy\n uint256 target = ((_getTotalAsset()) * params.debtRatio) / BASE_PARAMS;\n // console.log(\"PoolManager - report\");\n // console.log(\"_getTotalAsset %s / target %s\", _getTotalAsset(), target);\n if (target > params.totalStrategyDebt) {\n // If the strategy has some credit left, tokens can be transferred to this strategy\n uint256 available = Math.min(target - params.totalStrategyDebt, _getBalance());\n // console.log(\"available1 %s\", available);\n params.totalStrategyDebt = params.totalStrategyDebt + available;\n totalDebt = totalDebt + available;\n if (available > 0) {\n token.safeTransfer(msg.sender, available);\n }\n } else {\n uint256 available = Math.min(params.totalStrategyDebt - target, debtPayment + gain);\n // console.log(\"available2 %s\", available);\n params.totalStrategyDebt = params.totalStrategyDebt - available;\n totalDebt = totalDebt - available;\n if (available > 0) {\n token.safeTransferFrom(msg.sender, address(this), available);\n }\n }\n emit StrategyReported(msg.sender, gain, loss, debtPayment, params.totalStrategyDebt);\n }\n\n function _getBalance() internal view returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n function getTotalAsset() external view returns (uint256) {\n return _getTotalAsset();\n }\n\n function _getTotalAsset() internal view returns (uint256) {\n return _getBalance() + totalDebt;\n }\n\n function addStrategy(address strategy, uint256 _debtRatio) external {\n StrategyParams storage params = strategies[strategy];\n\n require(params.lastReport == 0, \"73\");\n require(address(this) == IStrategy(strategy).poolManager(), \"74\");\n // Using current code, this condition should always be verified as in the constructor\n // of the strategy the `want()` is set to the token of this `PoolManager`\n require(address(token) == IStrategy(strategy).want(), \"75\");\n require(debtRatio + _debtRatio <= BASE_PARAMS, \"76\");\n\n // Add strategy to approved strategies\n params.lastReport = 1;\n params.totalStrategyDebt = 0;\n params.debtRatio = _debtRatio;\n\n _grantRole(STRATEGY_ROLE, strategy);\n\n // Update global parameters\n debtRatio += _debtRatio;\n emit StrategyAdded(strategy, debtRatio);\n\n strategyList.push(strategy);\n }\n\n function revokeStrategy(address strategy) external {\n StrategyParams storage params = strategies[strategy];\n\n require(params.debtRatio == 0, \"77\");\n require(params.totalStrategyDebt == 0, \"77\");\n uint256 strategyListLength = strategyList.length;\n require(params.lastReport != 0 && strategyListLength >= 1, \"78\");\n // It has already been checked whether the strategy was a valid strategy\n for (uint256 i = 0; i < strategyListLength - 1; i++) {\n if (strategyList[i] == strategy) {\n strategyList[i] = strategyList[strategyListLength - 1];\n break;\n }\n }\n\n strategyList.pop();\n\n // Update global parameters\n debtRatio -= params.debtRatio;\n delete strategies[strategy];\n\n _revokeRole(STRATEGY_ROLE, strategy);\n\n emit StrategyRevoked(strategy);\n }\n\n function updateStrategyDebtRatio(address strategy, uint256 _debtRatio) external {\n StrategyParams storage params = strategies[strategy];\n require(params.lastReport != 0, \"78\");\n debtRatio = debtRatio + _debtRatio - params.debtRatio;\n require(debtRatio <= BASE_PARAMS, \"76\");\n params.debtRatio = _debtRatio;\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "contracts/strategies/AaveFlashloanStrategy/AaveFlashloanStrategy.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\nimport \"./AaveLibraries.sol\";\nimport \"./AaveInterfaces.sol\";\nimport \"../BaseStrategyUpgradeable.sol\";\nimport \"./ComputeProfitability.sol\";\n\n/// @title AaveFlashloanStrategy\n/// @author Yearn Finance (https://etherscan.io/address/0xd4E94061183b2DBF24473F28A3559cf4dE4459Db#code)\n/// but heavily reviewed and modified by Angle Core Team\n/// @notice This strategy is used to optimize lending yield on Aave by taking some form or recursivity that is to say\n/// by borrowing to maximize Aave rewards\n/// @dev Angle strategies computes the optimal collateral ratio based on AAVE rewards for deposits and borrows\n// solhint-disable-next-line max-states-count\ncontract AaveFlashloanStrategy is BaseStrategyUpgradeable, IERC3156FlashBorrower {\n using SafeERC20 for IERC20;\n using Address for address;\n\n // =========================== Constant Addresses ==============================\n\n /// @notice Router used for swaps\n address private constant _oneInch = 0x1111111254fb6c44bAC0beD2854e76F90643097d;\n /// @notice Chainlink oracle used to fetch data\n AggregatorV3Interface private constant _chainlinkOracle =\n AggregatorV3Interface(0x547a514d5e3769680Ce22B2361c10Ea13619e8a9);\n\n // ========================== Aave Protocol Addresses ==========================\n\n IAaveIncentivesController private constant _incentivesController =\n IAaveIncentivesController(0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5);\n ILendingPool private constant _lendingPool = ILendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);\n IProtocolDataProvider private constant _protocolDataProvider =\n IProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);\n\n // ============================== Token Addresses ==============================\n\n address private constant _aave = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;\n IStakedAave private constant _stkAave = IStakedAave(0x4da27a545c0c5B758a6BA100e3a049001de870f5);\n address private constant _weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n address private constant _dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n // ============================== Ops Constants ================================\n\n uint256 private constant _DEFAULT_COLLAT_TARGET_MARGIN = 0.02 ether;\n uint256 private constant _DEFAULT_COLLAT_MAX_MARGIN = 0.005 ether;\n uint256 private constant _LIQUIDATION_WARNING_THRESHOLD = 0.01 ether;\n uint256 private constant _BPS_WAD_RATIO = 1e14;\n uint256 private constant _COLLATERAL_RATIO_PRECISION = 1 ether;\n uint16 private constant _referral = 0;\n\n // ========================= Aave Protocol Parameters ==========================\n\n IReserveInterestRateStrategy private _interestRateStrategyAddress;\n uint256 public cooldownSeconds;\n uint256 public unstakeWindow;\n int256 public reserveFactor;\n int256 public slope1;\n int256 public slope2;\n int256 public r0;\n int256 public uOptimal;\n\n // =============================== Parameters and Variables ====================\n\n /// @notice Maximum the Aave protocol will let us borrow\n uint256 public maxBorrowCollatRatio;\n /// @notice LTV the strategy is going to lever up to\n uint256 public targetCollatRatio;\n /// @notice Closest to liquidation we'll risk\n uint256 public maxCollatRatio;\n /// @notice Parameter used for flash mints\n uint256 public daiBorrowCollatRatio;\n /// @notice Minimum amount to be moved before a deposit or a borrow\n uint256 public minWant;\n /// @notice Minimum gap between the collat ratio and the target collat ratio before\n /// rectifying it\n uint256 public minRatio;\n /// @notice Discount factor applied to the StkAAVE price\n uint256 public discountFactor;\n /// @notice Max number of iterations possible for the computation of the optimal lever\n uint8 public maxIterations;\n\n struct BoolParams {\n // Whether collateral ratio will be automatically computed\n bool automaticallyComputeCollatRatio;\n // Whether Flash mint is active\n bool isFlashMintActive;\n // Whether we should check withdrawals\n bool withdrawCheck;\n // Whether StkAAVE should be sent to cooldown or simply swapped for Aave all the time\n bool cooldownStkAave;\n }\n /// @notice Struct with some boolean parameters of the contract\n /// These parameters are packed in a struct for efficiency of SLOAD operations\n BoolParams public boolParams;\n\n // ========================= Supply and Borrow Tokens ==========================\n\n IAToken private _aToken;\n IVariableDebtToken private _debtToken;\n\n // ============================ Initializer ====================================\n\n /// @notice Constructor of the `Strategy`\n /// @param _poolManager Address of the `PoolManager` lending to this strategy\n /// @param interestRateStrategyAddress_ Address of the `InterestRateStrategy` defining borrow rates for the collateral\n /// @param governor Governor address of the protocol\n /// @param guardian Address of the guardian\n /// @param keepers List of the addresses with keeper privilege\n function initialize(\n address _poolManager,\n IReserveInterestRateStrategy interestRateStrategyAddress_,\n address governor,\n address guardian,\n address[] memory keepers\n ) external {\n _initialize(_poolManager, governor, guardian, keepers);\n\n // Then initializing operational state\n maxIterations = 6;\n // Setting mins\n minWant = 100;\n minRatio = 0.005 ether;\n discountFactor = 9000;\n\n boolParams = BoolParams({\n automaticallyComputeCollatRatio: true,\n isFlashMintActive: true,\n withdrawCheck: false,\n cooldownStkAave: true\n });\n\n _interestRateStrategyAddress = interestRateStrategyAddress_;\n // Setting reward params\n _setAavePoolVariables();\n\n // Set AAVE tokens\n (address aToken_, , address debtToken_) = _protocolDataProvider.getReserveTokensAddresses(address(want));\n _aToken = IAToken(aToken_);\n _debtToken = IVariableDebtToken(debtToken_);\n\n // Let collateral targets\n (uint256 ltv, uint256 liquidationThreshold) = _getProtocolCollatRatios(address(want));\n targetCollatRatio = liquidationThreshold - _DEFAULT_COLLAT_TARGET_MARGIN;\n maxCollatRatio = liquidationThreshold - _DEFAULT_COLLAT_MAX_MARGIN;\n maxBorrowCollatRatio = ltv - _DEFAULT_COLLAT_MAX_MARGIN;\n (uint256 daiLtv, ) = _getProtocolCollatRatios(_dai);\n daiBorrowCollatRatio = daiLtv - _DEFAULT_COLLAT_MAX_MARGIN;\n\n // Performing all the different approvals possible\n _approveMaxSpend(address(want), address(_lendingPool));\n _approveMaxSpend(aToken_, address(_lendingPool));\n // Approve flashloan spend\n _approveMaxSpend(_dai, FlashMintLib.LENDER);\n // Approve swap router spend\n _approveMaxSpend(address(_stkAave), _oneInch);\n _approveMaxSpend(_aave, _oneInch);\n if (address(want) != _dai) {\n _approveMaxSpend(_dai, address(_lendingPool));\n }\n }\n\n // ======================= Helper View Functions ===============================\n\n /// @notice Estimates the total assets controlled by the strategy\n /// @dev It sums the effective deposit amount to the rewards accumulated\n function estimatedTotalAssets() public view override returns (uint256) {\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n return\n _balanceOfWant() +\n deposits -\n borrows +\n _estimatedStkAaveToWant(\n _balanceOfStkAave() +\n _balanceOfAave() +\n _incentivesController.getRewardsBalance(_getAaveAssets(), address(this))\n );\n }\n\n /// @notice Get the current position of the strategy: that is to say the amount deposited\n /// and the amount borrowed on Aave\n /// @dev The actual amount brought is `deposits - borrows`\n function getCurrentPosition() public view returns (uint256 deposits, uint256 borrows) {\n deposits = _balanceOfAToken();\n borrows = _balanceOfDebtToken();\n }\n\n // ====================== Internal Strategy Functions ==========================\n\n /// @notice Frees up profit plus `_debtOutstanding`.\n /// @param _debtOutstanding Amount to withdraw\n /// @return _profit Profit freed by the call\n /// @return _loss Loss discovered by the call\n /// @return _debtPayment Amount freed to reimburse the debt\n /// @dev If `_debtOutstanding` is more than we can free we get as much as possible.\n function _prepareReturn(uint256 _debtOutstanding)\n internal\n override\n returns (\n uint256 _profit,\n uint256 _loss,\n uint256 _debtPayment\n )\n {\n // account for profit / losses\n uint256 totalDebt = poolManager.strategies(address(this)).totalStrategyDebt;\n\n // Assets immediately convertible to want only\n uint256 amountAvailable = _balanceOfWant();\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n uint256 totalAssets = amountAvailable + deposits - borrows;\n\n if (totalDebt > totalAssets) {\n // we have losses\n _loss = totalDebt - totalAssets;\n } else {\n // we have profit\n _profit = totalAssets - totalDebt;\n }\n\n // free funds to repay debt + profit to the strategy\n uint256 amountRequired = _debtOutstanding + _profit;\n\n if (amountRequired > amountAvailable) {\n // we need to free funds\n // we dismiss losses here, they cannot be generated from withdrawal\n // but it is possible for the strategy to unwind full position\n (amountAvailable, ) = _liquidatePosition(amountRequired, amountAvailable, deposits, borrows);\n\n if (amountAvailable >= amountRequired) {\n _debtPayment = _debtOutstanding;\n // profit remains unchanged unless there is not enough to pay it\n if (amountRequired - _debtPayment < _profit) {\n _profit = amountRequired - _debtPayment;\n }\n } else {\n // we were not able to free enough funds\n if (amountAvailable < _debtOutstanding) {\n // available funds are lower than the repayment that we need to do\n _profit = 0;\n _debtPayment = amountAvailable;\n // we dont report losses here as the strategy might not be able to return in this harvest\n // but it will still be there for the next harvest\n } else {\n // NOTE: amountRequired is always equal or greater than _debtOutstanding\n // important to use amountRequired just in case amountAvailable is > amountAvailable\n _debtPayment = _debtOutstanding;\n _profit = amountAvailable - _debtPayment;\n }\n }\n } else {\n _debtPayment = _debtOutstanding;\n // profit remains unchanged unless there is not enough to pay it\n if (amountRequired - _debtPayment < _profit) {\n _profit = amountRequired - _debtPayment;\n }\n }\n }\n\n /// @notice Function called by _harvest()\n function _adjustPosition() internal override {\n _adjustPosition(type(uint256).max);\n }\n\n /// @notice Function called by _adjustPosition()\n /// @param guessedBorrow First guess to the borrow amount to maximise revenue\n /// @dev It computes the optimal collateral ratio and adjusts deposits/borrows accordingly\n function _adjustPosition(uint256 guessedBorrow) internal override {\n uint256 _debtOutstanding = poolManager.debtOutstanding();\n\n uint256 wantBalance = _balanceOfWant();\n // deposit available want as collateral\n if (wantBalance > _debtOutstanding && wantBalance - _debtOutstanding > minWant) {\n _depositCollateral(wantBalance - _debtOutstanding);\n // Updating the `wantBalance` value\n wantBalance = _balanceOfWant();\n }\n\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n guessedBorrow = (guessedBorrow == type(uint256).max) ? borrows : guessedBorrow;\n uint256 _targetCollatRatio;\n if (boolParams.automaticallyComputeCollatRatio) {\n _targetCollatRatio = _computeOptimalCollatRatio(\n wantBalance + deposits - borrows,\n deposits,\n borrows,\n guessedBorrow\n );\n } else {\n _targetCollatRatio = targetCollatRatio;\n }\n\n // check current position\n uint256 currentCollatRatio = _getCollatRatio(deposits, borrows);\n\n // Either we need to free some funds OR we want to be max levered\n if (_debtOutstanding > wantBalance) {\n // we should free funds\n uint256 amountRequired = _debtOutstanding - wantBalance;\n\n // NOTE: vault will take free funds during the next harvest\n _freeFunds(amountRequired, deposits, borrows);\n } else if (currentCollatRatio < _targetCollatRatio) {\n // we should lever up\n if (_targetCollatRatio - currentCollatRatio > minRatio) {\n // we only act on relevant differences\n _leverMax(deposits, borrows);\n }\n } else if (currentCollatRatio > _targetCollatRatio) {\n if (currentCollatRatio - _targetCollatRatio > minRatio) {\n uint256 newBorrow = _getBorrowFromSupply(deposits - borrows, _targetCollatRatio);\n _leverDownTo(newBorrow, deposits, borrows);\n }\n }\n }\n\n /// @notice Liquidates `_amountNeeded` from a position\n /// @dev For gas efficiency this function calls another internal function\n function _liquidatePosition(uint256 _amountNeeded) internal override returns (uint256, uint256) {\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n return _liquidatePosition(_amountNeeded, _balanceOfWant(), deposits, borrows);\n }\n\n /// @notice Withdraws `_amountNeeded` of `want` from Aave\n /// @param _amountNeeded Amount of `want` to free\n /// @return _liquidatedAmount Amount of `want` available\n /// @return _loss Difference between `_amountNeeded` and what is actually available\n function _liquidatePosition(\n uint256 _amountNeeded,\n uint256 wantBalance,\n uint256 deposits,\n uint256 borrows\n ) internal returns (uint256 _liquidatedAmount, uint256 _loss) {\n // NOTE: Maintain invariant `want.balanceOf(this) >= _liquidatedAmount`\n // NOTE: Maintain invariant `_liquidatedAmount + _loss <= _amountNeeded`\n if (wantBalance > _amountNeeded) {\n // if there is enough free want, let's use it\n return (_amountNeeded, 0);\n }\n\n // we need to free funds\n uint256 amountRequired = _amountNeeded - wantBalance;\n _freeFunds(amountRequired, deposits, borrows);\n // Updating the `wantBalance` variable\n wantBalance = _balanceOfWant();\n if (_amountNeeded > wantBalance) {\n _liquidatedAmount = wantBalance;\n uint256 diff = _amountNeeded - _liquidatedAmount;\n if (diff <= minWant) {\n _loss = diff;\n }\n } else {\n _liquidatedAmount = _amountNeeded;\n }\n\n if (boolParams.withdrawCheck) {\n require(_amountNeeded == _liquidatedAmount + _loss, \"54\"); // dev: withdraw safety check\n }\n }\n\n /// @notice Withdraw as much as we can from Aave\n /// @return _amountFreed Amount successfully freed\n function _liquidateAllPositions() internal override returns (uint256 _amountFreed) {\n (_amountFreed, ) = _liquidatePosition(type(uint256).max);\n }\n\n function _protectedTokens() internal view override returns (address[] memory) {}\n\n // ============================== Setters ======================================\n\n /// @notice Sets collateral targets and value for collateral ratio\n function setCollateralTargets(\n uint256 _targetCollatRatio,\n uint256 _maxCollatRatio,\n uint256 _maxBorrowCollatRatio,\n uint256 _daiBorrowCollatRatio\n ) external onlyRole(GUARDIAN_ROLE) {\n (uint256 ltv, uint256 liquidationThreshold) = _getProtocolCollatRatios(address(want));\n (uint256 daiLtv, ) = _getProtocolCollatRatios(_dai);\n require(\n _targetCollatRatio < liquidationThreshold &&\n _maxCollatRatio < liquidationThreshold &&\n _targetCollatRatio < _maxCollatRatio &&\n _maxBorrowCollatRatio < ltv &&\n _daiBorrowCollatRatio < daiLtv,\n \"8\"\n );\n\n targetCollatRatio = _targetCollatRatio;\n maxCollatRatio = _maxCollatRatio;\n maxBorrowCollatRatio = _maxBorrowCollatRatio;\n daiBorrowCollatRatio = _daiBorrowCollatRatio;\n }\n\n /// @notice Sets `minWant`, `minRatio` and `maxItrations` values\n function setMinsAndMaxs(\n uint256 _minWant,\n uint256 _minRatio,\n uint8 _maxIterations\n ) external onlyRole(GUARDIAN_ROLE) {\n require(_minRatio < maxBorrowCollatRatio && _maxIterations > 0 && _maxIterations < 16, \"8\");\n minWant = _minWant;\n minRatio = _minRatio;\n maxIterations = _maxIterations;\n }\n\n /// @notice Sets all boolean parameters related to cooldown, withdraw check, flash loan and so on\n function setBoolParams(BoolParams memory _boolParams) external onlyRole(GUARDIAN_ROLE) {\n boolParams = _boolParams;\n }\n\n /// @notice Sets the discount factor for the StkAAVE price\n function setDiscountFactor(uint256 _discountFactor) external onlyRole(GUARDIAN_ROLE) {\n require(_discountFactor < 10000, \"4\");\n discountFactor = _discountFactor;\n }\n\n /// @notice Retrieves lending pool variables for `want`. Those variables are mostly used in the function\n /// to compute the optimal borrow amount\n /// @dev No access control needed because they fetch the values from Aave directly.\n /// If it changes there, it will need to be updated here too\n /// @dev We expect the values concerned not to be often modified\n function setAavePoolVariables() external {\n _setAavePoolVariables();\n }\n\n // ========================== External Actions =================================\n\n /// @notice Emergency function that we can use to deleverage manually if something is broken\n /// @param amount Amount of `want` to withdraw/repay\n function manualDeleverage(uint256 amount) external onlyRole(GUARDIAN_ROLE) {\n _withdrawCollateral(amount);\n _repayWant(amount);\n }\n\n /// @notice Emergency function that we can use to deleverage manually if something is broken\n /// @param amount Amount of `want` to withdraw\n function manualReleaseWant(uint256 amount) external onlyRole(GUARDIAN_ROLE) {\n _withdrawCollateral(amount);\n }\n\n /// @notice Adds a new guardian address\n /// @param _guardian New guardian address\n function addGuardian(address _guardian) external override onlyRole(POOLMANAGER_ROLE) {\n // Granting the new role\n // Access control for this contract\n _grantRole(GUARDIAN_ROLE, _guardian);\n }\n\n /// @notice Revokes the guardian role\n /// @param guardian Old guardian address to revoke\n function revokeGuardian(address guardian) external override onlyRole(POOLMANAGER_ROLE) {\n _revokeRole(GUARDIAN_ROLE, guardian);\n }\n\n /// @notice Swap earned stkAave or Aave for `want` through 1Inch\n /// @param minAmountOut Minimum amount of `want` to receive for the swap to happen\n /// @param payload Bytes needed for 1Inch API. Tokens swapped should be: stkAave -> `want` or Aave -> `want`\n function sellRewards(\n uint256 minAmountOut,\n bytes memory payload\n ) external onlyRole(KEEPER_ROLE) {\n //solhint-disable-next-line\n (bool success, bytes memory result) = _oneInch.call(payload);\n if (!success) _revertBytes(result);\n\n uint256 amountOut = abi.decode(result, (uint256));\n require(amountOut >= minAmountOut, \"15\");\n }\n\n /// @notice Flashload callback, as defined by EIP-3156\n /// @notice We check that the call is coming from the DAI lender and then execute the load logic\n /// @dev If everything went smoothly, will return `keccak256(\"ERC3156FlashBorrower.onFlashLoan\")`\n function onFlashLoan(\n address initiator,\n address,\n uint256 amount,\n uint256,\n bytes calldata data\n ) external override returns (bytes32) {\n require(msg.sender == FlashMintLib.LENDER && initiator == address(this), \"1\");\n (bool deficit, uint256 amountWant) = abi.decode(data, (bool, uint256));\n\n return FlashMintLib.loanLogic(deficit, amountWant, amount, address(want));\n }\n\n // ========================== Internal Actions =================================\n\n /// @notice Claim earned stkAAVE (only called at `harvest`)\n /// @dev stkAAVE require a \"cooldown\" period of 10 days before being claimed\n function _claimRewards() internal returns (uint256 stkAaveBalance) {\n stkAaveBalance = _balanceOfStkAave();\n uint256 cooldownStatus;\n if (stkAaveBalance > 0) {\n cooldownStatus = _checkCooldown(); // don't check status if we have no stkAave\n }\n\n // If it's the claim period claim\n if (stkAaveBalance > 0 && cooldownStatus == 1) {\n // redeem AAVE from stkAave\n _stkAave.claimRewards(address(this), type(uint256).max);\n _stkAave.redeem(address(this), stkAaveBalance);\n }\n\n // claim stkAave from lending and borrowing, this will reset the cooldown\n _incentivesController.claimRewards(_getAaveAssets(), type(uint256).max, address(this));\n\n stkAaveBalance = _balanceOfStkAave();\n\n // request start of cooldown period, if there's no cooldown in progress\n if (boolParams.cooldownStkAave && stkAaveBalance > 0 && cooldownStatus == 0) {\n _stkAave.cooldown();\n }\n }\n\n function claimRewards() external onlyRole(KEEPER_ROLE) {\n _claimRewards();\n }\n\n /// @notice Reduce exposure by withdrawing funds and repaying debt\n /// @param amountToFree Amount of `want` to withdraw/repay\n /// @return balance Current balance of `want`\n /// @dev `deposits` and `borrows` are always computed prior to the call\n function _freeFunds(\n uint256 amountToFree,\n uint256 deposits,\n uint256 borrows\n ) internal returns (uint256) {\n if (amountToFree == 0) return 0;\n\n uint256 realAssets = deposits - borrows;\n uint256 newBorrow = _getBorrowFromSupply(realAssets - Math.min(amountToFree, realAssets), targetCollatRatio);\n\n // repay required amount\n _leverDownTo(newBorrow, deposits, borrows);\n\n return _balanceOfWant();\n }\n\n /// @notice Get exposure up to `targetCollatRatio`\n function _leverMax(uint256 deposits, uint256 borrows) internal {\n uint256 totalAmountToBorrow = _getBorrowFromSupply(deposits - borrows, targetCollatRatio) - borrows;\n\n if (boolParams.isFlashMintActive) {\n // The best approach is to lever up using regular method, then finish with flash loan\n totalAmountToBorrow = totalAmountToBorrow - _leverUpStep(totalAmountToBorrow, deposits, borrows);\n\n if (totalAmountToBorrow > minWant) {\n totalAmountToBorrow = totalAmountToBorrow - _leverUpFlashLoan(totalAmountToBorrow);\n }\n } else {\n for (uint8 i = 0; i < maxIterations && totalAmountToBorrow > minWant; i++) {\n totalAmountToBorrow = totalAmountToBorrow - _leverUpStep(totalAmountToBorrow, deposits, borrows);\n deposits = 0;\n borrows = 0;\n }\n }\n }\n\n /// @notice Use a flashloan to increase our exposure in `want` on Aave\n /// @param amount Amount we will deposit and borrow on Aave\n /// @return amount Actual amount deposited/borrowed\n /// @dev Amount returned should equal `amount` but can be lower if we try to flashloan more than `maxFlashLoan` authorized\n function _leverUpFlashLoan(uint256 amount) internal returns (uint256) {\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n uint256 depositsToMeetLtv = _getDepositFromBorrow(borrows, maxBorrowCollatRatio, deposits);\n uint256 depositsDeficitToMeetLtv = 0;\n if (depositsToMeetLtv > deposits) {\n depositsDeficitToMeetLtv = depositsToMeetLtv - deposits;\n }\n return FlashMintLib.doFlashMint(false, amount, address(want), daiBorrowCollatRatio, depositsDeficitToMeetLtv);\n }\n\n /// @notice Increase exposure in `want`\n /// @param amount Amount of `want` to borrow\n /// @return amount Amount of `want` that was borrowed\n function _leverUpStep(\n uint256 amount,\n uint256 deposits,\n uint256 borrows\n ) internal returns (uint256) {\n if (deposits == 0 && borrows == 0) (deposits, borrows) = getCurrentPosition();\n\n uint256 wantBalance = _balanceOfWant();\n\n uint256 canBorrow = _getBorrowFromDeposit(deposits + wantBalance, maxBorrowCollatRatio);\n\n if (canBorrow <= borrows) {\n return 0;\n }\n canBorrow = canBorrow - borrows;\n\n if (canBorrow < amount) {\n amount = canBorrow;\n }\n\n _depositCollateral(wantBalance);\n _borrowWant(amount);\n _depositCollateral(amount);\n\n return amount;\n }\n\n /// @notice Reduce our exposure to `want` on Aave\n /// @param newAmountBorrowed Total amount we want to be borrowing\n /// @param deposits Amount currently lent\n /// @param currentBorrowed Amount currently borrowed\n function _leverDownTo(\n uint256 newAmountBorrowed,\n uint256 deposits,\n uint256 currentBorrowed\n ) internal {\n if (currentBorrowed > newAmountBorrowed) {\n uint256 totalRepayAmount = currentBorrowed - newAmountBorrowed;\n\n if (boolParams.isFlashMintActive) {\n totalRepayAmount = totalRepayAmount - _leverDownFlashLoan(totalRepayAmount, currentBorrowed);\n }\n\n uint256 _maxCollatRatio = maxCollatRatio;\n\n // in case the flashloan didn't repay the entire amount we have to repay it \"manually\"\n // by withdrawing a bit of collateral and then repaying the debt with it\n for (uint8 i = 0; i < maxIterations && totalRepayAmount > minWant; i++) {\n _withdrawExcessCollateral(_maxCollatRatio, 0, 0);\n uint256 toRepay = totalRepayAmount;\n uint256 wantBalance = _balanceOfWant();\n if (toRepay > wantBalance) {\n toRepay = wantBalance;\n }\n uint256 repaid = _repayWant(toRepay);\n totalRepayAmount = totalRepayAmount - repaid;\n }\n (deposits, currentBorrowed) = getCurrentPosition();\n }\n\n // Deposit back to get `targetCollatRatio` (we always need to leave this in this ratio)\n uint256 _targetCollatRatio = targetCollatRatio;\n uint256 targetDeposit = _getDepositFromBorrow(currentBorrowed, _targetCollatRatio, deposits);\n if (targetDeposit > deposits) {\n uint256 toDeposit = targetDeposit - deposits;\n if (toDeposit > minWant) {\n _depositCollateral(Math.min(toDeposit, _balanceOfWant()));\n }\n } else {\n if (deposits - targetDeposit > minWant) {\n _withdrawExcessCollateral(_targetCollatRatio, deposits, currentBorrowed);\n }\n }\n }\n\n /// @notice Use a flashloan to reduce our exposure in `want` on Aave\n /// @param amount Amount we will need to withdraw and repay to Aave\n /// @return amount Actual amount repaid\n /// @dev Amount returned should equal `amount` but can be lower if we try to flashloan more than `maxFlashLoan` authorized\n /// @dev `amount` will be withdrawn from deposits and then used to repay borrows\n function _leverDownFlashLoan(uint256 amount, uint256 borrows) internal returns (uint256) {\n if (amount <= minWant) return 0;\n if (amount > borrows) {\n amount = borrows;\n }\n return FlashMintLib.doFlashMint(true, amount, address(want), daiBorrowCollatRatio, 0);\n }\n\n /// @notice Adjusts the deposits based on the wanted collateral ratio (does not touch the borrow)\n /// @param collatRatio Collateral ratio to target\n function _withdrawExcessCollateral(\n uint256 collatRatio,\n uint256 deposits,\n uint256 borrows\n ) internal returns (uint256 amount) {\n if (deposits == 0 && borrows == 0) (deposits, borrows) = getCurrentPosition();\n uint256 theoDeposits = _getDepositFromBorrow(borrows, collatRatio, deposits);\n if (deposits > theoDeposits) {\n uint256 toWithdraw = deposits - theoDeposits;\n return _withdrawCollateral(toWithdraw);\n }\n }\n\n /// @notice Deposit `want` tokens in Aave and start earning interests\n /// @param amount Amount to be deposited\n /// @return amount The amount deposited\n function _depositCollateral(uint256 amount) internal returns (uint256) {\n if (amount == 0) return 0;\n _lendingPool.deposit(address(want), amount, address(this), _referral);\n return amount;\n }\n\n /// @notice Withdraw `want` tokens from Aave\n /// @param amount Amount to be withdrawn\n /// @return amount The amount withdrawn\n function _withdrawCollateral(uint256 amount) internal returns (uint256) {\n if (amount == 0) return 0;\n _lendingPool.withdraw(address(want), amount, address(this));\n return amount;\n }\n\n /// @notice Repay what we borrowed of `want` from Aave\n /// @param amount Amount to repay\n /// @return amount The amount repaid\n /// @dev `interestRateMode` is set to variable rate (2)\n function _repayWant(uint256 amount) internal returns (uint256) {\n if (amount == 0) return 0;\n return _lendingPool.repay(address(want), amount, 2, address(this));\n }\n\n /// @notice Borrow `want` from Aave\n /// @param amount Amount of `want` we are borrowing\n /// @return amount The amount borrowed\n /// @dev The third variable is the `interestRateMode`\n /// @dev set at 2 which means we will get a variable interest rate on our borrowed tokens\n function _borrowWant(uint256 amount) internal returns (uint256) {\n _lendingPool.borrow(address(want), amount, 2, _referral, address(this));\n return amount;\n }\n\n /// @notice Computes the optimal collateral ratio based on current interests and incentives on Aave\n /// @notice It modifies the state by updating the `targetCollatRatio`\n function _computeOptimalCollatRatio(\n uint256 balanceExcludingRewards,\n uint256 deposits,\n uint256 currentBorrowed,\n uint256 guessedBorrow\n ) internal returns (uint256) {\n uint256 borrow = _computeMostProfitableBorrow(\n balanceExcludingRewards,\n deposits,\n currentBorrowed,\n guessedBorrow\n );\n uint256 _collatRatio = _getCollatRatio(balanceExcludingRewards + borrow, borrow);\n uint256 _maxCollatRatio = maxCollatRatio;\n if (_collatRatio > _maxCollatRatio) {\n _collatRatio = _maxCollatRatio;\n }\n targetCollatRatio = _collatRatio;\n return _collatRatio;\n }\n\n /// @notice Approve `spender` maxuint of `token`\n /// @param token Address of token to approve\n /// @param spender Address of spender to approve\n function _approveMaxSpend(address token, address spender) internal {\n IERC20(token).safeApprove(spender, type(uint256).max);\n }\n\n /// @notice Internal version of the `_setAavePoolVariables`\n function _setAavePoolVariables() internal {\n (, , , , uint256 reserveFactor_, , , , , ) = _protocolDataProvider.getReserveConfigurationData(address(want));\n cooldownSeconds = IStakedAave(_stkAave).COOLDOWN_SECONDS();\n unstakeWindow = IStakedAave(_stkAave).UNSTAKE_WINDOW();\n reserveFactor = int256(reserveFactor_ * 10**23);\n slope1 = int256(_interestRateStrategyAddress.variableRateSlope1());\n slope2 = int256(_interestRateStrategyAddress.variableRateSlope2());\n r0 = int256(_interestRateStrategyAddress.baseVariableBorrowRate());\n uOptimal = int256(_interestRateStrategyAddress.OPTIMAL_UTILIZATION_RATE());\n }\n\n // ========================= Internal View Functions ===========================\n\n /// @notice Computes the optimal amounts to borrow based on current interest rates and incentives\n /// @dev Returns optimal `borrow` amount in base of `want`\n function _computeMostProfitableBorrow(\n uint256 balanceExcludingRewards,\n uint256 deposits,\n uint256 currentBorrow,\n uint256 guessedBorrow\n ) internal view returns (uint256 borrow) {\n // This works if `wantBase < 10**27` which we should expect to be very the case for the strategies we are\n // launching at the moment\n uint256 normalizationFactor = 10**27 / wantBase;\n\n ComputeProfitability.SCalculateBorrow memory parameters;\n\n {\n (\n uint256 availableLiquidity,\n uint256 totalStableDebt,\n uint256 totalVariableDebt,\n ,\n ,\n ,\n uint256 averageStableBorrowRate,\n ,\n ,\n\n ) = _protocolDataProvider.getReserveData(address(want));\n\n parameters = ComputeProfitability.SCalculateBorrow({\n reserveFactor: reserveFactor,\n totalStableDebt: int256(totalStableDebt * normalizationFactor),\n totalVariableDebt: int256((totalVariableDebt - currentBorrow) * normalizationFactor),\n totalDeposits: int256(\n (availableLiquidity +\n totalStableDebt +\n totalVariableDebt +\n // to adapt to our future balance\n // add the wantBalance and remove the currentBorrowed from the optimisation\n balanceExcludingRewards -\n deposits) * normalizationFactor\n ),\n stableBorrowRate: int256(averageStableBorrowRate),\n rewardDeposit: 0,\n rewardBorrow: 0,\n strategyAssets: int256(balanceExcludingRewards * normalizationFactor),\n guessedBorrowAssets: int256(guessedBorrow * normalizationFactor),\n slope1: slope1,\n slope2: slope2,\n r0: r0,\n uOptimal: uOptimal\n });\n }\n\n {\n uint256 stkAavePriceInWant = _estimatedStkAaveToWant(1 ether);\n\n (uint256 emissionPerSecondAToken, , ) = _incentivesController.assets(address(_aToken));\n (uint256 emissionPerSecondDebtToken, , ) = _incentivesController.assets(address(_debtToken));\n\n parameters.rewardDeposit = int256(\n (emissionPerSecondAToken * 86400 * 365 * stkAavePriceInWant * 10**9) / wantBase\n );\n parameters.rewardBorrow = int256(\n (emissionPerSecondDebtToken * 86400 * 365 * stkAavePriceInWant * 10**9) / wantBase\n );\n }\n\n borrow = uint256(ComputeProfitability.computeProfitability(parameters)) / normalizationFactor;\n }\n\n function estimatedAPR() public view returns (uint256) {\n (\n ,\n ,\n uint256 totalVariableDebt,\n uint256 liquidityRate,\n uint256 variableBorrowRate,\n ,\n ,\n ,\n ,\n\n ) = _protocolDataProvider.getReserveData(address(want));\n (uint256 deposits, uint256 borrows) = getCurrentPosition();\n uint256 yearlyRewardsATokenInUSDC;\n uint256 yearlyRewardsDebtTokenInUSDC;\n {\n uint256 stkAavePriceInWant = _estimatedStkAaveToWant(1 ether);\n (uint256 emissionPerSecondAToken, , ) = (_aToken.getIncentivesController()).assets(address(_aToken));\n (uint256 emissionPerSecondDebtToken, , ) = (_debtToken.getIncentivesController()).assets(\n address(_debtToken)\n );\n\n uint256 yearlyEmissionsAToken = emissionPerSecondAToken * 60 * 60 * 24 * 365; // BASE: 18\n uint256 yearlyEmissionsDebtToken = emissionPerSecondDebtToken * 60 * 60 * 24 * 365; // BASE: 18\n yearlyRewardsATokenInUSDC = ((deposits * yearlyEmissionsAToken * stkAavePriceInWant * 10**9) /\n _aToken.totalSupply()); // BASE 27 + want\n yearlyRewardsDebtTokenInUSDC = ((borrows * yearlyEmissionsDebtToken * stkAavePriceInWant * 10**9) /\n totalVariableDebt); // BASE 27 + want\n }\n\n uint256 _totalAssets = _balanceOfWant() + _balanceOfAToken() - _balanceOfDebtToken();\n return\n (liquidityRate *\n deposits +\n yearlyRewardsATokenInUSDC +\n yearlyRewardsDebtTokenInUSDC -\n variableBorrowRate *\n borrows) /\n _totalAssets /\n 10**18; // BASE 9\n }\n\n /// @notice Returns the `want` balance\n function _balanceOfWant() internal view returns (uint256) {\n return want.balanceOf(address(this));\n }\n\n /// @notice Returns the `aToken` balance\n function _balanceOfAToken() internal view returns (uint256) {\n return _aToken.balanceOf(address(this));\n }\n\n /// @notice Returns the `debtToken` balance\n function _balanceOfDebtToken() internal view returns (uint256) {\n return _debtToken.balanceOf(address(this));\n }\n\n /// @notice Returns the `AAVE` balance\n function _balanceOfAave() internal view returns (uint256) {\n return IERC20(_aave).balanceOf(address(this));\n }\n\n /// @notice Returns the `StkAAVE` balance\n function _balanceOfStkAave() internal view returns (uint256) {\n return IERC20(address(_stkAave)).balanceOf(address(this));\n }\n\n /// @notice Estimate the amount of `want` we will get out by swapping it for AAVE\n /// @param amount Amount of AAVE we want to exchange (in base 18)\n /// @return amount Amount of `want` we are getting. We include a discount to account for slippage equal to 9000\n /// @dev Uses Chainlink spot price. Return value will be in base of `want` (6 for USDC)\n function _estimatedStkAaveToWant(uint256 amount) internal view returns (uint256) {\n (, int256 aavePriceUSD, , , ) = _chainlinkOracle.latestRoundData(); // stkAavePriceUSD is in base 8\n // `aavePriceUSD` is in base 8, and the discount factor is in base 4, so ultimately we need to divide\n // by `1e(18+8+4)\n return (uint256(aavePriceUSD) * amount * wantBase * discountFactor) / 1e30;\n }\n\n /// @notice Verifies the cooldown status for earned stkAAVE\n /// @return cooldownStatus Status of the coolDown: if it is 0 then there is no cooldown Status, if it is 1 then\n /// the strategy should claim\n function _checkCooldown() internal view returns (uint256 cooldownStatus) {\n uint256 cooldownStartTimestamp = IStakedAave(_stkAave).stakersCooldowns(address(this));\n uint256 nextClaimStartTimestamp = cooldownStartTimestamp + cooldownSeconds;\n if (cooldownStartTimestamp == 0) {\n return 0;\n }\n if (block.timestamp > nextClaimStartTimestamp && block.timestamp <= nextClaimStartTimestamp + unstakeWindow) {\n return 1;\n }\n if (block.timestamp < nextClaimStartTimestamp) {\n return 2;\n }\n }\n\n /// @notice Get the deposit and debt token for our `want` token\n function _getAaveAssets() internal view returns (address[] memory assets) {\n assets = new address[](2);\n assets[0] = address(_aToken);\n assets[1] = address(_debtToken);\n }\n\n /// @notice Get Aave ratios for a token in order to compute later our collateral ratio\n /// @param token Address of the token for which to check the ratios (usually `want` token)\n /// @dev `getReserveConfigurationData` returns values in base 4. So here `ltv` and `liquidationThreshold` are returned in base 18\n function _getProtocolCollatRatios(address token) internal view returns (uint256 ltv, uint256 liquidationThreshold) {\n (, ltv, liquidationThreshold, , , , , , , ) = _protocolDataProvider.getReserveConfigurationData(token);\n // convert bps to wad\n ltv = ltv * _BPS_WAD_RATIO;\n liquidationThreshold = liquidationThreshold * _BPS_WAD_RATIO;\n }\n\n // ========================= Internal Pure Functions ===========================\n\n /// @notice Get target borrow amount based on deposit and collateral ratio\n /// @param deposit Current total deposited on Aave\n /// @param collatRatio Collateral ratio to target\n function _getBorrowFromDeposit(uint256 deposit, uint256 collatRatio) internal pure returns (uint256) {\n return (deposit * collatRatio) / _COLLATERAL_RATIO_PRECISION;\n }\n\n /// @notice Get target deposit amount based on borrow and collateral ratio\n /// @param borrow Current total borrowed on Aave\n /// @param collatRatio Collateral ratio to target\n /// @param deposits Current deposit amount: this is what the function should return if the `collatRatio` is null\n function _getDepositFromBorrow(\n uint256 borrow,\n uint256 collatRatio,\n uint256 deposits\n ) internal pure returns (uint256) {\n if (collatRatio > 0) return (borrow * _COLLATERAL_RATIO_PRECISION) / collatRatio;\n else return deposits;\n }\n\n /// @notice Get target borrow amount based on supply (deposits - borrow) and collateral ratio\n /// @param supply = deposits - borrows. The supply is what is \"actually\" deposited in Aave\n /// @param collatRatio Collateral ratio to target\n function _getBorrowFromSupply(uint256 supply, uint256 collatRatio) internal pure returns (uint256) {\n return (supply * collatRatio) / (_COLLATERAL_RATIO_PRECISION - collatRatio);\n }\n\n /// @notice Computes the position collateral ratio from deposits and borrows\n function _getCollatRatio(uint256 deposits, uint256 borrows) internal pure returns (uint256 currentCollatRatio) {\n if (deposits > 0) {\n currentCollatRatio = (borrows * _COLLATERAL_RATIO_PRECISION) / deposits;\n }\n }\n\n /// @notice Processes 1Inch revert messages\n function _revertBytes(bytes memory errMsg) internal pure {\n if (errMsg.length > 0) {\n //solhint-disable-next-line\n assembly {\n revert(add(32, errMsg), mload(errMsg))\n }\n }\n revert(\"117\");\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashBorrower.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC3156 FlashBorrower, as defined in\n * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].\n *\n * _Available since v4.1._\n */\ninterface IERC3156FlashBorrower {\n /**\n * @dev Receive a flash loan.\n * @param initiator The initiator of the loan.\n * @param token The loan currency.\n * @param amount The amount of tokens lent.\n * @param fee The additional amount of tokens to repay.\n * @param data Arbitrary data structure, intended to contain user-defined parameters.\n * @return The keccak256 hash of \"ERC3156FlashBorrower.onFlashLoan\"\n */\n function onFlashLoan(\n address initiator,\n address token,\n uint256 amount,\n uint256 fee,\n bytes calldata data\n ) external returns (bytes32);\n}\n" + }, + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "contracts/strategies/AaveFlashloanStrategy/AaveLibraries.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.7;\n\nimport { IAToken, IProtocolDataProvider, IProtocolDataProvider, ILendingPool, IPriceOracle, IOptionalERC20 } from \"./AaveInterfaces.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary DataTypes {\n // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.\n struct ReserveData {\n //stores the reserve configuration\n ReserveConfigurationMap configuration;\n //the liquidity index. Expressed in ray\n uint128 liquidityIndex;\n //variable borrow index. Expressed in ray\n uint128 variableBorrowIndex;\n //the current supply rate. Expressed in ray\n uint128 currentLiquidityRate;\n //the current variable borrow rate. Expressed in ray\n uint128 currentVariableBorrowRate;\n //the current stable borrow rate. Expressed in ray\n uint128 currentStableBorrowRate;\n uint40 lastUpdateTimestamp;\n //tokens addresses\n address aTokenAddress;\n address stableDebtTokenAddress;\n address variableDebtTokenAddress;\n //address of the interest rate strategy\n address interestRateStrategyAddress;\n //the id of the reserve. Represents the position in the list of the active reserves\n uint8 id;\n }\n\n struct ReserveConfigurationMap {\n //bit 0-15: LTV\n //bit 16-31: Liq. threshold\n //bit 32-47: Liq. bonus\n //bit 48-55: Decimals\n //bit 56: Reserve is active\n //bit 57: reserve is frozen\n //bit 58: borrowing is enabled\n //bit 59: stable rate borrowing enabled\n //bit 60-63: reserved\n //bit 64-79: reserve factor\n uint256 data;\n }\n\n struct UserConfigurationMap {\n uint256 data;\n }\n\n enum InterestRateMode {\n NONE,\n STABLE,\n VARIABLE\n }\n}\n\nlibrary FlashMintLib {\n event Leverage(\n uint256 amountRequested,\n uint256 amountUsed,\n uint256 requiredDAI,\n uint256 amountToCloseLTVGap,\n bool deficit,\n address flashLoan\n );\n\n address public constant LENDER = 0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853;\n uint256 private constant _DAI_DECIMALS = 1e18;\n uint256 private constant _COLLAT_RATIO_PRECISION = 1 ether;\n address private constant _WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n address private constant _DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n IAToken public constant ADAI = IAToken(0x028171bCA77440897B824Ca71D1c56caC55b68A3);\n IProtocolDataProvider private constant _protocolDataProvider =\n IProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d);\n ILendingPool private constant _lendingPool = ILendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9);\n\n bytes32 public constant CALLBACK_SUCCESS = keccak256(\"ERC3156FlashBorrower.onFlashLoan\");\n\n uint16 private constant _referral = 0; // TODO: get our own referral code\n\n uint256 private constant _RAY = 10**27;\n\n function doFlashMint(\n bool deficit,\n uint256 amountDesired,\n address token,\n uint256 collatRatioDAI,\n uint256 depositToCloseLTVGap\n ) public returns (uint256 amount) {\n if (amountDesired == 0) {\n return 0;\n }\n amount = amountDesired;\n address dai = _DAI;\n\n // calculate amount of dai we need\n uint256 requiredDAI;\n {\n requiredDAI = (toDAI(amount, token) * _COLLAT_RATIO_PRECISION) / collatRatioDAI;\n\n uint256 requiredDAIToCloseLTVGap = 0;\n if (depositToCloseLTVGap > 0) {\n requiredDAIToCloseLTVGap = toDAI(depositToCloseLTVGap, token);\n requiredDAI = requiredDAI + requiredDAIToCloseLTVGap;\n }\n\n uint256 _maxLiquidity = maxLiquidity();\n\n /*\n When depositing/withdrawing in the `lendingPool` the amounts are scaled by a `liquidityIndex` and rounded with the functions rayDiv and rayMul (in the aDAI contract)\n Weirdly, 2 different indexes are used: `liquidityIndex` is used when depositing and `getReserveNormalizedIncome` when withdrawing\n Therefore, we need to round `requiredDAI`, or we may get some rounding errors and revert\n because the amount we try to withdraw (to pay back the flashloan) is not equal to the amount deposited\n */\n uint256 liquidityIndex = _lendingPool.getReserveData(dai).liquidityIndex;\n uint256 getReserveNormalizedIncome = _lendingPool.getReserveNormalizedIncome(dai);\n uint256 rayDiv = ((requiredDAI * _RAY + liquidityIndex / 2) / liquidityIndex);\n requiredDAI = (rayDiv * getReserveNormalizedIncome + (_RAY / 2)) / _RAY;\n\n if (requiredDAI > _maxLiquidity) {\n requiredDAI = (_maxLiquidity * _RAY - (_RAY / 2)) / getReserveNormalizedIncome;\n requiredDAI = (requiredDAI * liquidityIndex - liquidityIndex / 2) / _RAY;\n\n // NOTE: if we cap amountDAI, we reduce amountToken we are taking too\n amount =\n (fromDAI(requiredDAI - requiredDAIToCloseLTVGap, token) * collatRatioDAI) /\n _COLLAT_RATIO_PRECISION;\n }\n }\n\n bytes memory data = abi.encode(deficit, amount);\n uint256 _fee = IERC3156FlashLender(LENDER).flashFee(dai, requiredDAI);\n // Check that fees have not been increased without us knowing\n require(_fee == 0);\n uint256 _allowance = IERC20(dai).allowance(address(this), address(LENDER));\n if (_allowance < requiredDAI) {\n IERC20(dai).approve(address(LENDER), 0);\n IERC20(dai).approve(address(LENDER), type(uint256).max);\n }\n\n IERC3156FlashLender(LENDER).flashLoan(IERC3156FlashBorrower(address(this)), dai, requiredDAI, data);\n\n emit Leverage(amountDesired, amount, requiredDAI, depositToCloseLTVGap, deficit, LENDER);\n\n return amount; // we need to return the amount of Token we have changed our position in\n }\n\n function loanLogic(\n bool deficit,\n uint256 amount,\n uint256 amountFlashmint,\n address want\n ) public returns (bytes32) {\n address dai = _DAI;\n bool isDai = (want == dai);\n\n ILendingPool lp = _lendingPool;\n\n if (isDai) {\n if (deficit) {\n lp.deposit(dai, amountFlashmint - amount, address(this), _referral);\n lp.repay(dai, IERC20(dai).balanceOf(address(this)), 2, address(this));\n lp.withdraw(dai, amountFlashmint, address(this));\n } else {\n lp.deposit(dai, IERC20(dai).balanceOf(address(this)), address(this), _referral);\n lp.borrow(dai, amount, 2, _referral, address(this));\n lp.withdraw(dai, amountFlashmint - amount, address(this));\n }\n } else {\n // 1. Deposit DAI in Aave as collateral\n lp.deposit(dai, amountFlashmint, address(this), _referral);\n\n if (deficit) {\n // 2a. if in deficit withdraw amount and repay it\n lp.withdraw(want, amount, address(this));\n lp.repay(want, IERC20(want).balanceOf(address(this)), 2, address(this));\n } else {\n // 2b. if levering up borrow and deposit\n lp.borrow(want, amount, 2, _referral, address(this));\n lp.deposit(want, IERC20(want).balanceOf(address(this)), address(this), _referral);\n }\n // 3. Withdraw DAI\n lp.withdraw(dai, amountFlashmint, address(this));\n }\n\n return CALLBACK_SUCCESS;\n }\n\n function priceOracle() internal view returns (IPriceOracle) {\n return IPriceOracle(_protocolDataProvider.ADDRESSES_PROVIDER().getPriceOracle());\n }\n\n function toDAI(uint256 _amount, address asset) internal view returns (uint256) {\n address dai = _DAI;\n if (_amount == 0 || _amount == type(uint256).max || asset == dai) {\n return _amount;\n }\n\n if (asset == _WETH) {\n return\n (_amount * (uint256(10)**uint256(IOptionalERC20(dai).decimals()))) / priceOracle().getAssetPrice(dai);\n }\n\n address[] memory tokens = new address[](2);\n tokens[0] = asset;\n tokens[1] = dai;\n uint256[] memory prices = priceOracle().getAssetsPrices(tokens);\n\n uint256 ethPrice = (_amount * prices[0]) / (uint256(10)**uint256(IOptionalERC20(asset).decimals()));\n return (ethPrice * _DAI_DECIMALS) / prices[1];\n }\n\n function fromDAI(uint256 _amount, address asset) internal view returns (uint256) {\n address dai = _DAI;\n if (_amount == 0 || _amount == type(uint256).max || asset == dai) {\n return _amount;\n }\n\n if (asset == _WETH) {\n return\n (_amount * priceOracle().getAssetPrice(dai)) / (uint256(10)**uint256(IOptionalERC20(dai).decimals()));\n }\n\n address[] memory tokens = new address[](2);\n tokens[0] = asset;\n tokens[1] = dai;\n uint256[] memory prices = priceOracle().getAssetsPrices(tokens);\n\n uint256 ethPrice = (_amount * prices[1]) / _DAI_DECIMALS;\n\n return (ethPrice * (uint256(10)**uint256(IOptionalERC20(asset).decimals()))) / prices[0];\n }\n\n function maxLiquidity() public view returns (uint256) {\n return IERC3156FlashLender(LENDER).maxFlashLoan(_DAI);\n }\n}\n" + }, + "contracts/strategies/AaveFlashloanStrategy/AaveInterfaces.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.7;\n\nimport { DataTypes } from \"./AaveLibraries.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IAaveIncentivesController {\n /**\n * @dev Returns the total of rewards of an user, already accrued + not yet accrued\n * @param user The address of the user\n * @return The rewards\n **/\n function getRewardsBalance(address[] calldata assets, address user) external view returns (uint256);\n\n /**\n * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards\n * @param amount Amount of rewards to claim\n * @param to Address that will be receiving the rewards\n * @return Rewards claimed\n **/\n function claimRewards(\n address[] calldata assets,\n uint256 amount,\n address to\n ) external returns (uint256);\n\n /**\n * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must\n * be whitelisted via \"allowClaimOnBehalf\" function by the RewardsAdmin role manager\n * @param amount Amount of rewards to claim\n * @param user Address to check and claim rewards\n * @param to Address that will be receiving the rewards\n * @return Rewards claimed\n **/\n function claimRewardsOnBehalf(\n address[] calldata assets,\n uint256 amount,\n address user,\n address to\n ) external returns (uint256);\n\n /**\n * @dev returns the unclaimed rewards of the user\n * @param user the address of the user\n * @return the unclaimed user rewards\n */\n function getUserUnclaimedRewards(address user) external view returns (uint256);\n\n /**\n * @dev for backward compatibility with previous implementation of the Incentives controller\n */\n function REWARD_TOKEN() external view returns (address);\n\n function getDistributionEnd() external view returns (uint256);\n\n function getAssetData(address asset)\n external\n view\n returns (\n uint256,\n uint256,\n uint256\n );\n\n function assets(address asset)\n external\n view\n returns (\n uint256 emissionPerSecond,\n uint256 index,\n uint256 lastUpdateTimestamp\n );\n\n function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) external;\n}\n\ninterface ILendingPool {\n /**\n * @dev Emitted on deposit()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address initiating the deposit\n * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens\n * @param amount The amount deposited\n * @param referral The referral code used\n **/\n event Deposit(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint16 indexed referral\n );\n\n /**\n * @dev Emitted on withdraw()\n * @param reserve The address of the underlyng asset being withdrawn\n * @param user The address initiating the withdrawal, owner of aTokens\n * @param to Address that will receive the underlying\n * @param amount The amount to be withdrawn\n **/\n event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);\n\n /**\n * @dev Emitted on borrow() and flashLoan() when debt needs to be opened\n * @param reserve The address of the underlying asset being borrowed\n * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just\n * initiator of the transaction on flashLoan()\n * @param onBehalfOf The address that will be getting the debt\n * @param amount The amount borrowed out\n * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable\n * @param borrowRate The numeric rate at which the user has borrowed\n * @param referral The referral code used\n **/\n event Borrow(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint256 borrowRateMode,\n uint256 borrowRate,\n uint16 indexed referral\n );\n\n /**\n * @dev Emitted on repay()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The beneficiary of the repayment, getting his debt reduced\n * @param repayer The address of the user initiating the repay(), providing the funds\n * @param amount The amount repaid\n **/\n event Repay(address indexed reserve, address indexed user, address indexed repayer, uint256 amount);\n\n /**\n * @dev Emitted on swapBorrowRateMode()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user swapping his rate mode\n * @param rateMode The rate mode that the user wants to swap to\n **/\n event Swap(address indexed reserve, address indexed user, uint256 rateMode);\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n **/\n event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n **/\n event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);\n\n /**\n * @dev Emitted on rebalanceStableBorrowRate()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user for which the rebalance has been executed\n **/\n event RebalanceStableBorrowRate(address indexed reserve, address indexed user);\n\n /**\n * @dev Emitted on flashLoan()\n * @param target The address of the flash loan receiver contract\n * @param initiator The address initiating the flash loan\n * @param asset The address of the asset being flash borrowed\n * @param amount The amount flash borrowed\n * @param premium The fee flash borrowed\n * @param referralCode The referral code used\n **/\n event FlashLoan(\n address indexed target,\n address indexed initiator,\n address indexed asset,\n uint256 amount,\n uint256 premium,\n uint16 referralCode\n );\n\n /**\n * @dev Emitted when the pause is triggered.\n */\n event Paused();\n\n /**\n * @dev Emitted when the pause is lifted.\n */\n event Unpaused();\n\n /**\n * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via\n * LendingPoolCollateral manager using a DELEGATECALL\n * This allows to have the events in the generated ABI for LendingPool.\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator\n * @param liquidator The address of the liquidator\n * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n **/\n event LiquidationCall(\n address indexed collateralAsset,\n address indexed debtAsset,\n address indexed user,\n uint256 debtToCover,\n uint256 liquidatedCollateralAmount,\n address liquidator,\n bool receiveAToken\n );\n\n /**\n * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared\n * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,\n * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it\n * gets added to the LendingPool ABI\n * @param reserve The address of the underlying asset of the reserve\n * @param liquidityRate The new liquidity rate\n * @param stableBorrowRate The new stable borrow rate\n * @param variableBorrowRate The new variable borrow rate\n * @param liquidityIndex The new liquidity index\n * @param variableBorrowIndex The new variable borrow index\n **/\n event ReserveDataUpdated(\n address indexed reserve,\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex\n );\n\n /**\n * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User deposits 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to deposit\n * @param amount The amount to be deposited\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to Address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n **/\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external returns (uint256);\n\n /**\n * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower\n * already deposited enough collateral, or he was given enough allowance by a credit delegator on the\n * corresponding debt token (StableDebtToken or VariableDebtToken)\n * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet\n * and 100 stable/variable debt tokens, depending on the `interestRateMode`\n * @param asset The address of the underlying asset to borrow\n * @param amount The amount to be borrowed\n * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself\n * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator\n * if he has been given credit delegation allowance\n **/\n function borrow(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n uint16 referralCode,\n address onBehalfOf\n ) external;\n\n /**\n * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned\n * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\n * other borrower whose debt should be removed\n * @return The final amount repaid\n **/\n function repay(\n address asset,\n uint256 amount,\n uint256 rateMode,\n address onBehalfOf\n ) external returns (uint256);\n\n /**\n * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa\n * @param asset The address of the underlying asset borrowed\n * @param rateMode The rate mode that the user wants to swap to\n **/\n function swapBorrowRateMode(address asset, uint256 rateMode) external;\n\n /**\n * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.\n * - Users can be rebalanced if the following conditions are satisfied:\n * 1. Usage ratio is above 95%\n * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been\n * borrowed at a stable rate and depositors are not earning enough\n * @param asset The address of the underlying asset borrowed\n * @param user The address of the user to be rebalanced\n **/\n function rebalanceStableBorrowRate(address asset, address user) external;\n\n /**\n * @dev Allows depositors to enable/disable a specific deposited asset as collateral\n * @param asset The address of the underlying asset deposited\n * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise\n **/\n function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;\n\n /**\n * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1\n * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives\n * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n **/\n function liquidationCall(\n address collateralAsset,\n address debtAsset,\n address user,\n uint256 debtToCover,\n bool receiveAToken\n ) external;\n\n /**\n * @dev Allows smartcontracts to access the liquidity of the pool within one transaction,\n * as long as the amount taken plus a fee is returned.\n * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.\n * For further details please visit https://developers.aave.com\n * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface\n * @param assets The addresses of the assets being flash-borrowed\n * @param amounts The amounts amounts being flash-borrowed\n * @param modes Types of the debt to open if the flash loan is not returned:\n * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver\n * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2\n * @param params Variadic packed params to pass to the receiver as extra information\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n **/\n function flashLoan(\n address receiverAddress,\n address[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata modes,\n address onBehalfOf,\n bytes calldata params,\n uint16 referralCode\n ) external;\n\n /**\n * @dev Returns the user account data across all the reserves\n * @param user The address of the user\n * @return totalCollateralETH the total collateral in ETH of the user\n * @return totalDebtETH the total debt in ETH of the user\n * @return availableBorrowsETH the borrowing power left of the user\n * @return currentLiquidationThreshold the liquidation threshold of the user\n * @return ltv the loan to value of the user\n * @return healthFactor the current health factor of the user\n **/\n function getUserAccountData(address user)\n external\n view\n returns (\n uint256 totalCollateralETH,\n uint256 totalDebtETH,\n uint256 availableBorrowsETH,\n uint256 currentLiquidationThreshold,\n uint256 ltv,\n uint256 healthFactor\n );\n\n function initReserve(\n address reserve,\n address aTokenAddress,\n address stableDebtAddress,\n address variableDebtAddress,\n address interestRateStrategyAddress\n ) external;\n\n function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external;\n\n function setConfiguration(address reserve, uint256 configuration) external;\n\n /**\n * @dev Returns the configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The configuration of the reserve\n **/\n function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory);\n\n /**\n * @dev Returns the configuration of the user across all the reserves\n * @param user The user address\n * @return The configuration of the user\n **/\n function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory);\n\n /**\n * @dev Returns the normalized income normalized income of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve's normalized income\n */\n function getReserveNormalizedIncome(address asset) external view returns (uint256);\n\n /**\n * @dev Returns the normalized variable debt per unit of asset\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve normalized variable debt\n */\n function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);\n\n /**\n * @dev Returns the state and configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The state of the reserve\n **/\n function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);\n\n function finalizeTransfer(\n address asset,\n address from,\n address to,\n uint256 amount,\n uint256 balanceFromAfter,\n uint256 balanceToBefore\n ) external;\n\n function getReservesList() external view returns (address[] memory);\n\n function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);\n\n function setPause(bool val) external;\n\n function paused() external view returns (bool);\n}\n\ninterface IProtocolDataProvider {\n struct TokenData {\n string symbol;\n address tokenAddress;\n }\n\n function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider);\n\n function getAllReservesTokens() external view returns (TokenData[] memory);\n\n function getAllATokens() external view returns (TokenData[] memory);\n\n function getReserveConfigurationData(address asset)\n external\n view\n returns (\n uint256 decimals,\n uint256 ltv,\n uint256 liquidationThreshold,\n uint256 liquidationBonus,\n uint256 reserveFactor,\n bool usageAsCollateralEnabled,\n bool borrowingEnabled,\n bool stableBorrowRateEnabled,\n bool isActive,\n bool isFrozen\n );\n\n function getReserveData(address asset)\n external\n view\n returns (\n uint256 availableLiquidity,\n uint256 totalStableDebt,\n uint256 totalVariableDebt,\n uint256 liquidityRate,\n uint256 variableBorrowRate,\n uint256 stableBorrowRate,\n uint256 averageStableBorrowRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex,\n uint40 lastUpdateTimestamp\n );\n\n function getUserReserveData(address asset, address user)\n external\n view\n returns (\n uint256 currentATokenBalance,\n uint256 currentStableDebt,\n uint256 currentVariableDebt,\n uint256 principalStableDebt,\n uint256 scaledVariableDebt,\n uint256 stableBorrowRate,\n uint256 liquidityRate,\n uint40 stableRateLastUpdated,\n bool usageAsCollateralEnabled\n );\n\n function getReserveTokensAddresses(address asset)\n external\n view\n returns (\n address aTokenAddress,\n address stableDebtTokenAddress,\n address variableDebtTokenAddress\n );\n}\n\ninterface IScaledBalanceToken {\n /**\n * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the\n * updated stored balance divided by the reserve's liquidity index at the moment of the update\n * @param user The user whose balance is calculated\n * @return The scaled balance of the user\n **/\n function scaledBalanceOf(address user) external view returns (uint256);\n\n /**\n * @dev Returns the scaled balance of the user and the scaled total supply.\n * @param user The address of the user\n * @return The scaled balance of the user\n * @return The scaled balance and the scaled total supply\n **/\n function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);\n\n /**\n * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)\n * @return The scaled total supply\n **/\n function scaledTotalSupply() external view returns (uint256);\n}\n\n/**\n * @title IVariableDebtToken\n * @author Aave\n * @notice Defines the basic interface for a variable debt token.\n **/\ninterface IVariableDebtToken is IERC20, IScaledBalanceToken {\n /**\n * @dev Emitted after the mint action\n * @param from The address performing the mint\n * @param onBehalfOf The address of the user on which behalf minting has been performed\n * @param value The amount to be minted\n * @param index The last index of the reserve\n **/\n event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index);\n\n /**\n * @dev Mints debt token to the `onBehalfOf` address\n * @param user The address receiving the borrowed underlying, being the delegatee in case\n * of credit delegate, or same as `onBehalfOf` otherwise\n * @param onBehalfOf The address receiving the debt tokens\n * @param amount The amount of debt being minted\n * @param index The variable debt index of the reserve\n * @return `true` if the the previous balance of the user is 0\n **/\n function mint(\n address user,\n address onBehalfOf,\n uint256 amount,\n uint256 index\n ) external returns (bool);\n\n /**\n * @dev Emitted when variable debt is burnt\n * @param user The user which debt has been burned\n * @param amount The amount of debt being burned\n * @param index The index of the user\n **/\n event Burn(address indexed user, uint256 amount, uint256 index);\n\n /**\n * @dev Burns user variable debt\n * @param user The user which debt is burnt\n * @param index The variable debt index of the reserve\n **/\n function burn(\n address user,\n uint256 amount,\n uint256 index\n ) external;\n\n /**\n * @dev Returns the address of the incentives controller contract\n **/\n function getIncentivesController() external view returns (IAaveIncentivesController);\n}\n\n/**\n * @title LendingPoolAddressesProvider contract\n * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles\n * - Acting also as factory of proxies and admin of those, so with right to change its implementations\n * - Owned by the Aave Governance\n * @author Aave\n **/\ninterface ILendingPoolAddressesProvider {\n event MarketIdSet(string newMarketId);\n event LendingPoolUpdated(address indexed newAddress);\n event ConfigurationAdminUpdated(address indexed newAddress);\n event EmergencyAdminUpdated(address indexed newAddress);\n event LendingPoolConfiguratorUpdated(address indexed newAddress);\n event LendingPoolCollateralManagerUpdated(address indexed newAddress);\n event PriceOracleUpdated(address indexed newAddress);\n event LendingRateOracleUpdated(address indexed newAddress);\n event ProxyCreated(bytes32 id, address indexed newAddress);\n event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);\n\n function getMarketId() external view returns (string memory);\n\n function setMarketId(string calldata marketId) external;\n\n function setAddress(bytes32 id, address newAddress) external;\n\n function setAddressAsProxy(bytes32 id, address impl) external;\n\n function getAddress(bytes32 id) external view returns (address);\n\n function getLendingPool() external view returns (address);\n\n function setLendingPoolImpl(address pool) external;\n\n function getLendingPoolConfigurator() external view returns (address);\n\n function setLendingPoolConfiguratorImpl(address configurator) external;\n\n function getLendingPoolCollateralManager() external view returns (address);\n\n function setLendingPoolCollateralManager(address manager) external;\n\n function getPoolAdmin() external view returns (address);\n\n function setPoolAdmin(address admin) external;\n\n function getEmergencyAdmin() external view returns (address);\n\n function setEmergencyAdmin(address admin) external;\n\n function getPriceOracle() external view returns (address);\n\n function setPriceOracle(address priceOracle) external;\n\n function getLendingRateOracle() external view returns (address);\n\n function setLendingRateOracle(address lendingRateOracle) external;\n}\n\ninterface IOptionalERC20 {\n function decimals() external view returns (uint8);\n}\n\ninterface IPriceOracle {\n function getAssetPrice(address _asset) external view returns (uint256);\n\n function getAssetsPrices(address[] calldata _assets) external view returns (uint256[] memory);\n\n function getSourceOfAsset(address _asset) external view returns (address);\n\n function getFallbackOracle() external view returns (address);\n}\n\ninterface IStakedAave is IERC20 {\n function stake(address to, uint256 amount) external;\n\n function redeem(address to, uint256 amount) external;\n\n function cooldown() external;\n\n function claimRewards(address to, uint256 amount) external;\n\n function getTotalRewardsBalance(address) external view returns (uint256);\n\n function COOLDOWN_SECONDS() external view returns (uint256);\n\n function stakersCooldowns(address) external view returns (uint256);\n\n function UNSTAKE_WINDOW() external view returns (uint256);\n}\n\n/**\n * @title IInitializableAToken\n * @notice Interface for the initialize function on AToken\n * @author Aave\n **/\ninterface IInitializableAToken {\n /**\n * @dev Emitted when an aToken is initialized\n * @param underlyingAsset The address of the underlying asset\n * @param pool The address of the associated lending pool\n * @param treasury The address of the treasury\n * @param incentivesController The address of the incentives controller for this aToken\n * @param aTokenDecimals the decimals of the underlying\n * @param aTokenName the name of the aToken\n * @param aTokenSymbol the symbol of the aToken\n * @param params A set of encoded parameters for additional initialization\n **/\n event Initialized(\n address indexed underlyingAsset,\n address indexed pool,\n address treasury,\n address incentivesController,\n uint8 aTokenDecimals,\n string aTokenName,\n string aTokenSymbol,\n bytes params\n );\n\n /**\n * @dev Initializes the aToken\n * @param pool The address of the lending pool where this aToken will be used\n * @param treasury The address of the Aave treasury, receiving the fees on this aToken\n * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)\n * @param incentivesController The smart contract managing potential incentives distribution\n * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's\n * @param aTokenName The name of the aToken\n * @param aTokenSymbol The symbol of the aToken\n */\n function initialize(\n ILendingPool pool,\n address treasury,\n address underlyingAsset,\n IAaveIncentivesController incentivesController,\n uint8 aTokenDecimals,\n string calldata aTokenName,\n string calldata aTokenSymbol,\n bytes calldata params\n ) external;\n}\n\ninterface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {\n /**\n * @dev Emitted after the mint action\n * @param from The address performing the mint\n * @param value The amount being\n * @param index The new liquidity index of the reserve\n **/\n event Mint(address indexed from, uint256 value, uint256 index);\n\n /**\n * @dev Mints `amount` aTokens to `user`\n * @param user The address receiving the minted tokens\n * @param amount The amount of tokens getting minted\n * @param index The new liquidity index of the reserve\n * @return `true` if the the previous balance of the user was 0\n */\n function mint(\n address user,\n uint256 amount,\n uint256 index\n ) external returns (bool);\n\n /**\n * @dev Emitted after aTokens are burned\n * @param from The owner of the aTokens, getting them burned\n * @param target The address that will receive the underlying\n * @param value The amount being burned\n * @param index The new liquidity index of the reserve\n **/\n event Burn(address indexed from, address indexed target, uint256 value, uint256 index);\n\n /**\n * @dev Emitted during the transfer action\n * @param from The user whose tokens are being transferred\n * @param to The recipient\n * @param value The amount being transferred\n * @param index The new liquidity index of the reserve\n **/\n event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);\n\n /**\n * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`\n * @param user The owner of the aTokens, getting them burned\n * @param receiverOfUnderlying The address that will receive the underlying\n * @param amount The amount being burned\n * @param index The new liquidity index of the reserve\n **/\n function burn(\n address user,\n address receiverOfUnderlying,\n uint256 amount,\n uint256 index\n ) external;\n\n /**\n * @dev Mints aTokens to the reserve treasury\n * @param amount The amount of tokens getting minted\n * @param index The new liquidity index of the reserve\n */\n function mintToTreasury(uint256 amount, uint256 index) external;\n\n /**\n * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken\n * @param from The address getting liquidated, current owner of the aTokens\n * @param to The recipient\n * @param value The amount of tokens getting transferred\n **/\n function transferOnLiquidation(\n address from,\n address to,\n uint256 value\n ) external;\n\n /**\n * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer\n * assets in borrow(), withdraw() and flashLoan()\n * @param user The recipient of the underlying\n * @param amount The amount getting transferred\n * @return The amount transferred\n **/\n function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);\n\n /**\n * @dev Invoked to execute actions on the aToken side after a repayment.\n * @param user The user executing the repayment\n * @param amount The amount getting repaid\n **/\n function handleRepayment(address user, uint256 amount) external;\n\n /**\n * @dev Returns the address of the incentives controller contract\n **/\n function getIncentivesController() external view returns (IAaveIncentivesController);\n\n /**\n * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)\n **/\n function UNDERLYING_ASSET_ADDRESS() external view returns (address);\n}\n\n/**\n * @title IReserveInterestRateStrategyInterface interface\n * @dev Interface for the calculation of the interest rates\n * @author Aave\n */\ninterface IReserveInterestRateStrategy {\n function baseVariableBorrowRate() external view returns (uint256);\n\n function getMaxVariableBorrowRate() external view returns (uint256);\n\n function stableRateSlope1() external view returns (uint256);\n\n function stableRateSlope2() external view returns (uint256);\n\n function variableRateSlope1() external view returns (uint256);\n\n function variableRateSlope2() external view returns (uint256);\n\n function OPTIMAL_UTILIZATION_RATE() external view returns (uint256);\n\n function calculateInterestRates(\n address reserve,\n uint256 availableLiquidity,\n uint256 totalStableDebt,\n uint256 totalVariableDebt,\n uint256 averageStableBorrowRate,\n uint256 reserveFactor\n )\n external\n view\n returns (\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate\n );\n\n function calculateInterestRates(\n address reserve,\n address aToken,\n uint256 liquidityAdded,\n uint256 liquidityTaken,\n uint256 totalStableDebt,\n uint256 totalVariableDebt,\n uint256 averageStableBorrowRate,\n uint256 reserveFactor\n )\n external\n view\n returns (\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate\n );\n}\n" + }, + "contracts/strategies/BaseStrategyUpgradeable.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"./BaseStrategyEvents.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\n/// @title BaseStrategyUpgradeable\n/// @author Forked from https://github.com/yearn/yearn-managers/blob/master/contracts/BaseStrategy.sol\n/// @notice `BaseStrategyUpgradeable` implements all of the required functionalities to interoperate\n/// with the `PoolManager` Contract.\n/// @dev This contract should be inherited and the abstract methods implemented to adapt the `Strategy`\n/// to the particular needs it has to create a return.\nabstract contract BaseStrategyUpgradeable is BaseStrategyEvents, AccessControlUpgradeable {\n using SafeERC20 for IERC20;\n\n uint256 public constant BASE = 10**18;\n uint256 public constant SECONDSPERYEAR = 31556952;\n\n /// @notice Role for `PoolManager` only\n bytes32 public constant POOLMANAGER_ROLE = keccak256(\"POOLMANAGER_ROLE\");\n /// @notice Role for guardians and governors\n bytes32 public constant GUARDIAN_ROLE = keccak256(\"GUARDIAN_ROLE\");\n /// @notice Role for keepers\n bytes32 public constant KEEPER_ROLE = keccak256(\"KEEPER_ROLE\");\n\n // ======================== References to contracts ============================\n\n /// @notice Reference to the protocol's collateral `PoolManager`\n IPoolManager public poolManager;\n\n /// @notice Reference to the ERC20 farmed by this strategy\n IERC20 public want;\n\n /// @notice Base of the ERC20 token farmed by this strategy\n uint256 public wantBase;\n\n // ============================ Parameters =====================================\n\n /// @notice Use this to adjust the threshold at which running a debt causes a\n /// harvest trigger. See `setDebtThreshold()` for more details\n uint256 public debtThreshold;\n\n /// @notice See note on `setEmergencyExit()`\n bool public emergencyExit;\n\n // ============================ Constructor ====================================\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() initializer {}\n\n /// @notice Constructor of the `BaseStrategyUpgradeable`\n /// @param _poolManager Address of the `PoolManager` lending collateral to this strategy\n /// @param governor Governor address of the protocol\n /// @param guardian Address of the guardian\n function _initialize(\n address _poolManager,\n address governor,\n address guardian,\n address[] memory keepers\n ) internal initializer {\n poolManager = IPoolManager(_poolManager);\n want = IERC20(poolManager.token());\n wantBase = 10**(IERC20Metadata(address(want)).decimals());\n require(guardian != address(0) && governor != address(0) && governor != guardian, \"0\");\n // AccessControl\n // Governor is guardian so no need for a governor role\n _setupRole(GUARDIAN_ROLE, guardian);\n _setupRole(GUARDIAN_ROLE, governor);\n _setupRole(POOLMANAGER_ROLE, address(_poolManager));\n _setRoleAdmin(POOLMANAGER_ROLE, POOLMANAGER_ROLE);\n _setRoleAdmin(GUARDIAN_ROLE, POOLMANAGER_ROLE);\n\n // Initializing roles first\n for (uint256 i = 0; i < keepers.length; i++) {\n require(keepers[i] != address(0), \"0\");\n _setupRole(KEEPER_ROLE, keepers[i]);\n }\n _setRoleAdmin(KEEPER_ROLE, GUARDIAN_ROLE);\n\n debtThreshold = 100 * BASE;\n emergencyExit = false;\n // Give `PoolManager` unlimited access (might save gas)\n want.safeIncreaseAllowance(address(poolManager), type(uint256).max);\n }\n\n // ========================== Core functions ===================================\n\n /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting\n /// the Strategy's position.\n function harvest() external {\n _report();\n // Check if free returns are left, and re-invest them\n _adjustPosition();\n }\n\n /// @notice Harvests the Strategy, recognizing any profits or losses and adjusting\n /// the Strategy's position.\n /// @param borrowInit Approximate optimal borrows to have faster convergence on the NR method\n function harvest(uint256 borrowInit) external onlyRole(KEEPER_ROLE) {\n _report();\n // Check if free returns are left, and re-invest them, gives an hint on the borrow amount to the NR method\n // to maximise revenue\n _adjustPosition(borrowInit);\n }\n\n /// @notice Withdraws `_amountNeeded` to `poolManager`.\n /// @param _amountNeeded How much `want` to withdraw.\n /// @return amountFreed How much `want` withdrawn.\n /// @return _loss Any realized losses\n /// @dev This may only be called by the `PoolManager`\n function withdraw(uint256 _amountNeeded)\n external\n onlyRole(POOLMANAGER_ROLE)\n returns (uint256 amountFreed, uint256 _loss)\n {\n // Liquidate as much as possible `want` (up to `_amountNeeded`)\n (amountFreed, _loss) = _liquidatePosition(_amountNeeded);\n // Send it directly back (NOTE: Using `msg.sender` saves some gas here)\n want.safeTransfer(msg.sender, amountFreed);\n // NOTE: Reinvest anything leftover on next `tend`/`harvest`\n }\n\n // ============================ View functions =================================\n\n /// @notice Provides an accurate estimate for the total amount of assets\n /// (principle + return) that this Strategy is currently managing,\n /// denominated in terms of `want` tokens.\n /// This total should be \"realizable\" e.g. the total value that could\n /// *actually* be obtained from this Strategy if it were to divest its\n /// entire position based on current on-chain conditions.\n /// @return The estimated total assets in this Strategy.\n /// @dev Care must be taken in using this function, since it relies on external\n /// systems, which could be manipulated by the attacker to give an inflated\n /// (or reduced) value produced by this function, based on current on-chain\n /// conditions (e.g. this function is possible to influence through\n /// flashloan attacks, oracle manipulations, or other DeFi attack\n /// mechanisms).\n function estimatedTotalAssets() public view virtual returns (uint256);\n\n /// @notice Provides an indication of whether this strategy is currently \"active\"\n /// in that it is managing an active position, or will manage a position in\n /// the future. This should correlate to `harvest()` activity, so that Harvest\n /// events can be tracked externally by indexing agents.\n /// @return True if the strategy is actively managing a position.\n function isActive() public view returns (bool) {\n return estimatedTotalAssets() > 0;\n }\n\n // ============================ Internal Functions =============================\n\n /// @notice PrepareReturn the Strategy, recognizing any profits or losses\n /// @dev In the rare case the Strategy is in emergency shutdown, this will exit\n /// the Strategy's position.\n /// @dev When `_report()` is called, the Strategy reports to the Manager (via\n /// `poolManager.report()`), so in some cases `harvest()` must be called in order\n /// to take in profits, to borrow newly available funds from the Manager, or\n /// otherwise adjust its position. In other cases `harvest()` must be\n /// called to report to the Manager on the Strategy's position, especially if\n /// any losses have occurred.\n /// @dev As keepers may directly profit from this function, there may be front-running problems with miners bots,\n /// we may have to put an access control logic for this function to only allow white-listed addresses to act\n /// as keepers for the protocol\n function _report() internal {\n uint256 profit = 0;\n uint256 loss = 0;\n uint256 debtOutstanding = poolManager.debtOutstanding();\n uint256 debtPayment = 0;\n if (emergencyExit) {\n // Free up as much capital as possible\n uint256 amountFreed = _liquidateAllPositions();\n if (amountFreed < debtOutstanding) {\n loss = debtOutstanding - amountFreed;\n } else if (amountFreed > debtOutstanding) {\n profit = amountFreed - debtOutstanding;\n }\n debtPayment = debtOutstanding - loss;\n } else {\n // Free up returns for Manager to pull\n (profit, loss, debtPayment) = _prepareReturn(debtOutstanding);\n }\n emit Harvested(profit, loss, debtPayment, debtOutstanding);\n\n // Allows Manager to take up to the \"harvested\" balance of this contract,\n // which is the amount it has earned since the last time it reported to\n // the Manager.\n poolManager.report(profit, loss, debtPayment);\n }\n\n /// @notice Performs any Strategy unwinding or other calls necessary to capture the\n /// \"free return\" this Strategy has generated since the last time its core\n /// position(s) were adjusted. Examples include unwrapping extra rewards.\n /// This call is only used during \"normal operation\" of a Strategy, and\n /// should be optimized to minimize losses as much as possible.\n ///\n /// This method returns any realized profits and/or realized losses\n /// incurred, and should return the total amounts of profits/losses/debt\n /// payments (in `want` tokens) for the Manager's accounting (e.g.\n /// `want.balanceOf(this) >= _debtPayment + _profit`).\n ///\n /// `_debtOutstanding` will be 0 if the Strategy is not past the configured\n /// debt limit, otherwise its value will be how far past the debt limit\n /// the Strategy is. The Strategy's debt limit is configured in the Manager.\n ///\n /// NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.\n /// It is okay for it to be less than `_debtOutstanding`, as that\n /// should only used as a guide for how much is left to pay back.\n /// Payments should be made to minimize loss from slippage, debt,\n /// withdrawal fees, etc.\n ///\n /// See `poolManager.debtOutstanding()`.\n function _prepareReturn(uint256 _debtOutstanding)\n internal\n virtual\n returns (\n uint256 _profit,\n uint256 _loss,\n uint256 _debtPayment\n );\n\n /// @notice Performs any adjustments to the core position(s) of this Strategy given\n /// what change the Manager made in the \"investable capital\" available to the\n /// Strategy. Note that all \"free capital\" in the Strategy after the report\n /// was made is available for reinvestment. Also note that this number\n /// could be 0, and you should handle that scenario accordingly.\n function _adjustPosition() internal virtual;\n\n /// @notice same as _adjustPosition but with an initial parameters\n function _adjustPosition(uint256) internal virtual;\n\n /// @notice Liquidates up to `_amountNeeded` of `want` of this strategy's positions,\n /// irregardless of slippage. Any excess will be re-invested with `_adjustPosition()`.\n /// This function should return the amount of `want` tokens made available by the\n /// liquidation. If there is a difference between them, `_loss` indicates whether the\n /// difference is due to a realized loss, or if there is some other sitution at play\n /// (e.g. locked funds) where the amount made available is less than what is needed.\n ///\n /// NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained\n function _liquidatePosition(uint256 _amountNeeded)\n internal\n virtual\n returns (uint256 _liquidatedAmount, uint256 _loss);\n\n /// @notice Liquidates everything and returns the amount that got freed.\n /// This function is used during emergency exit instead of `_prepareReturn()` to\n /// liquidate all of the Strategy's positions back to the Manager.\n function _liquidateAllPositions() internal virtual returns (uint256 _amountFreed);\n\n /// @notice Override this to add all tokens/tokenized positions this contract\n /// manages on a *persistent* basis (e.g. not just for swapping back to\n /// want ephemerally).\n ///\n /// NOTE: Do *not* include `want`, already included in `sweep` below.\n ///\n /// Example:\n /// ```\n /// function _protectedTokens() internal override view returns (address[] memory) {\n /// address[] memory protected = new address[](3);\n /// protected[0] = tokenA;\n /// protected[1] = tokenB;\n /// protected[2] = tokenC;\n /// return protected;\n /// }\n /// ```\n function _protectedTokens() internal view virtual returns (address[] memory);\n\n // ============================== Governance ===================================\n\n /// @notice Activates emergency exit. Once activated, the Strategy will exit its\n /// position upon the next harvest, depositing all funds into the Manager as\n /// quickly as is reasonable given on-chain conditions.\n /// @dev This may only be called by the `PoolManager`, because when calling this the `PoolManager` should at the same\n /// time update the debt ratio\n /// @dev This function can only be called once by the `PoolManager` contract\n /// @dev See `poolManager.setEmergencyExit()` and `harvest()` for further details.\n function setEmergencyExit() external onlyRole(POOLMANAGER_ROLE) {\n emergencyExit = true;\n emit EmergencyExitActivated();\n }\n\n /// @notice Sets how far the Strategy can go into loss without a harvest and report\n /// being required.\n /// @param _debtThreshold How big of a loss this Strategy may carry without\n /// @dev By default this is 0, meaning any losses would cause a harvest which\n /// will subsequently report the loss to the Manager for tracking.\n function setDebtThreshold(uint256 _debtThreshold) external onlyRole(GUARDIAN_ROLE) {\n debtThreshold = _debtThreshold;\n emit UpdatedDebtThreshold(_debtThreshold);\n }\n\n /// @notice Removes tokens from this Strategy that are not the type of tokens\n /// managed by this Strategy. This may be used in case of accidentally\n /// sending the wrong kind of token to this Strategy.\n ///\n /// Tokens will be sent to `governance()`.\n ///\n /// This will fail if an attempt is made to sweep `want`, or any tokens\n /// that are protected by this Strategy.\n ///\n /// This may only be called by governance.\n /// @param _token The token to transfer out of this `PoolManager`.\n /// @param to Address to send the tokens to.\n /// @dev\n /// Implement `_protectedTokens()` to specify any additional tokens that\n /// should be protected from sweeping in addition to `want`.\n function sweep(address _token, address to) external onlyRole(GUARDIAN_ROLE) {\n require(_token != address(want), \"93\");\n\n address[] memory __protectedTokens = _protectedTokens();\n for (uint256 i = 0; i < __protectedTokens.length; i++)\n // In the strategy we use so far, the only protectedToken is the want token\n // and this has been checked above\n require(_token != __protectedTokens[i], \"93\");\n\n IERC20(_token).safeTransfer(to, IERC20(_token).balanceOf(address(this)));\n }\n\n // ============================ Manager functions ==============================\n\n /// @notice Adds a new guardian address and echoes the change to the contracts\n /// that interact with this collateral `PoolManager`\n /// @param _guardian New guardian address\n /// @dev This internal function has to be put in this file because Access Control is not defined\n /// in PoolManagerInternal\n function addGuardian(address _guardian) external virtual;\n\n /// @notice Revokes the guardian role and propagates the change to other contracts\n /// @param guardian Old guardian address to revoke\n function revokeGuardian(address guardian) external virtual;\n}\n" + }, + "contracts/strategies/AaveFlashloanStrategy/ComputeProfitability.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.7;\n\n/// @title ComputeProfitability\n/// @author Angle Core Team\n/// @notice Helper contract to get the optimal borrow amount from a set of provided parameters from Aave\nlibrary ComputeProfitability {\n struct SCalculateBorrow {\n int256 reserveFactor;\n int256 totalStableDebt;\n int256 totalVariableDebt;\n int256 totalDeposits;\n int256 stableBorrowRate;\n int256 rewardDeposit;\n int256 rewardBorrow;\n int256 strategyAssets;\n int256 guessedBorrowAssets;\n int256 slope1;\n int256 slope2;\n int256 r0;\n int256 uOptimal;\n }\n\n int256 private constant _BASE_RAY = 10**27;\n\n /// @notice Computes the Aave utilization ratio\n function _computeUtilization(int256 borrow, SCalculateBorrow memory parameters) internal pure returns (int256) {\n return\n ((parameters.totalStableDebt + parameters.totalVariableDebt + borrow) * _BASE_RAY) /\n (parameters.totalDeposits + borrow);\n }\n\n /// @notice Computes the derivative of the utilization ratio with respect to the amount borrowed\n function _computeUprime(int256 borrow, SCalculateBorrow memory parameters) internal pure returns (int256) {\n return\n ((parameters.totalDeposits - parameters.totalStableDebt - parameters.totalVariableDebt) * _BASE_RAY) /\n (parameters.totalDeposits + borrow);\n }\n\n /// @notice Computes the value of the interest rate, its first and second order derivatives\n /// @dev The returned value is in `_BASE_RAY`\n function _calculateInterestPrimes(int256 borrow, SCalculateBorrow memory parameters)\n internal\n pure\n returns (\n int256 interest,\n int256 interestPrime,\n int256 interestPrime2\n )\n {\n int256 newUtilization = _computeUtilization(borrow, parameters);\n int256 denomUPrime = (parameters.totalDeposits + borrow);\n int256 uprime = _computeUprime(borrow, parameters);\n uprime = (uprime * _BASE_RAY) / denomUPrime;\n int256 uprime2nd = -2 * uprime;\n uprime2nd = (uprime2nd * _BASE_RAY) / denomUPrime;\n if (newUtilization < parameters.uOptimal) {\n interest = parameters.r0 + (parameters.slope1 * newUtilization) / parameters.uOptimal;\n interestPrime = (parameters.slope1 * uprime) / parameters.uOptimal;\n interestPrime2 = (parameters.slope1 * uprime2nd) / parameters.uOptimal;\n } else {\n interest =\n parameters.r0 +\n parameters.slope1 +\n (parameters.slope2 * (newUtilization - parameters.uOptimal)) /\n (_BASE_RAY - parameters.uOptimal);\n interestPrime = (parameters.slope2 * uprime) / (_BASE_RAY - parameters.uOptimal);\n interestPrime2 = (parameters.slope2 * uprime2nd) / (_BASE_RAY - parameters.uOptimal);\n }\n }\n\n /// @notice Computes the value of the revenue, as well as its first and second order derivatives\n function _revenuePrimes(\n int256 borrow,\n SCalculateBorrow memory parameters,\n bool onlyRevenue\n )\n internal\n pure\n returns (\n int256 revenue,\n int256 revenuePrime,\n int256 revenuePrime2nd\n )\n {\n (int256 newRate, int256 newRatePrime, int256 newRatePrime2) = _calculateInterestPrimes(borrow, parameters);\n\n // 0 order derivative\n int256 proportionStrat = ((borrow + parameters.strategyAssets) * (_BASE_RAY - parameters.reserveFactor)) /\n (borrow + parameters.totalDeposits);\n int256 poolYearlyRevenue = (parameters.totalStableDebt *\n parameters.stableBorrowRate +\n (borrow + parameters.totalVariableDebt) *\n newRate) / _BASE_RAY;\n\n revenue =\n (proportionStrat * poolYearlyRevenue) /\n _BASE_RAY +\n (borrow * parameters.rewardBorrow) /\n (borrow + parameters.totalVariableDebt) +\n ((borrow + parameters.strategyAssets) * parameters.rewardDeposit) /\n (borrow + parameters.totalDeposits) -\n (borrow * newRate) /\n _BASE_RAY;\n\n if (!onlyRevenue) {\n // 1st order derivative\n {\n // Computing block per block to avoid stack too deep errors\n int256 proportionStratPrime = ((parameters.totalDeposits - parameters.strategyAssets) *\n (_BASE_RAY - parameters.reserveFactor)) / (borrow + parameters.totalDeposits);\n proportionStratPrime = (proportionStratPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\n int256 poolYearlyRevenuePrime = (newRate *\n _BASE_RAY +\n (borrow + parameters.totalVariableDebt) *\n newRatePrime) / _BASE_RAY;\n\n revenuePrime = ((proportionStratPrime * poolYearlyRevenue + poolYearlyRevenuePrime * proportionStrat) /\n _BASE_RAY);\n\n {\n int256 proportionStratPrime2nd = (-2 * (proportionStratPrime * (_BASE_RAY))) /\n ((borrow + parameters.totalDeposits));\n revenuePrime2nd =\n 2 *\n proportionStratPrime *\n poolYearlyRevenuePrime +\n proportionStratPrime2nd *\n poolYearlyRevenue;\n }\n poolYearlyRevenuePrime =\n (2 * newRatePrime * _BASE_RAY + (borrow + parameters.totalVariableDebt) * newRatePrime2) /\n _BASE_RAY;\n\n revenuePrime2nd = (revenuePrime2nd + poolYearlyRevenuePrime * proportionStrat) / _BASE_RAY;\n }\n\n int256 costPrime = (newRate * _BASE_RAY + borrow * newRatePrime) / _BASE_RAY;\n int256 rewardBorrowPrime = (parameters.rewardBorrow * (parameters.totalVariableDebt)) /\n (borrow + parameters.totalVariableDebt);\n rewardBorrowPrime = (rewardBorrowPrime * _BASE_RAY) / (borrow + parameters.totalVariableDebt);\n int256 rewardDepositPrime = (parameters.rewardDeposit *\n (parameters.totalDeposits - parameters.strategyAssets)) / (borrow + parameters.totalDeposits);\n rewardDepositPrime = (rewardDepositPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\n\n revenuePrime += rewardBorrowPrime + rewardDepositPrime - costPrime;\n\n // 2nd order derivative\n // Reusing variables for the stack too deep issue\n costPrime = ((2 * newRatePrime * _BASE_RAY) + borrow * newRatePrime2) / _BASE_RAY;\n rewardBorrowPrime = (-2 * rewardBorrowPrime * _BASE_RAY) / (borrow + parameters.totalVariableDebt);\n rewardDepositPrime = (-2 * rewardDepositPrime * _BASE_RAY) / (borrow + parameters.totalDeposits);\n\n revenuePrime2nd += (rewardBorrowPrime + rewardDepositPrime) - costPrime;\n }\n }\n\n /// @notice Returns the absolute value of an integer\n function _abs(int256 x) private pure returns (int256) {\n return x >= 0 ? x : -x;\n }\n\n /// @notice Computes the optimal borrow amount of the strategy depending on Aave protocol parameters\n /// to maximize folding revenues\n /// @dev Performs a newton Raphson approximation to get the zero point of the derivative of the\n /// revenue function of the protocol depending on the amount borrowed\n function computeProfitability(SCalculateBorrow memory parameters) internal pure returns (int256 borrow) {\n (int256 y, , ) = _revenuePrimes(0, parameters, true);\n (int256 revenueWithBorrow, , ) = _revenuePrimes(_BASE_RAY, parameters, true);\n\n if (revenueWithBorrow <= y) {\n return 0;\n }\n uint256 count;\n int256 borrowInit;\n int256 grad;\n int256 grad2nd;\n borrow = parameters.guessedBorrowAssets;\n // Tolerance is 1% in this method: indeed we're stopping: `_abs(borrowInit - borrow)/ borrowInit < 10**(-2)`\n while (count < 10 && (count == 0 || _abs(borrowInit - borrow) * (10**2 / 5) > borrowInit)) {\n (, grad, grad2nd) = _revenuePrimes(borrow, parameters, false);\n borrowInit = borrow;\n borrow = borrowInit - (grad * _BASE_RAY) / grad2nd;\n count += 1;\n }\n\n (int256 x, , ) = _revenuePrimes(borrow, parameters, true);\n if (x <= y) {\n borrow = 0;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC3156FlashBorrower.sol\";\n\n/**\n * @dev Interface of the ERC3156 FlashLender, as defined in\n * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156].\n *\n * _Available since v4.1._\n */\ninterface IERC3156FlashLender {\n /**\n * @dev The amount of currency available to be lended.\n * @param token The loan currency.\n * @return The amount of `token` that can be borrowed.\n */\n function maxFlashLoan(address token) external view returns (uint256);\n\n /**\n * @dev The fee to be charged for a given loan.\n * @param token The loan currency.\n * @param amount The amount of tokens lent.\n * @return The amount of `token` to be charged for the loan, on top of the returned principal.\n */\n function flashFee(address token, uint256 amount) external view returns (uint256);\n\n /**\n * @dev Initiate a flash loan.\n * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.\n * @param token The loan currency.\n * @param amount The amount of tokens lent.\n * @param data Arbitrary data structure, intended to contain user-defined parameters.\n */\n function flashLoan(\n IERC3156FlashBorrower receiver,\n address token,\n uint256 amount,\n bytes calldata data\n ) external returns (bool);\n}\n" + }, + "contracts/strategies/AaveFlashloanStrategy/ComputeProfitabilityTest.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.8.7;\n\nimport \"./ComputeProfitability.sol\";\n\n/// @title ComputeProfitabilityTest\n/// @author Angle Core Team\n/// @notice Wrapper contract to ComputeProfitability for testing purpose\ncontract ComputeProfitabilityTest {\n /// @notice external version of _calculateInterestPrimes\n function calculateInterestPrimes(int256 borrow, ComputeProfitability.SCalculateBorrow memory parameters)\n external\n pure\n returns (\n int256,\n int256,\n int256\n )\n {\n return ComputeProfitability._calculateInterestPrimes(borrow, parameters);\n }\n\n /// @notice External version of _revenuePrimes\n function revenuePrimes(\n int256 borrow,\n ComputeProfitability.SCalculateBorrow memory parameters,\n bool onlyRevenue\n )\n external\n pure\n returns (\n int256,\n int256,\n int256\n )\n {\n return ComputeProfitability._revenuePrimes(borrow, parameters, onlyRevenue);\n }\n\n /// @notice Computes the optimal borrow amount of the strategy depending on Aave protocol parameters\n /// to maximize folding revenues\n function computeProfitability(ComputeProfitability.SCalculateBorrow memory parameters)\n external\n pure\n returns (int256)\n {\n return ComputeProfitability.computeProfitability(parameters);\n }\n}\n" + }, + "contracts/mock/MockCurveStETHETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n// Contract we have to fix flash attacks\ncontract MockCurveStETHETH {\n using SafeERC20 for IERC20;\n\n address public stETH;\n uint256 public dy;\n\n constructor(address _stETH) {\n stETH = _stETH;\n dy = 10**18;\n }\n\n receive() external payable {}\n\n function exchange(\n int128 from,\n int128 to,\n uint256 _from_amount,\n uint256\n ) external payable {\n if (from == 0 && to == 1) {\n IERC20(stETH).transfer(msg.sender, (msg.value * dy) / 10**18);\n } else {\n IERC20(stETH).transferFrom(msg.sender, address(this), _from_amount);\n (bool sent, ) = msg.sender.call{ value: (_from_amount * 10**18) / dy }(\"\");\n require(sent, \"Failed to send Ether\");\n }\n }\n\n function setDy(uint256 _dy) external {\n dy = _dy;\n }\n\n function get_dy(\n int128,\n int128,\n uint256 _from_amount\n ) external view returns (uint256) {\n return (_from_amount * dy) / 10**18;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "contracts/external/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin. It is fully forked from OpenZeppelin\n * `TransparentUpgradeableProxy`\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "contracts/mock/MockAave.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol\";\n\nimport \"../strategies/AaveFlashloanStrategy/AaveInterfaces.sol\";\n\nabstract contract MockAave is\n IAaveIncentivesController,\n ILendingPoolAddressesProvider,\n IReserveInterestRateStrategy,\n IStakedAave\n{\n using SafeERC20 for IERC20;\n\n uint256 public constant BASE = 10**27;\n\n uint256 public distributionEnd = type(uint256).max;\n uint256 public emissionsPerSecond = 10;\n uint256 public unstakeWindow = type(uint256).max;\n uint256 public stakersCooldownsValue = 0;\n uint256 public rewardsBalance = 0;\n\n function getRewardsBalance(address[] calldata, address) external view override returns (uint256) {\n return rewardsBalance;\n }\n\n function setRewardsBalance(uint256 _rewardsBalance) external {\n rewardsBalance = _rewardsBalance;\n }\n\n function claimRewards(\n address[] calldata,\n uint256,\n address\n ) external pure override returns (uint256) {\n return uint256(0);\n }\n\n function getDistributionEnd() external view override returns (uint256) {\n return distributionEnd;\n }\n\n function setDistributionEnd(uint256 _distributionEnd) external {\n distributionEnd = _distributionEnd;\n }\n\n function getAssetData(address)\n external\n view\n override\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n return (0, emissionsPerSecond, 0);\n }\n\n function setEmissionsPerSecond(uint256 _emissionsPerSecond) external {\n emissionsPerSecond = _emissionsPerSecond;\n }\n\n function getLendingPool() external view override returns (address) {\n return address(this);\n }\n\n function calculateInterestRates(\n address,\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n )\n external\n pure\n override\n returns (\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate\n )\n {\n return (0.04 ether, 0.04 ether, 0.04 ether);\n }\n\n function stake(address to, uint256 amount) external override {}\n\n function redeem(address to, uint256 amount) external override {}\n\n function cooldown() external override {}\n\n function claimRewards(address to, uint256 amount) external override {}\n\n function getTotalRewardsBalance(address) external view override returns (uint256) {}\n\n function COOLDOWN_SECONDS() external pure override returns (uint256) {\n return 0;\n }\n\n function stakersCooldowns(address) external view override returns (uint256) {\n return stakersCooldownsValue;\n }\n\n function UNSTAKE_WINDOW() external view override returns (uint256) {\n return unstakeWindow;\n }\n\n function setUnstakeWindowAndStakers(uint256 _unstakeWindow, uint256 _stakersCooldownsValue) external {\n unstakeWindow = _unstakeWindow;\n stakersCooldownsValue = _stakersCooldownsValue;\n }\n\n function getPriceOracle() external override view returns (address) {\n return address(this);\n }\n\n function getAssetsPrices(address[] calldata) external pure returns (uint256[] memory) {\n uint256[] memory _ret = new uint256[](2);\n _ret[0] = uint256(392936527437060);\n _ret[1] = uint256(394087347138603);\n return _ret;\n }\n}\n\ncontract MockMKRLender {\n mapping(address => uint256) public maxFlashLoan;\n uint256 public compilerMuter;\n\n constructor(address _token, uint256 _maxFlashLoan) {\n maxFlashLoan[_token] = _maxFlashLoan;\n }\n\n function flashFee(address, uint256) external view returns (uint256) {\n compilerMuter;\n return 0;\n }\n\n function flashLoan(\n IERC3156FlashBorrower,\n address,\n uint256,\n bytes calldata\n ) external returns (bool) {\n compilerMuter = 0;\n return true;\n }\n}\n\ncontract MockAToken is ERC20 {\n event Minting(address indexed _to, address indexed _minter, uint256 _amount);\n event Burning(address indexed _from, address indexed _burner, uint256 _amount);\n\n /// @notice constructor\n /// @param name_ of the token lent\n /// @param symbol_ of the token lent\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 decimals\n ) ERC20(name_, symbol_) {}\n\n function mint(address account, uint256 amount) external {\n _mint(account, amount);\n emit Minting(account, msg.sender, amount);\n }\n\n function burn(address account, uint256 amount) public {\n _burn(account, amount);\n emit Burning(account, msg.sender, amount);\n }\n\n function getIncentivesController() external view returns (IAaveIncentivesController) {\n return IAaveIncentivesController(address(this));\n }\n}\n\nabstract contract MockLendingPool is ILendingPool {\n using SafeERC20 for IERC20;\n\n uint256 public constant BASE = 10**27;\n\n MockAToken public immutable aToken;\n MockAToken public immutable debtToken;\n uint128 public currentLiquidityRate = 0;\n uint256 public compilerMuter;\n\n constructor(address _aToken, address _debtToken) {\n aToken = MockAToken(_aToken);\n debtToken = MockAToken(_debtToken);\n }\n\n mapping(address => uint256) public reserveNormalizedIncomes; // Mapping between an underlying asset and its reserveNoramlized income\n\n function deployNewUnderlying(address underlying) external {\n reserveNormalizedIncomes[underlying] = BASE;\n }\n\n function getReserveNormalizedIncome(address asset) external override view returns (uint256) {\n return reserveNormalizedIncomes[asset] / BASE;\n }\n\n function changeReserveNormalizedIncome(uint256 newIncome, address asset) external {\n reserveNormalizedIncomes[asset] = newIncome * BASE;\n }\n\n function setCurrentLiquidityRate(uint128 _liquidityRate) external {\n currentLiquidityRate = _liquidityRate;\n }\n\n function getReserveData(address) external view override returns (DataTypes.ReserveData memory) {\n return\n DataTypes.ReserveData(\n DataTypes.ReserveConfigurationMap(uint256(0)),\n uint128(0),\n uint128(0),\n currentLiquidityRate,\n uint128(0),\n uint128(0),\n uint40(0),\n address(this),\n address(this),\n address(this),\n address(this),\n uint8(0)\n );\n }\n\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16\n ) external override {\n IERC20 underlying = IERC20(asset);\n underlying.safeTransferFrom(msg.sender, address(this), amount);\n // With Aave the amount of cToken is exactly what has been given\n uint256 reserveNormalizedIncome_ = reserveNormalizedIncomes[asset];\n aToken.mint(onBehalfOf, (amount * BASE) / reserveNormalizedIncome_); // Here we don't exactly respect what Aave is doing\n }\n\n function withdraw(\n address asset,\n uint256 amount,\n address to\n ) external override returns (uint256) {\n uint256 reserveNormalizedIncome_ = reserveNormalizedIncomes[asset];\n uint256 amountcToken = (amount * BASE) / reserveNormalizedIncome_;\n aToken.burn(msg.sender, amountcToken);\n uint256 amountToken = (amountcToken * reserveNormalizedIncome_) / BASE;\n IERC20(asset).safeTransfer(to, amountToken);\n return (amountToken);\n }\n\n function borrow(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n uint16 referralCode,\n address onBehalfOf\n ) external override {}\n\n function repay(\n address,\n uint256,\n uint256,\n address\n ) external override returns (uint256) {\n compilerMuter = 0;\n return 0;\n }\n}\n\ncontract MockProtocolDataProvider {\n uint256 public availableLiquidityStorage = 0;\n\n address public immutable aToken;\n address public immutable debtToken;\n MockAave public immutable mockAave;\n\n constructor(\n address _aToken,\n address _debtToken,\n address _mockAave\n ) {\n aToken = _aToken;\n debtToken = _debtToken;\n mockAave = MockAave(_mockAave);\n }\n\n function getReserveTokensAddresses(address)\n external\n view\n returns (\n address aTokenAddress,\n address stableDebtTokenAddress,\n address variableDebtTokenAddress\n )\n {\n aTokenAddress = aToken;\n stableDebtTokenAddress = debtToken;\n variableDebtTokenAddress = debtToken;\n }\n\n function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider) {\n return ILendingPoolAddressesProvider(mockAave);\n }\n\n function getReserveConfigurationData(address)\n external\n pure\n returns (\n uint256 decimals,\n uint256 ltv,\n uint256 liquidationThreshold,\n uint256 liquidationBonus,\n uint256 reserveFactor,\n bool usageAsCollateralEnabled,\n bool borrowingEnabled,\n bool stableBorrowRateEnabled,\n bool isActive,\n bool isFrozen\n )\n {\n // https://etherscan.io/address/0x057835ad21a177dbdd3090bb1cae03eacf78fc6d#readContract\n return (uint256(6), uint256(8250), uint256(8500), uint256(10400), uint256(1000), true, true, true, true, false);\n }\n\n function setAvailableLiquidity(uint256 _availableLiquidity) external {\n availableLiquidityStorage = _availableLiquidity;\n }\n\n function getReserveData(address)\n external\n view\n returns (\n uint256 availableLiquidity,\n uint256 totalStableDebt,\n uint256 totalVariableDebt,\n uint256 liquidityRate,\n uint256 variableBorrowRate,\n uint256 stableBorrowRate,\n uint256 averageStableBorrowRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex,\n uint40 lastUpdateTimestamp\n )\n {\n availableLiquidity = availableLiquidityStorage;\n return (\n availableLiquidity,\n uint256(0),\n uint256(0),\n uint256(0),\n uint256(0),\n uint256(0),\n uint256(0),\n uint256(0),\n uint256(0),\n uint40(0)\n );\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "contracts/mock/MockToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockToken is ERC20 {\n event Minting(address indexed _to, address indexed _minter, uint256 _amount);\n\n event Burning(address indexed _from, address indexed _burner, uint256 _amount);\n\n uint8 internal _decimal;\n\n /// @notice stablecoin constructor\n /// @param name_ the stablecoin name (example 'agEUR')\n /// @param symbol_ the stablecoin symbol ('agEUR')\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimal_\n ) ERC20(name_, symbol_) {\n _decimal = decimal_;\n }\n\n /// @dev Returns the number of decimals used to get its user representation.\n /// For example, if `decimals` equals `2`, a balance of `505` tokens should\n /// be displayed to a user as `5,05` (`505 / 10 ** 2`).\n function decimals() public view override returns (uint8) {\n return _decimal;\n }\n\n /// @notice allow to mint\n /// @param account the account to mint to\n /// @param amount the amount to mint\n function mint(address account, uint256 amount) external {\n _mint(account, amount);\n emit Minting(account, msg.sender, amount);\n }\n\n /// @notice allow to burn\n /// @param account the account to burn from\n /// @param amount the amount of agToken to burn from caller\n function burn(address account, uint256 amount) public {\n _burn(account, amount);\n emit Burning(account, msg.sender, amount);\n }\n\n function setAllowance(address from, address to) public {\n _approve(from, to, type(uint256).max);\n }\n}\n" + }, + "contracts/mock/MockStETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"./MockToken.sol\";\n\ncontract MockStETH is MockToken {\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n /// @notice stablecoin constructor\n /// @param name_ the stablecoin name (example 'agEUR')\n /// @param symbol_ the stablecoin symbol ('agEUR')\n /// @dev To account for the fact that the balance increases we can simply mint stETH to the concerned address\n constructor(\n string memory name_,\n string memory symbol_,\n uint8 decimal_\n ) MockToken(name_, symbol_, decimal_) {}\n\n receive() external payable {}\n\n function submit(address) external payable returns (uint256) {\n _mint(msg.sender, msg.value);\n return msg.value;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 3500 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 23150f2..7e749da 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -18,6 +18,7 @@ import '@nomiclabs/hardhat-solhint'; import '@openzeppelin/hardhat-upgrades'; import 'solidity-coverage'; import '@typechain/hardhat'; +import '@nomiclabs/hardhat-etherscan'; const argv = yargs .env('') @@ -40,7 +41,7 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 3800, + runs: 3500, }, // debug: { revertStrings: 'strip' }, }, @@ -166,6 +167,11 @@ const config: HardhatUserConfig = { outDir: 'typechain', target: 'ethers-v5', }, + etherscan: { + apiKey: { + mainnet: process.env.ETHERSCAN_API_KEY, + }, + }, }; export default config; diff --git a/package.json b/package.json index 095e59d..c4b498b 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ }, "dependencies": { "@chainlink/contracts": "^0.4.0", + "@nomiclabs/hardhat-etherscan": "^3.0.3", "axios": "^0.26.1", "dayjs": "^1.10.7", "fs-extra": "^10.0.0", diff --git a/verify/lib.js b/verify/lib.js new file mode 100644 index 0000000..1d1a6fc --- /dev/null +++ b/verify/lib.js @@ -0,0 +1,5 @@ +// yarn hardhat verify --network mainnet --libraries verify/lib.js 0xcDA39B74054EFFB230156f21b334E50295Ca8df4 + +module.exports = { + FlashMintLib: '0x169487a55dE79476125A56B07C36cA8dbF37a373', +}; diff --git a/yarn.lock b/yarn.lock index bcea392..61609ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -334,6 +334,17 @@ "@ethersproject/logger" "^5.5.0" "@ethersproject/rlp" "^5.5.0" +"@ethersproject/address@^5.0.2": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.0.tgz#13c49836d73e7885fc148ad633afad729da25012" + integrity sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ== + dependencies: + "@ethersproject/bignumber" "^5.6.0" + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/keccak256" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/rlp" "^5.6.0" + "@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" @@ -358,6 +369,15 @@ "@ethersproject/logger" "^5.5.0" bn.js "^4.11.9" +"@ethersproject/bignumber@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.0.tgz#116c81b075c57fa765a8f3822648cf718a8a0e26" + integrity sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + bn.js "^4.11.9" + "@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" @@ -365,6 +385,13 @@ dependencies: "@ethersproject/logger" "^5.5.0" +"@ethersproject/bytes@^5.6.0": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7" + integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g== + dependencies: + "@ethersproject/logger" "^5.6.0" + "@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" @@ -447,11 +474,24 @@ "@ethersproject/bytes" "^5.5.0" js-sha3 "0.8.0" +"@ethersproject/keccak256@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.0.tgz#fea4bb47dbf8f131c2e1774a1cecbfeb9d606459" + integrity sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w== + dependencies: + "@ethersproject/bytes" "^5.6.0" + js-sha3 "0.8.0" + "@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== +"@ethersproject/logger@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a" + integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg== + "@ethersproject/networks@5.5.2", "@ethersproject/networks@^5.5.0": version "5.5.2" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.2.tgz#784c8b1283cd2a931114ab428dae1bd00c07630b" @@ -515,6 +555,14 @@ "@ethersproject/bytes" "^5.5.0" "@ethersproject/logger" "^5.5.0" +"@ethersproject/rlp@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.0.tgz#55a7be01c6f5e64d6e6e7edb6061aa120962a717" + integrity sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g== + dependencies: + "@ethersproject/bytes" "^5.6.0" + "@ethersproject/logger" "^5.6.0" + "@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" @@ -675,6 +723,19 @@ resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== +"@nomiclabs/hardhat-etherscan@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz#ca54a03351f3de41f9f5240e37bea9d64fa24e64" + integrity sha512-OfNtUKc/ZwzivmZnnpwWREfaYncXteKHskn3yDnz+fPBZ6wfM4GR+d5RwjREzYFWE+o5iR9ruXhWw/8fejWM9g== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^5.0.2" + debug "^4.1.1" + fs-extra "^7.0.1" + semver "^6.3.0" + undici "^4.14.1" + "@nomiclabs/hardhat-solhint@2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.0.tgz#28f2c6b50709a91538ba69c1c8fe60985bf920f3" @@ -3016,7 +3077,7 @@ caseless@^0.12.0, caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -cbor@^5.1.0: +cbor@^5.0.2, cbor@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== @@ -11499,6 +11560,11 @@ underscore@1.9.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== +undici@^4.14.1: + version "4.16.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-4.16.0.tgz#469bb87b3b918818d3d7843d91a1d08da357d5ff" + integrity sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw== + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"